1. 程式人生 > 其它 >JWT--token 認證

JWT--token 認證

目錄

常見的認證方式

  • 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"));
    }