為什么使用JWT?
隨著技術(shù)的發(fā)展抖锥,分布式web應(yīng)用的普及亿眠,通過session管理用戶登錄狀態(tài)成本越來越高,因此慢慢發(fā)展成為token的方式做登錄身份校驗磅废,然后通過token去取redis中的緩存的用戶信息纳像,隨著之后jwt的出現(xiàn),校驗方式更加簡單便捷化拯勉,無需通過redis緩存竟趾,而是直接根據(jù)token取出保存的用戶信息,以及對token可用性校驗宫峦,單點登錄更為簡單岔帽。
JWT架構(gòu)圖
使用JWT核心代碼:
maven依賴:
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency>
JWT工具類:
用于生成Token,和Token驗證
public class JwtUtils {
/**
* 簽發(fā)JWT
* @param id
* @param subject 可以是JSON數(shù)據(jù) 盡可能少
* @param ttlMillis
* @return String
*
*/
public static String createJWT(String id, String subject, long ttlMillis) {
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
SecretKey secretKey = generalKey();
JwtBuilder builder = Jwts.builder()
.setId(id)
.setSubject(subject) // 主題
.setIssuer("user") // 簽發(fā)者
.setIssuedAt(now) // 簽發(fā)時間
.signWith(signatureAlgorithm, secretKey); // 簽名算法以及密匙
if (ttlMillis >= 0) {
long expMillis = nowMillis + ttlMillis;
Date expDate = new Date(expMillis);
builder.setExpiration(expDate); // 過期時間
}
return builder.compact();
}
/**
* 驗證JWT
* @param jwtStr
* @return
*/
public static CheckResult validateJWT(String jwtStr) {
CheckResult checkResult = new CheckResult();
Claims claims = null;
try {
claims = parseJWT(jwtStr);
checkResult.setSuccess(true);
checkResult.setClaims(claims);
} catch (ExpiredJwtException e) {
checkResult.setErrCode(SystemConstant.JWT_ERRCODE_EXPIRE);
checkResult.setSuccess(false);
} catch (SignatureException e) {
checkResult.setErrCode(SystemConstant.JWT_ERRCODE_FAIL);
checkResult.setSuccess(false);
} catch (Exception e) {
checkResult.setErrCode(SystemConstant.JWT_ERRCODE_FAIL);
checkResult.setSuccess(false);
}
return checkResult;
}
public static SecretKey generalKey() {
byte[] encodedKey = Base64.decode(SystemConstant.JWT_SECERT);
SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
return key;
}
/**
*
* 解析JWT字符串
* @param jwt
* @return
* @throws Exception
*/
public static Claims parseJWT(String jwt) throws Exception {
SecretKey secretKey = generalKey();
return Jwts.parser()
.setSigningKey(secretKey)
.parseClaimsJws(jwt)
.getBody();
}
}
如何使用导绷?
代碼實例:
public class LoginController {
@Autowired
UserRepository userRepository;
@ApiOperation(value="用戶登陸")
@RequestMapping(value="login",method = RequestMethod.POST)
public ReturnVo login(String username, String password,HttpServletResponse
response) {
User user = userRepository.findByUsername(username);
if(user!=null){
if(user.getPassword().equals(password)){
//把token返回給客戶端-->客戶端保存至cookie-->客戶端每次請求附帶cookie參數(shù)
String JWT = JwtUtils.createJWT("1", username, SystemConstant.JWT_TTL);
return ReturnVo.ok(JWT);
}else{
return ReturnVo.error();
}
}else{
return ReturnVo.error();
}
}
@ApiOperation(value="獲取用戶信息")
@RequestMapping(value="description",method = RequestMethod.POST)
public ReturnVo description(String username) {
User user = userRepository.findByUsername(username);
return ReturnVo.ok(user.getDescription());
}
}