我正在编写一个简单的带有身份验证的游戏框架应用程序,其中密码使用 BCrypt 进行哈希处理。
简而言之,我的问题是:我观察到在 JPA 实体中,当您调用属性的 get 方法时,它的 set 方法也会以某种方式被调用。如果我在其中执行非幂等操作,这是一个问题设置方法。
我将在这里描述我的问题的简化示例
这是我的登录视图
@helper.form(routes.Application.authenticate) {
<h3>Login</h3>
<ul id="login_box">
<li>
<span class="loginbox_label">Username : </span>
<input type="text" class="login_input" id="usernm-input" name="email" value='@form("email").value' placeholder="Enter Username..." />
</li>
<li>
<span class="loginbox_label">Password : </span>
<input type="password" class="login_input" id="passwd-input" name="password" placeholder="Enter Password..." />
</li>
<li>
@if(form.hasGlobalErrors) {
<p class="error">
@form.globalError.message
</p>
}
</li>
</ul>
<hr />
<a href="#" onclick="javascript:window.location.href = '@routes.Application.forgotpwd()?usr='+$('#usernm-input').val()" class="forgotpwdlink">Retrieve Forgotten Password</a>
<input type="submit" class="alt_btn login_btn" value="Login" />
<hr />
}
在提交时,它进入身份验证功能
@play.db.jpa.Transactional
public static Result authenticate(){
Form<Login> loginForm = form(Login.class).bindFromRequest();
if(loginForm.hasErrors())
{
return badRequest(index.render(loginForm));
}
else
{
//Save Email to session
session("email", loginForm.get().email);
//Redirect to dashboard
return redirect(routes.Application.showDashboard());
}
}
这是我的登录类
public static class Login
{
public String email;
public String password;
public String validate()
{
User usr = User.findByEmail(email);
if(usr == null)
return MessageStrings.USER_NOT_FOUND; //User Not Found
if(usr.getPassword().equals(this.password))
{
return MessageStrings.NO_ERROR; //NO ERROR
}
else
{
return usr.getPassword();//MessageStrings.PASSWORD_MISMATCH; //Wrong Password
}
}
}
如您所见,我无处调用 usr.setPassword 方法。另外,我在 else 部分返回 usr.getPassword() 以返回它并在页面上显示它而不是错误消息。
最后,这是我的用户类,一个 JPA 实体
@Transient
@Constraints.Required
@Formats.NonEmpty
private String password;
@Access(AccessType.PROPERTY)
@Column(name = "password")
public String getPassword(){
return this.password;
}
public void setPassword(String password){
this.password = password + "1";//BCrypt.hashpw(password, BCrypt.gensalt());
}
链接到完整的 JPA 实体: http: //pastebin.com/HZDEyYHZ
我这里只添加了代码的相关部分。现在查看代码,您会发现每次提交表单时,它必须只返回存储的密码(因为我在 else 部分返回 usr.getPassword())。注意this.password = password + "1"; .
现在,如果我继续使用错误的密码提交..这就是我得到的
显然,每当我提交登录表单时,都会重复调用 setPassword
为什么会这样?
一个很长的帖子,我知道