上次寫了用戶注冊接口的實現(xiàn),接著寫登錄接口
傳統(tǒng)的登錄驗證方式是 session + cookie 的形式,這種驗證方式不太適用于只提供 restful api 的后端系統(tǒng),所以選擇了 基于 token 的驗證方式。
token 是個長字符串,客戶端向服務器申請。在需要登錄的請求中每次都攜帶上申請到的token,服務器端驗證 token 的有效性,只有驗證通過了才允許訪問。具體怎么驗證 token 下次再寫,先來看看怎么生成 token。
我使用了JWT 形式的 token, 關(guān)于 JWT(JSON Web Token),可以看看下面兩篇文章
對比上次的目錄結(jié)構(gòu),多了 AuthenticationApi.java 和 AuthenticationService.java 兩個文件

目錄結(jié)構(gòu)
添加 JWT 依賴
jwt 的 java 實現(xiàn)由很多,經(jīng)過對比,選擇了下面這個。 在 pom.xml 中添加
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.0.2</version>
</dependency>
Controller 層
新建 AuthenticationApi.java 文件
@RestController
@RequestMapping("/api/authentication")
public class AuthenticationApi {
private AuthenticationService authenticationService;
private UserService userService;
@Autowired
public AuthenticationApi(AuthenticationService authenticationService, UserService userService) {
this.authenticationService = authenticationService;
this.userService = userService;
}
@PostMapping("")
public Object login(@RequestBody User user) {
User userInDataBase = userService.findByName(user.getName());
JSONObject jsonObject = new JSONObject();
if (userInDataBase == null) {
jsonObject.put("message", "用戶不存在");
} else if (!userService.comparePassword(user, userInDataBase)) {
jsonObject.put("message", "密碼不正確");
} else {
String token = authenticationService.getToken(userInDataBase);
jsonObject.put("token", token);
jsonObject.put("user", userInDataBase);
}
return jsonObject;
}
}
Service 層
新建 AuthenticationService.java
@Service
public class AuthenticationService {
public String getToken(User user) {
String token = "";
try {
token = JWT.create()
.withAudience(user.getId().toString()) // 將 user id 保存到 token 里面
.sign(Algorithm.HMAC256(user.getPassword())); // 以 password 作為 token 的密鑰
} catch (UnsupportedEncodingException ignore) {
}
return token;
}
}
添加 comparePassword 方法
編輯 UserService.java,添加
public boolean comparePassword(User user, User userInDataBase) {
return passwordToHash(user.getPassword()) // 將用戶提交的密碼轉(zhuǎn)換為 hash
.equals(userInDataBase.getPassword()); // 數(shù)據(jù)庫中的 password 已經(jīng)是 hash,不用轉(zhuǎn)換
}
測試
為了方便,使用 postman 這個程序來測試。
-
先添加一個用戶
添加用戶
從返回的 Body 那里,可以看到創(chuàng)建用戶成功。
-
正常登陸
登陸成功 -
用戶不存在時
用戶不存在 -
密碼錯誤時
密碼錯誤
查看項目完整代碼
項目地址: https://github.com/hyrijk/spring-boot-blog
克隆項目到本地
git clone https://github.com/hyrijk/spring-boot-blog.git
checkout 到當前版本
git checkout 201c830d765d00014394563169b21bc1eb6c2a37
完。



