gpt4 book ai didi

java - JPA 与 Hibernate - 对象 'get' 方法返回一对一关系的不同版本

转载 作者:行者123 更新时间:2023-12-02 04:23:40 25 4
gpt4 key购买 nike

我有一个与 AuthorizationToken 对象具有一对一关系的 User 对象。这个项目的基础可以参见here

当用户登录时,通过持久保存与用户一对一链接的授权 token (具有指定的到期时间)来创建新 session 。出于开发目的,此到期时间设置为 1 个月,这在我的脑海中。现在我的 token 已经开始过期,系统遇到错误。

用户登录时调用以下方法:

public AuthorizationToken createAuthorizationToken(User user) {
if(user.getAuthorizationToken() == null || user.getAuthorizationToken().hasExpired()) {
LOG.debug("UserToken has expired or is null, creating new token");
user.setAuthorizationToken(new AuthorizationToken(user, applicationConfig.getAuthorizationExpiryTimeInSeconds()));
userRepository.save(user);
}
return user.getAuthorizationToken();
}

这将返回当前 token ,如果 token 为空或过期,则返回一个新 token 。如果为空或过期,连接到用户的 token 也会被替换(setAuthorizationToken 方法)。这有效,我的新 token 在数据库中创建并返回给客户端。

然后,我们使用该 token 为每个后续请求创建请求签名。服务器接收签名,使用存储的 token 进行复制并检查它们是否相同以识别发送者。

问题就出在这里,下面是在服务器中创建签名的方法:

private boolean isAuthorized(User user, AuthorizationRequestContext authorizationRequest, String hashedToken) {
String unEncodedString = composeUnEncodedRequest(authorizationRequest);
AuthorizationToken authorizationToken = user.getAuthorizationToken();
String userTokenHash = encodeAuthToken(authorizationToken.getToken(), unEncodedString);
if (hashedToken.equals(userTokenHash)) {
return true;
}
return false;
}

我使用与原始登录过程中使用的相同的 user.getAuthorizationToken() 方法,但它产生两个不同的值。登录方法返回新创建的 token ,签名服务返回数据库中与该用户相关的第一个实例(该实例现已过期,不应再映射到用户对象)。这里出了什么问题?难道只是清理过期的 token 以使它们不被混淆吗?我确信这是一个更深层次的问题,因为用户一次只能有一个身份验证 token 映射。

对代码的任何评论表示赞赏。

最佳答案

这就是我认为正在发生的事情。

查看源代码,在 AuthorizationToken 中,您有一个到 User 的映射(这是关系的拥有方)

@JoinColumn(name = "user_id")
@OneToOne(fetch = FetchType.LAZY)
private User user;

User中,你有这种关系的另一面

@OneToOne(fetch = FetchType.LAZY,
mappedBy = "user",
cascade = CascadeType.ALL)
private AuthorizationToken authorizationToken;

当您在 createAuthorizationToken() 中创建新 token 时,您只需将该新 token 设置到 user 中并保存对用户的更改。您没有在旧 token 上设置 null 用户。之后,由于 AuthorizationToken 拥有该关系(外键位于其表中),因此您最终会在 rest_authorization_token 表中得到两行,它们都具有 user_id 指向您的用户。这意味着随用户返回的 token 是数据库作为第一个返回的 token ,该 token 在调用之间可能有所不同,导致您在不同的方法中看到不同的 token 实例。

解决方案是将旧 token 设置为 null 或完全删除旧 token 。这是一个 @OneToOne 关系,您应该对 rest_authorization_token.user_id 有一个唯一的约束。像这样的事情

public AuthorizationToken createAuthorizationToken(User user) {
if(user.getAuthorizationToken() == null) {
LOG.debug("UserToken is null, creating new token");
user.setAuthorizationToken(new AuthorizationToken(user, applicationConfig.getAuthorizationExpiryTimeInSeconds()));
userRepository.save(user);
} else if (user.getAuthorizationToken().hasExpired()) {
LOG.debug("UserToken has expired, creating new token");
AuthorizationToken oldToken = user.getAuthorizationToken();
oldToken.setUser(null);
tokenRepository.update(oldToken);
user.setAuthorizationToken(new AuthorizationToken(user, applicationConfig.getAuthorizationExpiryTimeInSeconds()));
userRepository.save(user);
}
return user.getAuthorizationToken();
}

关于java - JPA 与 Hibernate - 对象 'get' 方法返回一对一关系的不同版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32461860/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com