英文:
DynamoDBMappingException: no RANGE key value present
问题
我对NoSQL
和Amazon DynamoDB
还不太了解。我正在尝试首先通过username
从DynamoDB
的UserMaster
表中检索用户。
我有一个名为UserMaster
的表,具有5个属性(username
,correct-hash
,email
,lastLogin
,role
),每个属性的类型都是String
,我有一个相应的UsermasterBean
映射到表UserMaster
。UserMaster
表的分区键(哈希键)是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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论