最近刚刚参与一个基于Play框架的管理平台的升级工作,其中涉及到了用户的验证工作。第一次接触play框架,直接看已有代码,有点晕。因此,自己实现了一个简单的用户验证功能。
首先,新建一个User类,包含两个属性,包含两个属性email和password。并在构造器中对密码进行了加密。
@Entity
public class User extends Model {
@Id
private String email;
private String password;
// Constructor
public User(String email, String password) {
String passwordHash = BCrypt.hashpw(password, BCrypt.gensalt());
this.email = email;
this.password = passwordHash;
}
}
接下来,新增控制器Application.java,其中主要包含包含两个动作和一个表单类Registration。一个动作register()用于显示注册页面,另一个动作postRegister处理表单提交的信息,
并增加相应的数据库记录。Registration则对应注册页面所显示的表格:
public class Application extends Controller { public static class Registration { @Email public String email; @Required public String password; } public static Result register() { Form<Registration> userForm = Form.form(Registration.class); return ok(views.html.register.render(userForm)); } public static Result postRegister() { Form<Registration> userForm = Form.form(Registration.class).bindFromRequest(); User user = new User(userForm.get().email, userForm.get().password); user.save(); return ok("registered"); } }
其后,新增Rigister所对应的前端页面,并在Routes文件中为Appication所对应的动作增加访问路径。
<!DOCTYPE html> <html> <body> <h1> Registration </h1> @helper.form(action = routes.Application.postRegister()) { @helper.inputText(userForm("email")) @helper.inputPassword(userForm("password")) <input type="submit"> } </body> </html>
Routes文件:
GET /register controllers.Application.register() POST /register controllers.Application.postRegister()
其后,访问页面,输入用户名和密码,可以看到数据库中新增了一条记录。
接下来,将用户验证的逻辑加入到User类中,修改User类,新增authenticate()方法。authenticate()接收的是明文密码。上面的验证中,首先检查用户邮箱是否存在。如果存在,则检查密码是否符合数据库的记录。
如果邮箱或者密码错误,将返回null。否则返回正确的用户对象。
// Query public static Model.Finder<Integer, User> find = new Model.Finder<>(Integer.class, User.class); // Authentification public static User authenticate(String email, String password) { User user = find.where() .eq("email", email) .findUnique(); if (user == null) { return user; } else if (BCrypt.checkpw(password, user.password)) { return user; } else { return null; } }
接下来,进一步修改Application控制器,增加两个动作和一个表单类。动作login()用于显示登录页面,动作postLogin()用于处理登录表单填写的信息,并根据信息决定是否登入用户。Login类对应登录页面的表单。
public static class Login { @Email public String email; @Required public String password; public String validate() { if (User.authenticate(email, password) == null) { return "Invalid user or password"; } return null; } } public static Result login() { Form<Login> userForm = Form.form(Login.class); return ok(views.html.login.render(userForm)); } public static Result postLogin() { Form<Login> userForm = Form.form(Login.class).bindFromRequest(); if (userForm.hasErrors()) { return badRequest("Wrong user/password"); } else { return ok("Valid user"); } }
其中,在静态类Login中,增加了validate()方法,并在其中调用User的验证逻辑。正如postLogin()中所示,表单的hasErrors()方法将自动检查validate()方法的返回值。如果validate()方法返回为null,
则说明表单无误。postLogin()的if结构,将根据登录是否合法,来返回不同的结果。
最后,同样的在Routes文件中新增两条对应的URL
GET /login controllers.Application.login() POST /login controllers.Application.postLogin()
其后,访问/login页面,并尝试登录。发现已增加了验证功能。