1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        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從入門(mén)到精通實(shí)戰(zhàn)課程分享

        Jwt全稱(chēng)是:json web token。它將用戶(hù)信息加密到token里,服務(wù)器不保存任何用戶(hù)信息。服務(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ù)載中可以包含用戶(hù)所需要的信息,避免了多次查詢(xún)數(shù)據(jù)庫(kù);

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

        4. 不需要在服務(wù)端保存會(huì)話(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. 聲明類(lèi)型,這里是Jwt

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

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

        JWS算法名稱(chēng)
        HS256HMAC256
        HS384HMAC384
        HS512HMAC512
        RS256RSA256
        RS384RSA384
        RS512RSA512
        ES256ECDSA256
        ES384ECDSA384
        ES512ECDSA512

        1.3 playload

        載荷就是存放有效信息的地方?;旧咸?/span>2種類(lèi)型數(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所面向的用戶(hù)
        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)目依賴(lài) 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、用戶(hù)實(shí)體類(lèi)、及查詢(xún)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注釋?zhuān)袆t跳過(guò)認(rèn)證
        ????????if?(method.isAnnotationPresent(PassToken.class))?{
        ????????????PassToken?passToken?=?method.getAnnotation(PassToken.class);
        ????????????if?(passToken.required())?{
        ????????????????return?true;
        ????????????}
        ????????}
        ????????//檢查有沒(méi)有需要用戶(hù)權(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("用戶(hù)不存在,請(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從入門(mén)到入土學(xué)習(xí)路線(xiàn)圖

        ???

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


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

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

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            黄色成人在线免费观看 | 免费淫片aa直播app | 人善交video另类hd男人 | 人人超碰人人 | 操操操网站 | 日皮视频免费在线观看 | 国产欧美精品日韩区二区麻豆天美 | 国产又粗又大又爽91嫩草 | 女生被人操 | 国产伦精品一区二区三区视频金莲 |