最近剛剛參與一個基于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 {@Emailpublic String email;@Requiredpublic 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。否則返回正確的用戶對象。
// Querypublic static Model.Finder<Integer, User> find = new Model.Finder<>(Integer.class, User.class);// Authentificationpublic 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 {@Emailpublic String email;@Requiredpublic 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頁面,并嘗試登錄。發現已增加了驗證功能。