後端引入依賴:html
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.7.0</version> </dependency>
JWT工具類:前端
package com.tangzhe.util; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.util.Date; import io.jsonwebtoken.Claims; import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.SignatureException; /** * API調用認證工具類,採用RSA加密 */ public class JWTUtils { private static RSAPrivateKey priKey; private static RSAPublicKey pubKey; private static class SingletonHolder { private static final JWTUtils INSTANCE = new JWTUtils(); } public synchronized static JWTUtils getInstance(String modulus, String privateExponent, String publicExponent) { if (priKey == null && pubKey == null) { priKey = RSAUtils.getPrivateKey(modulus, privateExponent); pubKey = RSAUtils.getPublicKey(modulus, publicExponent); } return SingletonHolder.INSTANCE; } public synchronized static void reload(String modulus, String privateExponent, String publicExponent) { priKey = RSAUtils.getPrivateKey(modulus, privateExponent); pubKey = RSAUtils.getPublicKey(modulus, publicExponent); } public synchronized static JWTUtils getInstance() { if (priKey == null && pubKey == null) { priKey = RSAUtils.getPrivateKey(RSAUtils.modulus, RSAUtils.private_exponent); pubKey = RSAUtils.getPublicKey(RSAUtils.modulus, RSAUtils.public_exponent); } return SingletonHolder.INSTANCE; } /** * 獲取Token * @param uid 用戶ID * @param exp 失效時間,單位分鐘 * @return */ public static String getToken(String uid, int exp) { long endTime = System.currentTimeMillis() + 1000 * exp; return Jwts.builder().setSubject(uid).setExpiration(new Date(endTime)) .signWith(SignatureAlgorithm.RS512, priKey).compact(); } /** * 獲取Token * @param uid 用戶ID * @return */ public String getToken(String uid) { long endTime = System.currentTimeMillis() + 1000 * 60 * 1440; return Jwts.builder().setSubject(uid).setExpiration(new Date(endTime)) .signWith(SignatureAlgorithm.RS512, priKey).compact(); } /** * 檢查Token是否合法 * @param token * @return JWTResult */ public JWTResult checkToken(String token) { try { Claims claims = Jwts.parser().setSigningKey(pubKey).parseClaimsJws(token).getBody(); String sub = claims.get("sub", String.class); return new JWTResult(true, sub, "合法請求", ResponseCode.SUCCESS_CODE.getCode()); } catch (ExpiredJwtException e) { // 在解析JWT字符串時,若是‘過時時間字段’已經早於當前時間,將會拋出ExpiredJwtException異常,說明本次請求已經失效 return new JWTResult(false, null, "token已過時", ResponseCode.TOKEN_TIMEOUT_CODE.getCode()); } catch (SignatureException e) { // 在解析JWT字符串時,若是密鑰不正確,將會解析失敗,拋出SignatureException異常,說明該JWT字符串是僞造的 return new JWTResult(false, null, "非法請求", ResponseCode.NO_AUTH_CODE.getCode()); } catch (Exception e) { return new JWTResult(false, null, "非法請求", ResponseCode.NO_AUTH_CODE.getCode()); } } public static class JWTResult { private boolean status; private String uid; private String msg; private int code; public JWTResult() { super(); } public JWTResult(boolean status, String uid, String msg, int code) { super(); this.status = status; this.uid = uid; this.msg = msg; this.code = code; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public boolean isStatus() { return status; } public void setStatus(boolean status) { this.status = status; } public String getUid() { return uid; } public void setUid(String uid) { this.uid = uid; } } }
前端頁面文件:java
<!-- 登陸 --> <div> <p>用戶名:<input v-model="username" /></p> <p>密碼:<input v-model="password" /></p> <button @click="login">登陸</button> </div>
...
login: function() {
axios.post('http://localhost:8889/user/login', {
username: this.username,
password: this.password,
})
.then(function (response) {
if (response.data.status) {
alert(response.data.token);
} else {
alert("登陸失敗");
}
})
.catch(function (error) {
console.log(error);
});
}
後端controller:ios
@PostMapping("/login") public Object login(@RequestBody LoginInfo loginInfo) { Map<String, Object> result = new HashMap<>(); String token = userService.login(loginInfo); if (token == null) { result.put("status", false); } else { result.put("status", true); result.put("token", token); } return result; }
後端service:web
public String login(LoginInfo loginInfo) { User user = userRepository.findByUsernameAndPassword(loginInfo.getUsername(), loginInfo.getPassword()); if (user == null) { return null; } String token = JWTUtils.getInstance().getToken(user.getId() + ""); return token; }
測試登陸:json
登陸成功返回tokenaxios
token本地存儲:後端
存儲在前端app
login: function() { axios.post('http://localhost:8889/user/login', { username: this.username, password: this.password, }) .then(function (response) { if (response.data.status) { alert(response.data.token); // token本地存儲 localStorage.setItem("token", response.data.token); } else { alert("登陸失敗"); } }) .catch(function (error) { console.log(error); }); }
// 從html本地存儲中拿出token,設置到全局請求頭中
axios.defaults.headers.common['Authorization'] = localStorage.getItem("token");
這樣每次發送請求就能帶上token的請求頭了
後端解析請求頭獲取token,並藉助jwt工具類解密出當前登陸用戶id:
public class LoginInfoUtils { /** * 獲取當前登陸用戶id */ public static String getLoginUserId(HttpServletRequest request) { String authorization = request.getHeader("Authorization"); if (StringUtils.isNotBlank(authorization)) { JWTUtils.JWTResult result = JWTUtils.getInstance().checkToken(authorization); if (result.isStatus()) { return result.getUid(); } } return null; } }
後端控制檯輸出當前登陸用戶ID:工具
@GetMapping("/list") public List<User> list(HttpServletRequest request) { // 獲取當前登陸用戶id System.out.println("當前用戶ID: " + LoginInfoUtils.getLoginUserId(request)); return userService.findAll(); }
若還沒登陸則輸出:當前用戶ID: null
用戶登陸則輸出:當前用戶ID: 6
這樣,前端發送請求時,請求頭中帶有後端登陸接口返回的token值,
後端能夠從請求頭中獲取token並經過JWT解密得到當前登陸用戶id,就能夠在後端獲取當前登陸用戶了。