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>

        Spring Boot 如何集成JWT實(shí)現(xiàn)Token驗(yàn)證

        共 5398字,需瀏覽 11分鐘

         ·

        2021-12-14 14:16

        近年來,隨著前后端分離、微服務(wù)等架構(gòu)的興起,傳統(tǒng)的cookie+session身份驗(yàn)證模式已經(jīng)逐漸被基于Token的身份驗(yàn)證模式取代。接下來介紹如何在Spring Boot項(xiàng)目中集成JWT實(shí)現(xiàn)Token驗(yàn)證。

        一、JWT入門

        1.什么是JWT

        JWT (Json web token)是為了在網(wǎng)絡(luò)應(yīng)用環(huán)境間傳遞聲明而執(zhí)行的一種基于JSON的開放標(biāo)準(zhǔn)((RFC 7519)。它定義了一種緊湊的,自包含的方式,用于通信雙方之間以JSON對(duì)象的形式安全傳遞信息。JWT使用HMAC算法或者是RSA的公私秘鑰的數(shù)字簽名技術(shù),所以這些信息是可被驗(yàn)證和信任的。


        JWT官網(wǎng):https://jwt.io/

        JWT(Java版)的github地址:https://github.com/jwtk/jjwt


        2.JWT的結(jié)構(gòu)

        在使用 JWT 前,需要先了解它的組成結(jié)構(gòu)。它是由以下三段信息構(gòu)成的:

        • Header 頭部(包含簽名和/或加密算法的類型)

        • Payload 載荷 (存放有效信息)

        • Signature 簽名/簽證

        將這三段信息文本用‘.’連接一起就構(gòu)成完整的JWT字符串,也是就我們需要的Token。如下所示:

        eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0aW1lU3RhbXAiOjE2MzkwNDc1NTMxNjksInVzZXJSb2xlIjoiUk9MRV9BRE1JTiIsInVzZXJJZCI6ImFkbWluIn0.UFQLvaiQ1AThx9Fa4SRqNg-b9HPJ9y1TlgQB4-F3pi0

        JWT的數(shù)據(jù)結(jié)構(gòu)還是比較復(fù)雜的,Header,Payload,Signature中包含了很多信息,建議大家最好是能夠了解。

        3.JWT的請(qǐng)求流程

        JWT的請(qǐng)求流程也特別簡單,首先使用賬號(hào)登錄獲取Token,然后后面的各種請(qǐng)求,都帶上這個(gè)Token即可。具體流程如下:

        1. 客戶端發(fā)起登錄請(qǐng)求,傳入賬號(hào)密碼;

        2. 服務(wù)端使用私鑰創(chuàng)建一個(gè)Token;

        3. 服務(wù)器返回Token給客戶端;

        4. 客戶端向服務(wù)端發(fā)送請(qǐng)求,在請(qǐng)求頭中該Token;

        5. 服務(wù)器驗(yàn)證該Token;

        6. 返回結(jié)果。


        二、Spring Boot 如何集成JWT

        JWT提供了基于Java組件:java-jwt幫助我們?cè)赟pring Boot項(xiàng)目中快速集成JWT,接下來進(jìn)行SpringBoot和JWT的集成。

        1.引入JWT依賴

        創(chuàng)建普通的Spring Boot項(xiàng)目,修改項(xiàng)目中的pom.xml文件,引入JWT等依賴。示例代碼如下:

        <dependency>    <groupId>com.auth0groupId>    <artifactId>java-jwtartifactId>    <version>3.10.3version>dependency><dependency>    <groupId>org.springframework.bootgroupId>    <artifactId>spring-boot-starter-webartifactId>dependency>

        2.創(chuàng)建&驗(yàn)證Token

        創(chuàng)建通用的處理類TokenUtil,負(fù)責(zé)創(chuàng)建和驗(yàn)證Token。示例代碼如下:

        @Componentpublic class TokenUtil {    @Value("${token.secretKey}")    private String secretKey;    /**     * 加密token.     */    public String getToken(String userId, String userRole) {        //這個(gè)是放到負(fù)載payLoad 里面,魔法值可以使用常量類進(jìn)行封裝.        String token = JWT                .create()                .withClaim("userId" ,userId)                .withClaim("userRole", userRole)                .withClaim("timeStamp", System.currentTimeMillis())                .sign(Algorithm.HMAC256(secretKey));        return token;    }    /**     * 解析token.     * {     * "userId": "weizhong",     * "userRole": "ROLE_ADMIN",     * "timeStamp": "134143214"     * }     */    public Map<String, String> parseToken(String token) {        HashMap<String, String> map = new HashMap<String, String>();        DecodedJWT decodedjwt = JWT.require(Algorithm.HMAC256(secretKey))                .build().verify(token);        Claim userId = decodedjwt.getClaim("userId");        Claim userRole = decodedjwt.getClaim("userRole");        Claim timeStamp = decodedjwt.getClaim("timeStamp");        map.put("userId", userId.asString());        map.put("userRole", userRole.asString());        map.put("timeStamp", timeStamp.asLong().toString());        return map;    }}

        3.創(chuàng)建攔截器,驗(yàn)證Token

        創(chuàng)建一個(gè)攔截器AuthHandlerInterceptor,負(fù)責(zé)攔截所有Http請(qǐng)求,驗(yàn)證Token是否有效。示例代碼如下:

        @Slf4j@Componentpublic class AuthHandlerInterceptor implements HandlerInterceptor {    @Autowired    TokenUtil tokenUtil;    @Value("${token.refreshTime}")    private Long refreshTime;    @Value("${token.expiresTime}")    private Long expiresTime;    /**     * 權(quán)限認(rèn)證的攔截操作.     */    @Override    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {        log.info("=======進(jìn)入攔截器========");        // 如果不是映射到方法直接通過,可以訪問資源.        if (!(object instanceof HandlerMethod)) {            return true;        }        //為空就返回錯(cuò)誤        String token = httpServletRequest.getHeader("token");        if (null == token || "".equals(token.trim())) {            return false;        }        log.info("==============token:" + token);        Map map = tokenUtil.parseToken(token);        String userId = map.get("userId");        String userRole = map.get("userRole");        long timeOfUse = System.currentTimeMillis() - Long.parseLong(map.get("timeStamp"));        //1.判斷 token 是否過期        if (timeOfUse < refreshTime) {            log.info("token驗(yàn)證成功");            return true;        }        //超過token刷新時(shí)間,刷新 token        else if (timeOfUse >= refreshTime && timeOfUse < expiresTime) {            httpServletResponse.setHeader("token",tokenUtil.getToken(userId,userRole));            log.info("token刷新成功");            return true;        }        //token過期就返回 token 無效.        else {            throw new TokenAuthExpiredException();        }    }}

        攔截器創(chuàng)建之后,需要將攔截器注冊(cè)到Spring Boot中。這和其他的攔截器注冊(cè)是一樣的。示例代碼如下:

        @Configurationpublic class AuthWebMvcConfigurer implements WebMvcConfigurer {    @Autowired    AuthHandlerInterceptor authHandlerInterceptor;    /**     * 給除了 /login 的接口都配置攔截器,攔截轉(zhuǎn)向到 authHandlerInterceptor     */    @Override    public void addInterceptors(InterceptorRegistry registry) {        registry.addInterceptor(authHandlerInterceptor)                .addPathPatterns("/**")                .excludePathPatterns("/login");    }}

        4.創(chuàng)建控制器

        創(chuàng)建TokenTestController控制器,處理HTTP請(qǐng)求。示例代碼如下:

        @RestControllerpublic class TokenTestController {    @Autowired    TokenUtil tokenUtil;    @PostMapping("/login")    public String login(@RequestBody LoginUser user){        // 先驗(yàn)證用戶的賬號(hào)密碼,賬號(hào)密碼驗(yàn)證通過之后,生成Token        String role = "ROLE_ADMIN";        String token = tokenUtil.getToken(user.username,role);        return token;    }    @PostMapping("/testToken")    public String testToken(HttpServletRequest request){        String token = request.getHeader("token");        tokenUtil.parseToken(token);        return "請(qǐng)求成功";    }}


        5.測(cè)試驗(yàn)證

        集成JWT成功之后,接下來驗(yàn)證Token是否成功,啟動(dòng)項(xiàng)目。在Postman中調(diào)用相關(guān)接口,驗(yàn)證功能是否正常。

        首先,調(diào)用http://localhost:8080/testToken,獲取token


        然后,調(diào)用http://localhost:8080/testToken 驗(yàn)證token是否有效。


        最后

        以上,我們就把Spring Boot集成JWT實(shí)現(xiàn)Token驗(yàn)證介紹完了。身份驗(yàn)證是Web開發(fā)中非常基礎(chǔ)的功能,后面還會(huì)介紹授權(quán)及權(quán)限管理等內(nèi)容。


        瀏覽 44
        點(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>
            亚洲黄色视频在线 | 免费一级a毛片免费观看 | 亚洲成人在线影视 | 国产小姐操逼视频 | 插逼视频欧美 | 在线观看黄国产 | 国产AV一区二区三区传媒 | 日韩无码视频网 | 麻豆91在线视频 | 男人和女人日b视频 |