最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JWT全面解讀和詳細使用步驟

 更新時間:2021年12月02日 11:36:04   作者:丁可樂  
這篇文章全面解讀了JWT規(guī)范和詳細使用步驟,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

定義:JSON Web Token(縮寫 JWT)是目前最流行的跨域認證解決方案

JWT官網(wǎng)

由于HTTP協(xié)議是無狀態(tài)的,這意味著如果我們想判定一個接口是否被認證后訪問,就需要借助cookie或者session會話機制進行判定,但是由于現(xiàn)在的系統(tǒng)架構(gòu)大部分都不止一臺服務(wù)器,此時又要借助數(shù)據(jù)庫或者全局緩存 做存儲,這種方案顯然受限太多。

那么我們可不可以讓認證令牌的發(fā)布者自己去識別這個令牌是不是我曾經(jīng)發(fā)布的令牌呢(JWT核心思想),這是JWT最大的優(yōu)點也是最大的缺點,優(yōu)點是簡單快捷、不需要依賴任何第三方操作就能實現(xiàn)身份認證,缺點就是對于任何擁有用戶發(fā)布令牌的請求都會認證通過。

JWT的數(shù)據(jù)結(jié)構(gòu)

正常的JWT數(shù)據(jù)結(jié)構(gòu)應(yīng)該如下

它是一個很長的字符串,中間用點(.)分隔成三個部分

JWT的三個部分依次: Header - 頭部 、Payload - 負載 、Signature(簽名)

即:Header.Payload.Signature

Header

Header 部分是一個 JSON 對象,描述 JWT 的元數(shù)據(jù),通常是下面的樣子。

{
"alg": "HS256",
"typ": "JWT"
}

alg屬性表示簽名的算法(algorithm),默認是 HMAC SHA256(寫成 HS256);typ屬性表示這個令牌(token)的類型(type),JWT 令牌統(tǒng)一寫為JWT

Payload

Payload 部分也是一個 JSON 對象,用來存放實際需要傳遞的數(shù)據(jù)。JWT 規(guī)定了7個官方字段,供選用。

  1. iss (issuer):簽發(fā)人
  2. exp (expiration time):過期時間
  3. sub (subject):主題
  4. aud (audience):受眾
  5. nbf (Not Before):生效時間
  6. iat (Issued At):簽發(fā)時間
  7. jti (JWT ID):編號

除了官方字段,你還可以在這個部分定義私有字段

{
"sub": "1234567890",
"name": "John Doe",
"age": "19"
}

注意:JWT默認是明文展示,任何人都可以讀取到,所以此處不要放私密信息

這個 JSON 對象也要使用 Base64URL 算法轉(zhuǎn)成字符串。

Signature

Signature 部分是對前兩部分的簽名,防止數(shù)據(jù)篡改。

首先,需要指定一個密鑰(secret)。這個密鑰只有服務(wù)器才知道,不能泄露給用戶。然后,使用 Header 里面指定的簽名算法(默認是 HMAC SHA256),按照下面的公式產(chǎn)生簽名。

  HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

算出簽名以后,把 Header、Payload、Signature 三個部分拼成一個字符串,每個部分之間用"點"(.)分隔,就可以返回給用戶。

Base64URL

前面提到,Header 和 Payload 串型化的算法是 Base64URL。這個算法跟 Base64 算法基本類似,但有一些小的不同。

JWT 作為一個令牌(token),有些場合可能會放到 URL(比如 api.example.com/?token=xxx)。Base64 有三個字符+、/和=,在 URL 里面有特殊含義,所以要被替換掉:=被省略、+替換成-,/替換成_ 。這就是 Base64URL 算法

JWT的實現(xiàn)

Maven依賴

 <dependency>
		    <groupId>com.auth0</groupId>
		    <artifactId>java-jwt</artifactId>
		    <version>3.5.0</version>
</dependency>

JWT簽名發(fā)布和驗證代碼

public class TokenUtil {
	//Token的過期時間
	private static final long EXPIRE_TIME = 30 * 60 * 1000;
	//Token的私鑰
	private static final String TOKEN_SECRET = "jytoken_secret";
	
	
	/**
	 * 生成簽名,30分鐘過期
	 * @param **userInfo**	用戶信息 用戶姓名
	* @param **other** 用戶其他信息 用戶id
	* @return
	 */
	public static String sign(String userInfo, String other) {
	    try {
	    	// 設(shè)置過期時間
	    	Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
	    	//私鑰和加密算法
	        Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
	        // 設(shè)置頭部信息
	        Map<String, Object> header = new HashMap<>(2);
	        header.put("Type", "Jwt");
	        header.put("alg", "HS256");
	        // 返回token字符串
	        return JWT.create()
	                .withHeader(header)
	                .withClaim("userInfo", userInfo)
	                .withClaim("other", other)
	                .withExpiresAt(date)
	                .sign(algorithm);
	    } catch (Exception e) {
	        e.printStackTrace();
	        return null;
	    }
	}
	
	/**
	 * 生成簽名,30分鐘過期
	 * @param **userInfo**	用戶信息 用戶姓名
	* @param **other** 用戶其他信息 用戶id
	* @return
	 */
	public static String sign(String userInfo, String other,long expire) {
	    try {
	    	// 設(shè)置過期時間
	    	Date date = new Date(System.currentTimeMillis() + expire);
	    	//私鑰和加密算法
	        Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
	        // 設(shè)置頭部信息
	        Map<String, Object> header = new HashMap<>(2);
	        header.put("Type", "Jwt");
	        header.put("alg", "HS256");
	        // 返回token字符串
	        return JWT.create()
	                .withHeader(header)
	                .withClaim("userInfo", userInfo)
	                .withClaim("other", other)
	                .withExpiresAt(date)
	                .sign(algorithm);
	    } catch (Exception e) {
	        e.printStackTrace();
	        return null;
	    }
	}
	
	
	/**
	 * 檢驗token是否正確
	 * @param **token**
	* @return
	 */
	public static boolean verify(String token){
	    try {
	        Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
	        JWTVerifier verifier = JWT.require(algorithm).build();
	        verifier.verify(token);//未驗證通過會拋出異常
	        return true;
	    } catch (Exception e){
	        return false;
	    }
	}
	
	/**
	 * 從token中獲取info信息
	 * @param **token**
	* @return
	 */
	public static String getUserName(String token,String info){
	    try {
	        DecodedJWT jwt = JWT.decode(token);
	        return jwt.getClaim(info).asString();
	    } catch (JWTDecodeException e){
	        e.printStackTrace();
	    }
	    return null;
	}
	
}

攔截器配置無需認證的請求

@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport  {
   
	@Autowired
	private TokenHandler tokenHandler;
    


    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        List<String> excludePath = new ArrayList<>();
        String checkLogin = "/pushlogin/checkIsCanLogin";
        String login = "/pushlogin/login";
        String getVerifyCode = "/common/send";
        String verfifyMethod = "/common/validationCode";
        excludePath.add(checkLogin);
        excludePath.add(login);
        excludePath.add(getVerifyCode);
        excludePath.add(verfifyMethod);
        registry.addInterceptor(tokenHandler).excludePathPatterns(excludePath);
    }
}

Token統(tǒng)一攔截器代碼

@Component
@Slf4j
public class TokenHandler implements HandlerInterceptor{
	
		@Override
	   public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)  throws Exception {
	 
	        String token = request.getHeader("Authentication");
	        if (token != null){
	            boolean result = TokenUtil.verify(token);
	            if(result){
	                log.info("通過攔截器");
	                return true;
	            }
	        }
	        log.info("認證失敗");
	        
	        return false;
	   }
	
}

用戶登錄時驗證用戶信息后,返回Token信息

 	@Override
    public UserDTO selectIsExistUserInfo(String phone) {
        //TODO 偽代碼 驗證用戶信息 
        UserDTO info = 查詢用戶信息
        if (info != null) {
            String token = TokenUtil.sign(info.getUsername(), info.getUserId(), 6 * 60 * 60 * 1000);
            info.setToken(token);
        }
        return info;
    }

到此這篇關(guān)于JWT全面解讀和詳細使用步驟的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java反射概念與使用實例代碼

    Java反射概念與使用實例代碼

    JAVA反射機制是在運行狀態(tài)中,對于任意一個類,都能夠知道這個類的所有屬性和方法,下面這篇文章主要給大家介紹了關(guān)于Java反射概念與使用的相關(guān)資料,需要的朋友可以參考下
    2021-11-11
  • Java基礎(chǔ)之不簡單的數(shù)組

    Java基礎(chǔ)之不簡單的數(shù)組

    數(shù)組(Array)是有序的元素序列。 若將有限個類型相同的變量的集合命名,那么這個名稱為數(shù)組名。組成數(shù)組的各個變量稱為數(shù)組的分量,也稱為數(shù)組的元素,有時也稱為下標變量
    2021-09-09
  • 解決@Cacheable在同一個類中方法調(diào)用不起作用的問題

    解決@Cacheable在同一個類中方法調(diào)用不起作用的問題

    這篇文章主要介紹了解決@Cacheable在同一個類中方法調(diào)用不起作用的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java設(shè)計模式之觀察者模式解析

    Java設(shè)計模式之觀察者模式解析

    這篇文章主要介紹了Java設(shè)計模式之觀察者模式解析,觀察者模式,又被稱為發(fā)布/訂閱模式,它定義了一種一對多的依賴關(guān)系,讓多個觀察者對象同時監(jiān)聽某一個主題對象,這個主題對象在狀態(tài)變化時,會通知所有的觀察者對象,使他們能夠自動更新自己,需要的朋友可以參考下
    2023-09-09
  • MybatisPlus自動填充時間的配置類實現(xiàn)

    MybatisPlus自動填充時間的配置類實現(xiàn)

    本文介紹了如何在MyBatis-Plus中實現(xiàn)自動填充時間的功能,通過實現(xiàn)MetaObjectHandler接口,重寫insertFill()和updateFill()方法,分別在插入和更新時填充創(chuàng)建時間和更新時間,感興趣的可以了解一下
    2024-12-12
  • SpringBoot項目多層級多環(huán)境yml設(shè)計詳解

    SpringBoot項目多層級多環(huán)境yml設(shè)計詳解

    這篇文章主要為大家介紹了SpringBoot項目多層級多環(huán)境yml設(shè)計詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-03-03
  • maven打包插件的使用(maven-compiler-plugin、maven-dependency-plugin、maven-jar-plugin、maven-resources-plugin)

    maven打包插件的使用(maven-compiler-plugin、maven-dependency-plugin、m

    本文主要介紹了maven打包插件的使用(maven-compiler-plugin、maven-dependency-plugin、maven-jar-plugin、maven-resources-plugin),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • SpringBoot?ApplicationContext接口深入分析

    SpringBoot?ApplicationContext接口深入分析

    ApplicationContext是Spring應(yīng)用程序中的中央接口,由于繼承了多個組件,使得ApplicationContext擁有了許多Spring的核心功能,如獲取bean組件,注冊監(jiān)聽事件,加載資源文件等
    2022-11-11
  • Spring?MVC數(shù)據(jù)綁定方式

    Spring?MVC數(shù)據(jù)綁定方式

    這篇文章主要介紹了Spring?MVC數(shù)據(jù)綁定方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • Java使用Lua實現(xiàn)動態(tài)擴展和腳本自動升級

    Java使用Lua實現(xiàn)動態(tài)擴展和腳本自動升級

    Lua是一種輕量級的腳本語言,常用于游戲開發(fā)和嵌入式系統(tǒng)中,這篇文章主要介紹了Java如何調(diào)用Lua實現(xiàn)動態(tài)擴展和腳本自動升級,感興趣的可以學(xué)習(xí)下
    2023-08-08

最新評論

苍山县| 娄烦县| 绩溪县| 出国| 延安市| 榆中县| 潞西市| 五台县| 峨边| 垦利县| 巩留县| 威远县| 海林市| 泸州市| 建水县| 临夏市| 酒泉市| 西乡县| 通海县| 竹山县| 兖州市| 通州区| 临夏市| 鹤岗市| 武功县| 武定县| 彰化县| 炎陵县| 家居| 金川县| 阜新市| 宝鸡市| 开原市| 丹江口市| 遂溪县| 杭州市| 务川| 商水县| 浦北县| 西吉县| 兰溪市|