<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SpringBoot集成JWT實(shí)現(xiàn)token驗(yàn)證

          共 10521字,需瀏覽 22分鐘

           ·

          2020-12-28 03:28

          點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號(hào)”

          優(yōu)質(zhì)文章,第一時(shí)間送達(dá)

          66套java從入門到精通實(shí)戰(zhàn)課程分享

          Jwt全稱是:json web token。它將用戶信息加密到token里,服務(wù)器不保存任何用戶信息。服務(wù)器通過(guò)使用保存的密鑰驗(yàn)證token的正確性,只要正確即通過(guò)驗(yàn)證。

          優(yōu)點(diǎn)

          1. 簡(jiǎn)潔: 可以通過(guò)URLPOST參數(shù)或者在HTTP header發(fā)送,因?yàn)閿?shù)據(jù)量小,傳輸速度也很快;

          2. 自包含:負(fù)載中可以包含用戶所需要的信息,避免了多次查詢數(shù)據(jù)庫(kù);

          3. 因?yàn)?/span>Token是以JSON加密的形式保存在客戶端的,所以JWT是跨語(yǔ)言的,原則上任何web形式都支持;

          4. 不需要在服務(wù)端保存會(huì)話信息,特別適用于分布式微服務(wù)。

          缺點(diǎn)

          1. 無(wú)法作廢已頒布的令牌;

          2. 不易應(yīng)對(duì)數(shù)據(jù)過(guò)期。

          一、Jwt消息構(gòu)成

          1.1 組成

          一個(gè)token分3部分,按順序?yàn)?/span>

          1. 頭部(header)

          2. 載荷(payload)

          3. 簽證(signature)

          三部分之間用.號(hào)做分隔。例如:

          eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIxYzdiY2IzMS02ODFlLTRlZGYtYmU3Yy0wOTlkODAzM2VkY2UiLCJleHAiOjE1Njk3Mjc4OTF9.wweMzyB3tSQK34Jmez36MmC5xpUh15Ni3vOV_SGCzJ8

          1.2 header

          Jwt的頭部承載兩部分信息:

          1. 聲明類型,這里是Jwt

          2. 聲明加密的算法 通常直接使用?HMAC SHA256

          Jwt里驗(yàn)證和簽名使用的算法列表如下:

          JWS算法名稱
          HS256HMAC256
          HS384HMAC384
          HS512HMAC512
          RS256RSA256
          RS384RSA384
          RS512RSA512
          ES256ECDSA256
          ES384ECDSA384
          ES512ECDSA512

          1.3 playload

          載荷就是存放有效信息的地方。基本上填2種類型數(shù)據(jù)

          1. 標(biāo)準(zhǔn)中注冊(cè)的聲明的數(shù)據(jù);

          2. 自定義數(shù)據(jù)。

          由這2部分內(nèi)部做base64加密。

          • 標(biāo)準(zhǔn)中注冊(cè)的聲明 (建議但不強(qiáng)制使用)

          iss:?jwt簽發(fā)者
          sub:?jwt所面向的用戶
          aud:?接收jwt的一方
          exp:?jwt的過(guò)期時(shí)間,這個(gè)過(guò)期時(shí)間必須要大于簽發(fā)時(shí)間
          nbf:?定義在什么時(shí)間之前,該jwt都是不可用的.
          iat:?jwt的簽發(fā)時(shí)間
          jti: jwt的唯一身份標(biāo)識(shí),主要用來(lái)作為一次性token,從而回避重放攻擊。
          • 自定義數(shù)據(jù):存放我們想放在token中存放的key-value

          1.4 signature

          Jwt的第三部分是一個(gè)簽證信息,這個(gè)簽證信息由三部分組成
          base64加密后的headerbase64加密后的payload連接組成的字符串,然后通過(guò)header中聲明的加密方式進(jìn)行加鹽secret組合加密,然后就構(gòu)成了Jwt的第三部分。

          二、Spring Boot和Jwt集成示例

          2.1、項(xiàng)目依賴 pom.xml

          ??
          ???com.auth0
          ???java-jwt
          ???3.10.3
          ??

          2.2、自定義注解

          //需要登錄才能進(jìn)行操作的注解LoginToken?
          @Target({ElementType.METHOD,?ElementType.TYPE})
          @Retention(RetentionPolicy.RUNTIME)
          public?@interface?LoginToken?{
          ????boolean?required()?default?true;
          }
          //用來(lái)跳過(guò)驗(yàn)證的PassToken
          @Target({ElementType.METHOD,?ElementType.TYPE})
          @Retention(RetentionPolicy.RUNTIME)
          public?@interface?PassToken?{
          ????boolean?required()?default?true;
          }

          2.3、用戶實(shí)體類、及查詢service

          @Data
          @AllArgsConstructor
          @NoArgsConstructor
          public?class?User?{
          ????private?String?userID;
          ????private?String?userName;
          ????private?String?passWord;
          }
          package?com.sky.springbootdemo.jwt.service;
          ?
          import?com.sky.springbootdemo.jwt.entity.User;
          import?org.springframework.stereotype.Service;
          ?
          /**
          ?*?@title:?UserService
          ?*?@Author?gjt
          ?*?@Date:?2020-12-21
          ?*?@Description:
          ?*/
          @Service
          public?class?UserService?{
          ?
          ????public?User?getUser(String?userid,?String?password){
          ????????if?("admin".equals(userid)?&&?"admin".equals(password)){
          ????????????User?user=new?User();
          ????????????user.setUserID("admin");
          ????????????user.setUserName("admin");
          ????????????user.setPassWord("admin");
          ????????????return?user;
          ????????}
          ????????else{
          ????????????return?null;
          ????????}
          ????}
          ?
          ????public?User?getUser(String?userid){
          ????????if?("admin".equals(userid)){
          ????????????User?user=new?User();
          ????????????user.setUserID("admin");
          ????????????user.setUserName("admin");
          ????????????user.setPassWord("admin");
          ????????????return?user;
          ????????}
          ????????else{
          ????????????return?null;
          ????????}
          ????}
          }

          2.4、Token生成

          package?com.sky.springbootdemo.jwt.service;
          ?
          import?com.auth0.jwt.JWT;
          import?com.auth0.jwt.algorithms.Algorithm;
          import?com.sky.springbootdemo.jwt.entity.User;
          import?org.springframework.stereotype.Service;
          ?
          import?java.util.Date;
          ?
          /**
          ?*?@title:?TokenService
          ?*?@Author?gjt
          ?*?@Date:?2020-12-21
          ?*?@Description:
          ?*/
          @Service
          public?class?TokenService?{
          ????/**
          ?????*?過(guò)期時(shí)間5分鐘
          ?????*/
          ????private?static?final?long?EXPIRE_TIME?=?5?*?60?*?1000;
          ?
          ????public?String?getToken(User?user)?{
          ????????Date?date?=?new?Date(System.currentTimeMillis()?+?EXPIRE_TIME);
          ????????String?token="";
          ????????token=?JWT.create().withAudience(user.getUserID())?//?將?user?id?保存到?token?里面
          ????????????.withExpiresAt(date)?//五分鐘后token過(guò)期
          ????????????.sign(Algorithm.HMAC256(user.getPassWord()));?//?以?password?作為?token?的密鑰
          ????????return?token;
          ????}
          }

          2.5、攔截器攔截token

          package?com.sky.springbootdemo.jwt.interceptor;
          ?
          import?com.auth0.jwt.JWT;
          import?com.auth0.jwt.JWTVerifier;
          import?com.auth0.jwt.algorithms.Algorithm;
          import?com.auth0.jwt.exceptions.JWTDecodeException;
          import?com.auth0.jwt.exceptions.JWTVerificationException;
          import?com.sky.springbootdemo.jwt.annotation.LoginToken;
          import?com.sky.springbootdemo.jwt.annotation.PassToken;
          import?com.sky.springbootdemo.jwt.entity.User;
          import?com.sky.springbootdemo.jwt.service.UserService;
          import?org.springframework.beans.factory.annotation.Autowired;
          import?org.springframework.web.method.HandlerMethod;
          import?org.springframework.web.servlet.HandlerInterceptor;
          import?org.springframework.web.servlet.ModelAndView;
          ?
          import?javax.servlet.http.HttpServletRequest;
          import?javax.servlet.http.HttpServletResponse;
          import?java.lang.reflect.Method;
          ?
          /**
          ?*?@title:?JwtInterceptor
          ?*?@Author?gjt
          ?*?@Date:?2020-12-21
          ?*?@Description:
          ?*/
          public?class?JwtInterceptor?implements?HandlerInterceptor{
          ?
          ????@Autowired
          ????private?UserService?userService;
          ?
          ????@Override
          ????public?boolean?preHandle(HttpServletRequest?httpServletRequest,?HttpServletResponse?httpServletResponse,?Object?object)?throws?Exception?{
          ????????String?token?=?httpServletRequest.getHeader("token");//?從?http?請(qǐng)求頭中取出?token
          ????????//?如果不是映射到方法直接通過(guò)
          ????????if(!(object?instanceof?HandlerMethod)){
          ????????????return?true;
          ????????}
          ????????HandlerMethod?handlerMethod=(HandlerMethod)object;
          ????????Method?method=handlerMethod.getMethod();
          ????????//檢查是否有passtoken注釋,有則跳過(guò)認(rèn)證
          ????????if?(method.isAnnotationPresent(PassToken.class))?{
          ????????????PassToken?passToken?=?method.getAnnotation(PassToken.class);
          ????????????if?(passToken.required())?{
          ????????????????return?true;
          ????????????}
          ????????}
          ????????//檢查有沒(méi)有需要用戶權(quán)限的注解
          ????????if?(method.isAnnotationPresent(LoginToken.class))?{
          ????????????LoginToken?loginToken?=?method.getAnnotation(LoginToken.class);
          ????????????if?(loginToken.required())?{
          ????????????????//?執(zhí)行認(rèn)證
          ????????????????if?(token?==?null)?{
          ????????????????????throw?new?RuntimeException("無(wú)token,請(qǐng)重新登錄");
          ????????????????}
          ????????????????//?獲取?token?中的?user?id
          ????????????????String?userId;
          ????????????????try?{
          ????????????????????userId?=?JWT.decode(token).getAudience().get(0);
          ????????????????}?catch?(JWTDecodeException?j)?{
          ????????????????????throw?new?RuntimeException("401");
          ????????????????}
          ????????????????User?user?=?userService.getUser(userId);
          ????????????????if?(user?==?null)?{
          ????????????????????throw?new?RuntimeException("用戶不存在,請(qǐng)重新登錄");
          ????????????????}
          ????????????????//?驗(yàn)證?token
          ????????????????JWTVerifier?jwtVerifier?=?JWT.require(Algorithm.HMAC256(user.getPassWord())).build();
          ????????????????try?{
          ????????????????????jwtVerifier.verify(token);
          ????????????????}?catch?(JWTVerificationException?e)?{
          ????????????????????throw?new?RuntimeException("401");
          ????????????????}
          ????????????????return?true;
          ????????????}
          ????????}
          ????????return?true;
          ????}
          ?
          ????@Override
          ????public?void?postHandle(HttpServletRequest?httpServletRequest,?HttpServletResponse?httpServletResponse,?Object?o,?ModelAndView?modelAndView)?throws?Exception?{
          ?
          ????}
          ????@Override
          ????public?void?afterCompletion(HttpServletRequest?httpServletRequest,?HttpServletResponse?httpServletResponse,?Object?o,?Exception?e)?throws?Exception?{
          ?
          ????}
          }

          2.6、注冊(cè)攔截器

          package?com.sky.springbootdemo.jwt.config;
          ?
          import?com.sky.springbootdemo.jwt.interceptor.JwtInterceptor;
          import?org.springframework.context.annotation.Bean;
          import?org.springframework.context.annotation.Configuration;
          import?org.springframework.web.servlet.config.annotation.InterceptorRegistry;
          import?org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
          ?
          /**
          ?*?@title:?InterceptorConfig
          ?*?@Author?gjt
          ?*?@Date:?2020-12-21
          ?*?@Description:
          ?*/
          @Configuration
          public?class?InterceptorConfig?implements?WebMvcConfigurer{
          ????@Override
          ????public?void?addInterceptors(InterceptorRegistry?registry)?{
          ????????registry.addInterceptor(jwtInterceptor())
          ????????????.addPathPatterns("/**");????//?攔截所有請(qǐng)求,通過(guò)判斷是否有?@LoginRequired?注解?決定是否需要登錄
          ?
          ????????//注冊(cè)TestInterceptor攔截器
          //????????InterceptorRegistration?registration?=?registry.addInterceptor(jwtInterceptor());
          //????????registration.addPathPatterns("/**");??????????????????????//添加攔截路徑
          //????????registration.excludePathPatterns(?????????????????????????//添加不攔截路徑
          //????????????"/**/*.html",????????????//html靜態(tài)資源
          //????????????"/**/*.js",??????????????//js靜態(tài)資源
          //????????????"/**/*.css",?????????????//css靜態(tài)資源
          //????????????"/**/*.woff",
          //????????????"/**/*.ttf",
          //????????????"/swagger-ui.html"
          //????????);
          ????}
          ????@Bean
          ????public?JwtInterceptor?jwtInterceptor()?{
          ????????return?new?JwtInterceptor();
          ????}
          }

          ?2.7、登錄Controller

          package?com.sky.springbootdemo.jwt.controller;
          ?
          import?com.alibaba.fastjson.JSONObject;
          import?com.sky.springbootdemo.jwt.annotation.LoginToken;
          import?com.sky.springbootdemo.jwt.entity.User;
          import?com.sky.springbootdemo.jwt.service.TokenService;
          import?com.sky.springbootdemo.jwt.service.UserService;
          import?org.springframework.beans.factory.annotation.Autowired;
          import?org.springframework.web.bind.annotation.PostMapping;
          import?org.springframework.web.bind.annotation.RestController;
          ?
          /**
          ?*?@title:?Login
          ?*?@Author?gjt
          ?*?@Date:?2020-12-22
          ?*?@Description:
          ?*/
          @RestController
          public?class?Login?{
          ?
          ????@Autowired
          ????private?UserService?userService;
          ????@Autowired
          ????private?TokenService?tokenService;
          ?
          ????@PostMapping("login")
          ????public?Object?login(String?username,?String?password){
          ????????JSONObject?jsonObject=new?JSONObject();
          ????????User?user=userService.getUser(username,?password);
          ????????if(user==null){
          ????????????jsonObject.put("message","登錄失敗!");
          ????????????return?jsonObject;
          ????????}else?{
          ????????????String?token?=?tokenService.getToken(user);
          ????????????jsonObject.put("token",?token);
          ????????????jsonObject.put("user",?user);
          ????????????return?jsonObject;
          ????????}
          ????}
          ?
          ????@LoginToken
          ????@PostMapping("/getMessage")
          ????public?String?getMessage(){
          ????????return?"你已通過(guò)驗(yàn)證";
          ????}
          }

          2.8、配置全局異常捕獲

          package?com.sky.springbootdemo.jwt.controller;
          ?
          import?com.alibaba.fastjson.JSONObject;
          import?org.springframework.web.bind.annotation.ExceptionHandler;
          import?org.springframework.web.bind.annotation.ResponseBody;
          import?org.springframework.web.bind.annotation.RestControllerAdvice;
          ?
          /**
          ?*?@title:?GlobalExceptionHandler
          ?*?@Author?gjt
          ?*?@Date:?2020-12-22
          ?*?@Description:
          ?*/
          @RestControllerAdvice
          public?class?GlobalExceptionHandler?{
          ????@ResponseBody
          ????@ExceptionHandler(Exception.class)
          ????public?Object?handleException(Exception?e)?{
          ????????String?msg?=?e.getMessage();
          ????????if?(msg?==?null?||?msg.equals(""))?{
          ????????????msg?=?"服務(wù)器出錯(cuò)";
          ????????}
          ????????JSONObject?jsonObject?=?new?JSONObject();
          ????????jsonObject.put("code",?1000);
          ????????jsonObject.put("message",?msg);
          ????????return?jsonObject;
          ????}
          }

          三、postman測(cè)試

          3.1、獲取tockem

          3.2、無(wú)tocken登錄

          3.3、有tocken登錄



          版權(quán)聲明:本文為博主原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接和本聲明。

          本文鏈接:

          https://blog.csdn.net/gjtao1130/article/details/111658060





          粉絲福利:Java從入門到入土學(xué)習(xí)路線圖

          ???

          ?長(zhǎng)按上方微信二維碼?2 秒


          感謝點(diǎn)贊支持下哈?

          瀏覽 55
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  青青草青青日青青干视频 | 色五月婷婷视频网 | 日韩黄色一级免费片 | 少妇高潮日韩 | 成人污污|