springboot-vue-JWT使用
后端引入依賴:
<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;
}
}
}
前端頁面文件:
<!-- 登錄 -->
<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:
@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:
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;
}
測試登錄:

登錄成功返回token

token本地存儲:
存儲在前端
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,就可以在后端獲取當前登錄用戶了。

