0

我正在编写一个简单的带有身份验证的游戏框架应用程序,其中密码使用 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

为什么会这样?

一个很长的帖子,我知道

4

1 回答 1

1

您明确地为您的实体选择了属性访问权限。这意味着调用 setter 来填充您的实体。但是您的二传手并不是真正的二传手。因此,将此方法重命名为其他名称,并添加一个真正的 setter,或者使用字段访问而不是属性访问。

恕我直言,散列密码不应该由实体完成,更不用说由设置者完成。预期的行为是 getter 应该返回由 setter 设置的值。

于 2013-01-31T18:29:32.180 回答