DynamoDBMappingException: 没有范围键值存在

huangapple go评论87阅读模式
英文:

DynamoDBMappingException: no RANGE key value present

问题

我对NoSQLAmazon DynamoDB还不太了解。我正在尝试首先通过usernameDynamoDBUserMaster表中检索用户。

我有一个名为UserMaster的表,具有5个属性(usernamecorrect-hashemaillastLoginrole),每个属性的类型都是String,我有一个相应的UsermasterBean映射到表UserMasterUserMaster表的分区键(哈希键)是username,而排序键(范围键)是correct-hash

UsermasterBean

@DynamoDBTable(tableName = "UserMaster")
public class UsermasterBean {
    
    private String username;
    private String correctHash;
    private String email;
    private String lastLogin;
    private String role;
    
    @DynamoDBHashKey(attributeName = "username")
    @DynamoDBAttribute(attributeName = "username")
    public String getUsername() {
        return username;
    }
    
    @DynamoDBRangeKey(attributeName = "correct-hash")
    @DynamoDBAttribute(attributeName = "correct-hash")
    public String getCorrectHash() {
        return correctHash;
    }
    
    @DynamoDBAttribute(attributeName = "email")
    public String getEmail() {
        return email;
    }
    
    @DynamoDBAttribute(attributeName = "last-login")
    public String getLastLogin() {
        return lastLogin;
    }
    
    @DynamoDBAttribute(attributeName = "role")
    public String getRole() {
        return role;
    }
    
    public void setUsername(String username) {
        this.username = username;
    }
    // ...
    // ...
}

从用户界面检索数据:

UsermasterBean usermasterBean = new UsermasterBean();
UsermasterDao usermasterDao = new UsermasterDao();

usermasterBean.setUsername(username.getValue()); // 从UI表单获取用户名
final String inputtedPassword = password.getValue(); // 从UI表单获取密码

UsermasterBean retrievedUserBean = usermasterDao.findByUsernameAndPassword(usermasterBean, inputtedPassword);

验证用户:

public UsermasterBean findByUsernameAndPassword(final UsermasterBean usermasterBean, final String inputtedPassword)
        throws IOException {
    AmazonDynamoDBClientHandler amazonDynamoDBClientHandler = AmazonDynamoDBClientHandler.getNewInstance();
    UsermasterBean retrievedUser;
    try {
        AmazonDynamoDB amazonDynamoDB = amazonDynamoDBClientHandler.createNewClient();
        DynamoDBMapper dynamoDBMapper = new DynamoDBMapper(amazonDynamoDB);
        retrievedUser = dynamoDBMapper.load(usermasterBean.getClass(), usermasterBean.getUsername());
        System.out.println("从数据库中检索到的正确哈希值:" + retrievedUser.getCorrectHash()); // 检查检索到的哈希值是否正确。

        // PasswordUtilityManager.verifyPassword(inputtedPassword,retrievedUser.getCorrectHash());
    } catch (IOException ioException) {
        throw ioException;
    } finally {
        amazonDynamoDBClientHandler.shutdownClient();
    }
    return retrievedUser;
}

问题:

retrievedUser = dynamoDBMapper.load(usermasterBean.getClass(), usermasterBean.getUsername()); 抛出 com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException 异常。

我期望 retrievedUser.getCorrectHash() 应该显示存储在数据库中的哈希密码作为一个String,以便我可以验证输入的密码是否生成与从数据库中检索到的哈希值相同的哈希。

英文:

I am new to NoSQL and Amazon Dynamo DB. I am trying to retreive a user by username first from a DynamoDB UserMaster table.

I have a table UserMaster with 5 attributes(username, correct-hash, email, lastLogin, role), each of type String and I have a corresponding UsermasterBean mapped to the table UserMaster. UserMaster table's Partition Key(Hashkey) is username and Sort key(Range Key) is correct-hash

UsermasterBean

    @DynamoDBTable(tableName = "UserMaster")
    public class UsermasterBean {
    
    private String username;
    private String correctHash;
    private String email;
    private String lastLogin;
    private String role;
    
    @DynamoDBHashKey(attributeName = "username")
    @DynamoDBAttribute(attributeName = "username")
    public String getUsername() {
    	return username;
    }
    
    @DynamoDBRangeKey(attributeName = "correct-hash")
    @DynamoDBAttribute(attributeName = "correct-hash")
    public String getCorrectHash() {
    	return correctHash;
    }
    
    @DynamoDBAttribute(attributeName = "email")
    public String getEmail() {
    	return email;
    }
    
    @DynamoDBAttribute(attributeName = "last-login")
    public String getLastLogin() {
    	return lastLogin;
    }
    
    @DynamoDBAttribute(attributeName = "role")
    public String getRole() {
    	return role;
    }
    
    public void setUsername(String username) {
        this.username = username;
    }
    ....
    ....
   }

Retrieve data from UI:

UsermasterBean usermasterBean = new UsermasterBean();
UsermasterDao usermasterDao = new UsermasterDao();

usermasterBean.setUsername(username.getValue()); // Get the username from UI form
final String inputtedPassword = password.getValue(); // Get the password from UI form

UsermasterBean retrievedUserBean = usermasterDao.findByUsernameAndPassword(usermasterBean,inputtedPassword);

Validate User:

public UsermasterBean findByUsernameAndPassword(final UsermasterBean usermasterBean, final String inputtedPassword)
			throws IOException {
		AmazonDynamoDBClientHandler amazonDynamoDBClientHandler = AmazonDynamoDBClientHandler.getNewInstance();
		UsermasterBean retrievedUser;
		try {
			AmazonDynamoDB amazonDynamoDB = amazonDynamoDBClientHandler.createNewClient();
			DynamoDBMapper dynamoDBMapper = new DynamoDBMapper(amazonDynamoDB);
			retrievedUser = dynamoDBMapper.load(usermasterBean.getClass(), usermasterBean.getUsername());
			System.out.println("RETRIEVED CORRECT-HASH FROM DATABASE: " + retrievedUser.getCorrectHash()); // Check if hash retrieved is correct for this user.

			// PasswordUtilityManager.verifyPassword(inputtedPassword,retrievedUser.getCorrectHash());
		} catch (IOException ioException) {
			throw ioException;
		} finally {
			amazonDynamoDBClientHandler.shutdownClient();
		}
		return retrievedUser;
}

Problem:

retrievedUser = dynamoDBMapper.load(usermasterBean.getClass(), usermasterBean.getUsername()); throws com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException

I am expecting retrievedUser.getCorrectHash() should display the hashed password stored in database as a String so that I can verify if the inputted password creates the same hash as retrieved from the database.

答案1

得分: 3

这个异常被抛出是因为 DynamoDBMapper 也期望传入范围键(因为你的 DynamoDB 表包含一个名为 correct-hash 的范围键)。

正确的函数调用应该如下:

retrievedUser = dynamoDBMapper.load(usermasterBean.getClass(), usermasterBean.getUsername(), usermasterBean.getCorrectHash());

由于这可能是用户密码的哈希值,你可以指定用户提供的密码的哈希副本。如果在 DynamoDB 中没有返回结果,则可以假设用户名或密码错误。

英文:

This exception is being throw because the DynamoDBMapper is expecting the range key to be passed in too (as your DynamoDB table contains a range key of correct-hash).

The correct function call should be as below

retrievedUser = dynamoDBMapper.load(usermasterBean.getClass(), usermasterBean.getUsername(), usermasterBean.getCorrectHash());

As this is presumably the hash for your users password, you can specify a hashed copy of the password provided by the user. If this returns no results in DynamoDB you can assume that either their username or password is incorrect.

答案2

得分: 1

根据您的数据模型,UserMaster 表中针对单个用户(username)可能会有多个条目,而这并不是您的意图。(为什么一个用户会有两个哈希密码?)

不要将 correctHash 建模为范围键(range key)。如果这样做,DynamoDB 将要求您在调用 load 时同时提供哈希键和范围键(否则您必须使用 query)。

详情请参阅:https://stackoverflow.com/questions/31850030/dynamodbmapper-load-vs-query

英文:

As per your data model, there can be more than one entry in the UserMaster table for a single user (username) which is not your intention. (Why would a user have two hashed passwords?)

Do not model correctHash as a range key. If you do, DynamoDB mandates you to provide both the hash and range key when calling load (else you have to query).

See: https://stackoverflow.com/questions/31850030/dynamodbmapper-load-vs-query

huangapple
  • 本文由 发表于 2020年7月25日 20:31:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/63088354.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定