天天看點

springboot整合jwt_springBoot整合JWT使用JWT資料結構1、Header 頭部2、payload 負載3、signature 簽名jwt認證流程圖springBoot整合JWT1、首先寫一個jwt工具類2、登入時擷取token3、攔截器,攔截頭部沒有攜帶token的接口4、配置攔截器5、結束

注:業餘時間自學,以此作為筆記.

JWT資料結構

例如 xxxx.yyy.zzz 由三部分組成,每部分用英文句号連接配接,JWT的三個部分: header 頭部 payload 負載 signature 簽名.也就是 Header.Payload.Signature,如圖

springboot整合jwt_springBoot整合JWT使用JWT資料結構1、Header 頭部2、payload 負載3、signature 簽名jwt認證流程圖springBoot整合JWT1、首先寫一個jwt工具類2、登入時擷取token3、攔截器,攔截頭部沒有攜帶token的接口4、配置攔截器5、結束

JWT結構圖

1、Header 頭部

是一個JSON 對象, 描述JWT的中繼資料,例如: {"alg": "HS256", "typ": "JWT"}

alg屬性表示簽名的算法(algorithm),預設是 HMAC SHA256

typ屬性表示這個令牌的類型(type),JWT 令牌統一寫為JWT,不寫則預設上面格式

2、payload 負載

是一個JSON 對象, 用來存放實際需要傳遞的資料,形如: {"sub": "1234567890", "name": "John Doe","admin": true}

一般是在這個部分定義私有字段: 例如{"userId":"1","userName":"jack"}

注意,JWT 預設是不加密的,任何人都可以讀到,是以不要把機密資訊放在這個部分,如使用者密碼等。

3、signature 簽名

signature 是對前兩部分的簽名,防止資料篡改

1、需要指定一個密鑰(secret) 2、這個密鑰隻有伺服器才知道,不能洩露給用戶端 3、使用 Header 裡面指定的簽名算法,按照下面的公式産生簽名

jwt認證流程圖

springboot整合jwt_springBoot整合JWT使用JWT資料結構1、Header 頭部2、payload 負載3、signature 簽名jwt認證流程圖springBoot整合JWT1、首先寫一個jwt工具類2、登入時擷取token3、攔截器,攔截頭部沒有攜帶token的接口4、配置攔截器5、結束

springBoot整合JWT

1、首先寫一個jwt工具類

public class JwtHelper {    // 加密字元串,随便定義    private static final String SECRET = "@[email protected]";    // 簽發人    private static String ISSUER = "sys_user";    // 期限 15d    public static final long EXPIRE_SECONDS = 15 * 24 * 60 * 60;    /**     * 生成JWT     *     * @return     */    public static String getToken(UserInfo userInfo) {        try {            //使用HMAC256進行加密            Algorithm algorithm = Algorithm.HMAC256(SECRET);            LocalDateTime localDateTimeNow = LocalDateTime.now();            LocalDateTime localDateTimeExpire = localDateTimeNow.plusSeconds(EXPIRE_SECONDS);            //token過期時間            Date expire = Date.from(localDateTimeExpire.atZone(ZoneId.systemDefault()).toInstant());            //建立jwt            String token = JWT.create()                    .withClaim("userId", userInfo.getUserId())                    .withClaim("userName", userInfo.getUsername())                    .withClaim("role", userInfo.getRole())                    .withIssuer(ISSUER) // 發行人                    .withExpiresAt(expire)                    .sign(algorithm);// 過期時間點            return token;        } catch (IllegalArgumentException e) {            throw new RuntimeException(e);        }    }    /**     * 解密jwt     */    public static UserInfo parseToken(String token) {        UserInfo user = null;        try {            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).withIssuer(ISSUER).build();            DecodedJWT jwt = verifier.verify(token);            Map claimMap = jwt.getClaims();            Map userMap = new HashMap<>();            claimMap.forEach((k, v) -> userMap.put(k, v.asString()));            user = BeanUtil.mapToBean(userMap, UserInfo.class, true);        } catch (Exception e) {            e.printStackTrace();        }        return user;    }}
           

2、登入時擷取token

public Rest loginApp(@RequestParam(value = "data") String data) throws IOException {        HashMap paramMap = JSONUtil.toBean(data, HashMap.class);        UserInfo userInfo = systemAppService.getLoginInfo(paramMap);        if (userInfo != null) {            String token = JwtHelper.getToken(userInfo);            userInfo.setToken(token);            Map config = new HashMap();            config.put("socketAddress", propertyConfig.getSocketAddress());            config.put("allocurl", propertyConfig.getAllocurl());            userInfo.setConfig(config);            return RestUtil.ok(userInfo);        }        return RestUtil.fail("使用者名或密碼不正确");    }
           

3、攔截器,攔截頭部沒有攜帶token的接口

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {        // System.out.println("app login intercept ...");        log.info("app login intercept used ...");        // 從 http 請求頭中取出 token        final String token = request.getHeader("token");        // 如果不是映射到方法直接通過        if (!(handler instanceof HandlerMethod)) {            return true;        }        HandlerMethod handlerMethod = (HandlerMethod) handler;        Method method = handlerMethod.getMethod();        // 檢查是否有passtoken注釋,有則跳過認證        if (method.isAnnotationPresent(PassToken.class)) {            PassToken passToken = method.getAnnotation(PassToken.class);            if (passToken.required()) {                return true;            }        }        // 執行認證        if (StringUtils.isEmpty(token)) {            // 未登入,傳回401            response.setStatus(HttpStatus.UNAUTHORIZED.value());            return false;        }        // 解析token        UserInfo userInfo = JwtHelper.parseToken(token);        if (userInfo == null) {            // 抛出異常,證明未登入,傳回401            response.setStatus(HttpStatus.UNAUTHORIZED.value());            return false;        }        // 放入線程域        UserLocal.set(userInfo);        return true;    }
           

4、配置攔截器

@Configurationpublic class CustomMVCConfiguration implements WebMvcConfigurer {  //攔截器    @Override    public void addInterceptors(InterceptorRegistry registry) {        registry.addInterceptor(new AppLoginInterceptor())                .addPathPatterns("/**")   //攔截所有路徑                .excludePathPatterns("/system/loginApp")  //放行登入接口                .excludePathPatterns("/doc.html", "/swagger-resources/**");    }}
           

5、結束