本例代碼是在Spring Boot教程(十一):Spring Boot集成fastjson基礎上修改,修改內容主要包括:
- pom.xml文件裏依賴版本進行了升級
- 去掉了jsp集成
注:不需要參考第十一講源碼,直接查看本文底部源碼即可。
一、簡介
JSON Web Token(JWT)是爲了在網絡應用環境間傳遞聲明而執行的一種基於JSON的開放標準((RFC 7519),它定義了一種緊湊(Compact)且自包含(Self-contained)的方式,用於在各方之間以JSON對象安全傳輸信息。 這些信息可以通過數字簽名進行驗證和信任。 可以使用祕密(使用HMAC算法)或使用RSA的公鑰/私鑰對對JWT進行簽名。JWT的聲明一般被用來在身份提供者和服務提供者間傳遞被認證的用戶身份信息,以便於從資源服務器獲取資源,也可以增加一些額外的其它業務邏輯所必須的聲明信息,該token也可直接被用於認證,也可被加密。是目前最流行的跨域認證解決方案。
二、jwt使用流程簡述
瀏覽器發請求時,在請求頭裏加入Authorization,並加上Bearer標註:
// Authorization: Bearer <token>
getToken('api/user/1', {
headers: {
'Authorization': 'Bearer ' + token
}
})
三、集成JWT
1、添加依賴
<!-- jwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
2、在application.properties裏添加配置參數
# jwt
jwt.secret=12345
jwt.expire=60
3、創建Jwt配置
package com.songguoliang.springboot.configuration;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import java.util.Date;
/**
* @author itinypocket
* @date 2019-09-03 12:56
*/
@Configuration
public class JwtToken {
private static Logger logger = LoggerFactory.getLogger(JwtToken.class);
/**
* 祕鑰
*/
@Value("${jwt.secret}")
private String secret;
/**
* 過期時間(秒)
*/
@Value("${jwt.expire}")
private long expire;
/**
* 生成jwt token
*/
public String generateToken(String loginName) {
Date nowDate = new Date();
Date expireDate = new Date(nowDate.getTime() + expire * 1000);
return Jwts.builder()
.setHeaderParam("typ", "JWT")
.setSubject(loginName)
.setIssuedAt(nowDate)
.setExpiration(expireDate)
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
public Claims getClaimByToken(String token) {
if (StringUtils.isEmpty(token)) {
return null;
}
String[] header = token.split("Bearer");
token = header[1];
try {
return Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
} catch (Exception e) {
logger.debug("validate is token error ", e);
return null;
}
}
/**
* token是否過期
*
* @return true:過期
*/
public static boolean isTokenExpired(Date expiration) {
return expiration.before(new Date());
}
}
4、創建測試控制類
package com.songguoliang.springboot.controller;
import com.songguoliang.springboot.configuration.JwtToken;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
import javax.security.sasl.AuthenticationException;
import java.util.Arrays;
import java.util.List;
/**
* @author itinypocket
* @date 2019-09-03 12:59
*/
@RestController
public class JwtController {
@Autowired
private JwtToken jwtToken;
@PostMapping("/login")
public String login(String loginName, String password) {
// 1. 根據登錄名從數據庫查詢用戶,驗證用戶名和密碼,爲了簡單演示jwt,這裏假設驗證通過
// Todo
// 2. 驗證成功生成token,並返回
String token = jwtToken.generateToken(loginName);
return token;
}
@GetMapping("/getUserInfo")
public String getUserInfo(@RequestHeader("Authorization") String authHeader) throws AuthenticationException {
// 黑名單token
List<String> blacklistToken = Arrays.asList("禁止訪問的token");
Claims claims = jwtToken.getClaimByToken(authHeader);
if (claims == null || JwtToken.isTokenExpired(claims.getExpiration()) || blacklistToken.contains(authHeader)) {
throw new AuthenticationException("token 不可用");
}
String userId = claims.getSubject();
// 根據用戶id獲取接口數據返回接口
return userId;
}
}
5、啓動服務,使用postman工具進行測試,post方式訪問登錄url進行登錄認證,獲取token,如下圖:
6、通過token訪問項目其他接口,如下: