JWT--token 認證
阿新 • • 發佈:2021-07-21
目錄
常見的認證方式
- http basic auth: 最簡單的每次都要認證使用者名稱和密碼,不安全、麻煩、所以不採用
- cookie+session: 比較常用,但是比較費伺服器空間,伺服器需要為每個使用者開闢session空間
- OAuth第三方授權:
使用者在訪問蝦米app時需要使用qq賬號登陸,於是qq認證伺服器讓使用者授權,使用者授權通過後,qq伺服器發一個令牌給蝦米,蝦米帶著這個令牌去qq資源伺服器獲取使用者的基本資訊(暱稱、頭像、性別等),蝦米再把資訊展示給使用者。
- 基於Token的認證
客戶端在伺服器端登陸成功以後,伺服器會建立一個token,儲存在redis中,並且把這個token傳送給客戶端。客戶端下次訪問資源時會自動攜帶這個token,伺服器拿到token去redis中驗證,如果驗證通過就把資訊進行返回。
token認證的優點:比http basic auth安全、比cookie節省伺服器空間,比oauth認證要輕巧,應用場景也不同。
token的優點:
- 可以不需要通過cookie來儲存,讓前端把token放到請求頭裡傳遞給後端,不受cookie的跨域限制。
- token和uuid還是有區別的,因為可以直接通過token的解碼來獲取使用者的部分資訊。-- jwt 通過base64編碼將使用者資訊編碼成token,因此可以通過base64解碼獲取token中的使用者資訊
一、JWT
1.jwt介紹
Json web token 是一種儲存和傳輸資料的標準。jwt由三個部分組成: 頭部、負載、簽名
1)頭部
頭部用來存放描述jwt的基本資訊,比如型別、演算法
{
"alg": "HS256",
"typ": "JWT"
}
使用base64編碼後:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9,也就是說使用base64解碼後能還原字串資訊
2)負載
分成了兩種宣告:
- 公共的宣告:存放一些標準的資訊,固定的鍵
- 私有的宣告:存放自定義資訊
{ "sub": "use001", "name": "weixiang", "iat": 1516239022 }
3)簽名
通過使用者指定的鹽,來生成簽名,用於服務端的安全驗證。但不能保證jwt中負載中資料的必然的安全。
二、JWT的官方推薦類庫-JJWT
1.引入依賴
<!--jjwt-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
2.建立token
@Test
public void createToken(){
//建立JWT物件
JwtBuilder jwtBuilder = Jwts.builder()
.setId("1001")//設定公共引數id
.setSubject("xiaowang")//設定物件名
.setIssuedAt(new Date())//設定簽發時間
.signWith(SignatureAlgorithm.HS256, "qfjava");//設定簽名
//得到token
String token = jwtBuilder.compact();
System.out.println(token);
}
eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxMDAxIiwic3ViIjoieGlhb3dhbmciLCJpYXQiOjE2MTU5NDk2NjJ9.MSGqmONhNdxDG0XldhZQ1iXpY4IfU-PjmjS3MpHMb64
3.解析token,獲取token中的資料
/**
* 解析token
*/
@Test
public void parseToken(){
String token = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxMDAxIiwic3ViIjoieGlhb3dhbmciLCJpYXQiOjE2MTU5NDk2NjJ9.MSGqmONhNdxDG0XldhZQ1iXpY4IfU-PjmjS3MpHMb64";
Claims claims = Jwts.parser().setSigningKey("qfjava").parseClaimsJws(token).getBody();//設定簽名
System.out.println("id:"+claims.getId());//獲取token中的資料
System.out.println("subject:"+claims.getSubject());
System.out.println("time:"+claims.getIssuedAt());
}
4.設定token的超時時間
/**
* 設定token的過期時間
*/
@Test
public void testExp(){
long now = System.currentTimeMillis();
long exp = now + 60*1000;//設定過期的時間的毫秒值
Date expDate = new Date(exp);
//建立JWT物件
JwtBuilder jwtBuilder = Jwts.builder().setId("1001")//設定公共引數id
.setSubject("xiaowang")//設定物件名
.setIssuedAt(new Date())//設定簽發時間
.setExpiration(expDate)//過期的時間點
.signWith(SignatureAlgorithm.HS256, "qfjava");//設定簽名
//得到token
String token = jwtBuilder.compact();
System.out.println(token);
}
5.建立帶自定義宣告的token
/**
* 建立token
*/
@Test
public void createCustomToken(){
//建立JWT物件
JwtBuilder jwtBuilder = Jwts.builder().setId("1001")//設定公共引數id
.setSubject("xiaowang")//設定物件名
.setIssuedAt(new Date())//設定簽發時間
.claim("role","student")
.claim("class","java2007")
.signWith(SignatureAlgorithm.HS256, "qfjava");//設定簽名
//得到token
String token = jwtBuilder.compact();
System.out.println(token);
}
6.解析自定義宣告的token
/**
* 解析自定義宣告的token
*/
@Test
public void parseClaimToken(){
String token = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxMDAxIiwic3ViIjoieGlhb3dhbmciLCJpYXQiOjE2MTU5NTA0OTksInJvbGUiOiJzdHVkZW50IiwiY2xhc3MiOiJqYXZhMjAwNyJ9.dSiMUMpqvCJIZFVRRPO5tRho3ue2qCuEYQP0r2JrJvQ";
Claims claims = Jwts.parser().setSigningKey("qfjava").parseClaimsJws(token).getBody();//設定簽名
System.out.println("role:"+claims.get("role"));
System.out.println("class:"+claims.get("class"));
}