上次寫(xiě)了用戶(hù)注冊(cè)接口的實(shí)現(xiàn)缤言,接著寫(xiě)登錄接口
傳統(tǒng)的登錄驗(yàn)證方式是 session + cookie 的形式,這種驗(yàn)證方式不太適用于只提供 restful api 的后端系統(tǒng)胆萧,所以選擇了 基于 token 的驗(yàn)證方式跌穗。
token 是個(gè)長(zhǎng)字符串,客戶(hù)端向服務(wù)器申請(qǐng)锈拨。在需要登錄的請(qǐng)求中每次都攜帶上申請(qǐng)到的token羹唠,服務(wù)器端驗(yàn)證 token 的有效性,只有驗(yàn)證通過(guò)了才允許訪問(wèn)缝彬。具體怎么驗(yàn)證 token 下次再寫(xiě),先來(lái)看看怎么生成 token杆怕。
我使用了JWT 形式的 token壳贪, 關(guān)于 JWT(JSON Web Token)违施,可以看看下面兩篇文章
對(duì)比上次的目錄結(jié)構(gòu)磕蒲,多了 AuthenticationApi.java 和 AuthenticationService.java 兩個(gè)文件
添加 JWT 依賴(lài)
jwt 的 java 實(shí)現(xiàn)由很多,經(jīng)過(guò)對(duì)比兔院,選擇了下面這個(gè)坊萝。 在 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", "用戶(hù)不存在");
} 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()) // 將用戶(hù)提交的密碼轉(zhuǎn)換為 hash
.equals(userInDataBase.getPassword()); // 數(shù)據(jù)庫(kù)中的 password 已經(jīng)是 hash惦积,不用轉(zhuǎn)換
}
測(cè)試
為了方便狮崩,使用 postman 這個(gè)程序來(lái)測(cè)試厉亏。
-
先添加一個(gè)用戶(hù)
添加用戶(hù)
從返回的 Body 那里烈和,可以看到創(chuàng)建用戶(hù)成功。
-
正常登陸
登陸成功 -
用戶(hù)不存在時(shí)
用戶(hù)不存在 -
密碼錯(cuò)誤時(shí)
密碼錯(cuò)誤
查看項(xiàng)目完整代碼
項(xiàng)目地址: https://github.com/hyrijk/spring-boot-blog
克隆項(xiàng)目到本地
git clone https://github.com/hyrijk/spring-boot-blog.git
checkout 到當(dāng)前版本
git checkout 201c830d765d00014394563169b21bc1eb6c2a37
完。