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

SpringBoot項(xiàng)目引入token設(shè)置方式

 更新時(shí)間:2025年01月06日 15:10:39   作者:陳厚伯  
本文詳細(xì)介紹了JWT(JSON Web Token)的基本概念、結(jié)構(gòu)、應(yīng)用場景以及工作原理,通過動手實(shí)踐,展示了如何在Spring Boot項(xiàng)目中實(shí)現(xiàn)JWT的生成、驗(yàn)證和攔截器配置

一. 先了解熟悉JWT(JSON Web Token)

看這些介紹、結(jié)構(gòu)之類的,確實(shí)挺無聊的;想直接進(jìn)入主題的話,就跳過第一大步。

望各位同仁給出相關(guān)意見,以備我來更加深入的學(xué)習(xí)。

1. JSON Web Token是什么鬼?

這個(gè)東西,反正理解成一個(gè)標(biāo)準(zhǔn)就行了,啥標(biāo)準(zhǔn)我也不知道。反正就是用于各種信息的安全性傳輸。

2. JSON Web令牌應(yīng)用的場景

1.授權(quán),在用戶登錄后會給用戶一個(gè)token,在用戶后續(xù)的所有請求后臺資源的操作都將攜帶這個(gè)token,只有被token允許的操作才能執(zhí)行。

2.信息交換,應(yīng)用于各種數(shù)據(jù)信息交換的場景;目前這種場景我也沒有涉及到過,嘿嘿!

3. JSON Web令牌結(jié)構(gòu)

JSON Web Tokens由dot(.)分隔的三個(gè)部分組成:Header、Payload、Signature;

因此token的形式是:

xxxxx.yyyyy.zzzzz

3.1 Header

標(biāo)頭通常由兩部分組成:令牌的類型,即JWT,以及正在使用的簽名算法,例如HMAC SHA256或RSA。

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

然后,這個(gè)JSON被編碼為Base64Url,形成JWT的第一部分

3.2 Payload

這一部分是聲明,有三種類型:注冊,公開私有聲明;

  1. 注冊
    這些是一組預(yù)定義聲明,不是強(qiáng)制性的,但建議使用,以提供一組有用的,可互操作的聲明。其中一些是:iss (issuer), exp (expiration time), sub (subject), aud(audience)等
    注:請注意,聲明名稱只有三個(gè)字符,因?yàn)镴WT意味著緊湊。
  2. 公開
    這些可以由使用JWT的人隨意定義。但為避免沖突,應(yīng)在 IANA JSON Web令牌注冊表中定義它們,或者將其定義為包含防沖突命名空間的URI
  3. 私有
    私有聲明是提供者和消費(fèi)者所共同定義的聲明,一般不建議存放敏感信息,因?yàn)閎ase64是對稱解密的,意味著該部分信息可以歸類為明文信息
    payload示例:
{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

然后,payload經(jīng)過Base64Url編碼,形成JSON Web令牌的第二部分

請注意:對于簽名令牌,此信息雖然可以防止被篡改,但任何人都可以讀取。除非加密,否則不要將秘密信息放在JWT的payload或header中。

3.3 Signature

要創(chuàng)建簽名部分,必須采用 header, payload, secret,標(biāo)頭中指定的算法,并對其進(jìn)行簽名。

例如,如果要使用HMAC SHA256算法,將按以下方式創(chuàng)建簽名:

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

3.4 token

最后輸出是三個(gè)由點(diǎn)分隔的Base64-URL字符串

4. JSON Web令牌工作原理

  1. 用戶登陸的時(shí)候使用用戶名和密碼發(fā)送POST請求
  2. 服務(wù)器使用私鑰創(chuàng)建一個(gè)jwt
  3. 服務(wù)器返回這個(gè)jwt到瀏覽器
  4. 瀏覽器將該jwt串加入請求頭中向服務(wù)器發(fā)送請求
  5. 服務(wù)器驗(yàn)證jwt
  6. 返回相應(yīng)的資源給客戶端

二. 動手開始搞

1.引入依賴

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

2. 定義注解

package com.example.fighting.config;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

public class UserToken {

//    跳過驗(yàn)證
    @Target({ElementType.METHOD, ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface PassToken {
        boolean required() default true;
    }

//    需要驗(yàn)證
    @Target({ElementType.METHOD, ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface UserLoginToken {
        boolean required() default true;
    }
}

3.新增TokenService接口類和TokenServiceImpl實(shí)現(xiàn)類

package com.example.fighting.serviceImpl;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.example.fighting.bean.UserTest;
import com.example.fighting.service.TokenService;
import org.springframework.stereotype.Service;

@Service
public class TokenServiceImpl implements TokenService {

    @Override
    public String getToken(UserTest userTest) {
        String token="";
        token= JWT.create().withAudience(userTest.getId().toString())
                .sign(Algorithm.HMAC256(userTest.getPassword()));
        return token;
    }
}

4.新增攔截器

package com.example.fighting.config;

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.example.fighting.bean.UserTest;
import com.example.fighting.service.UserTestService;
import jdk.nashorn.internal.ir.annotations.Reference;
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;

public class AuthenticationInterceptor implements HandlerInterceptor {
    @Autowired
//    @Reference
    UserTestService userTestService;

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
        String token = httpServletRequest.getHeader("token");// 從 http 請求頭中取出 token
        // 如果不是映射到方法直接通過
        if (!(object instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) object;
        Method method = handlerMethod.getMethod();
        //檢查是否有passtoken注釋,有則跳過認(rèn)證
        if (method.isAnnotationPresent(UserToken.PassToken.class)) {
            UserToken.PassToken passToken = method.getAnnotation(UserToken.PassToken.class);
            if (passToken.required()) {
                return true;
            }
        }
        //檢查有沒有需要用戶權(quán)限的注解
        if (method.isAnnotationPresent(UserToken.UserLoginToken.class)) {
            UserToken.UserLoginToken userLoginToken = method.getAnnotation(UserToken.UserLoginToken.class);
            if (userLoginToken.required()) {
                // 執(zhí)行認(rèn)證
                if (token == null) {
                    throw new RuntimeException("無token,請重新登錄");
                }
                // 獲取 token 中的 user id
                String userId;
                try {
                    userId = JWT.decode(token).getAudience().get(0);
                } catch (JWTDecodeException j) {
                    throw new RuntimeException("401");
                }
                UserTest user = userTestService.findUserTestById(Long.parseLong(userId));
                if (user == null) {
                    throw new RuntimeException("用戶不存在,請重新登錄");
                }
                // 驗(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 {
    }
}

5.添加攔截器配置

package com.example.fighting.interceptor;

import com.example.fighting.config.AuthenticationInterceptor;
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;

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authenticationInterceptor())
                .addPathPatterns("/**");
    }
    @Bean
    public AuthenticationInterceptor authenticationInterceptor() {
        return new AuthenticationInterceptor();
    }
}

6. 在controller中添加登錄接口

//登錄
    @ApiOperation(value="登錄接口",notes ="驗(yàn)證登錄后獲取一個(gè)token")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType="query",name="username",value="賬號",required = true),
            @ApiImplicitParam(paramType="query",name="password",value="密碼",required = true)
    })
    @PostMapping("/login")
    @ResponseBody
    public Map login(UserTest user) {
        Map<Object, Object> map = new HashMap<>();
        UserTest userForBase = userTestService.findUserTestByUserName(user.getUsername());
        if (userForBase == null) {
            map.put("message", "登錄失敗,用戶不存在");
            return map;
        } else {
            if (!userForBase.getPassword().equals(user.getPassword())) {
                map.put("message", "登錄失敗,密碼錯(cuò)誤");
                return map;
            } else {
                String token = tokenService.getToken(userForBase);
                map.put("token", token);
                map.put("user", userForBase);
                return map;
            }
        }
    }
    @ApiOperation(value="測試token",notes ="測試token是否通過")
    @UserToken.UserLoginToken
    @GetMapping("/getMessage")
    public String getMessage() {
        return "你已通過驗(yàn)證";
    }

7.接口測試

1.用postman不加token訪問

調(diào)接口:http://localhost:8014/userTest/getMessage

后臺打印結(jié)果:

2.用postman添加錯(cuò)誤的token訪問

打印結(jié)果:

3.正常登錄,使用登錄后返回的token

登錄接口:http://localhost:8014/userTest/login

調(diào)接口測試token是否生效:

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringBoot集成mybatis連接oracle的圖文教程

    SpringBoot集成mybatis連接oracle的圖文教程

    這篇文章主要介紹了Spring Boot集成mybatis連接oracle的圖文教程,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • maven中springboot-maven-plugin的5種打包方式

    maven中springboot-maven-plugin的5種打包方式

    本文主要介紹了maven中springboot-maven-plugin的5種打包方式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-09-09
  • SpringBoot全局異常捕獲參數(shù)以及參數(shù)異常的解決方案

    SpringBoot全局異常捕獲參數(shù)以及參數(shù)異常的解決方案

    這篇文章主要介紹了SpringBoot全局異常捕獲參數(shù)以及參數(shù)異常的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-05-05
  • SpringBoot整合EasyExcel實(shí)現(xiàn)導(dǎo)入導(dǎo)出功能

    SpringBoot整合EasyExcel實(shí)現(xiàn)導(dǎo)入導(dǎo)出功能

    EasyExcel是一個(gè)基于Java的、快速、簡潔、解決大文件內(nèi)存溢出的Excel處理工具,他能讓你在不用考慮性能、內(nèi)存的等因素的情況下,快速完成Excel的讀、寫等功能,本文就給大家介紹一下SpringBoot整合EasyExcel實(shí)現(xiàn)導(dǎo)入導(dǎo)出功能的方法,需要的朋友可以參考下
    2023-09-09
  • java同一個(gè)類中,一個(gè)無事務(wù)方法調(diào)用一個(gè)有事務(wù)方法時(shí),事務(wù)失效問題

    java同一個(gè)類中,一個(gè)無事務(wù)方法調(diào)用一個(gè)有事務(wù)方法時(shí),事務(wù)失效問題

    本文詳細(xì)介紹了Spring框架中事務(wù)管理的實(shí)現(xiàn)原理,包括@Transactional注解的使用、事務(wù)的開啟、提交和回滾機(jī)制,以及代理對象的兩種實(shí)現(xiàn)方式(JDK動態(tài)代理和CGLIB代理),文章還探討了在同一個(gè)類中調(diào)用有事務(wù)方法時(shí)事務(wù)失效的原因,并提供了解決方法
    2024-12-12
  • Java標(biāo)識接口的使用方法

    Java標(biāo)識接口的使用方法

    在本篇文章中小編給大家分享了關(guān)于Java標(biāo)識接口的使用方法和教程內(nèi)容,有需要的朋友們學(xué)習(xí)下。
    2019-01-01
  • 使用Java發(fā)送帶附件的附件的示例

    使用Java發(fā)送帶附件的附件的示例

    這篇文章主要介紹了使用Java發(fā)送帶附件的附件的方法,使用到了JavaMail這個(gè)API,需要的朋友可以參考下
    2015-11-11
  • 深入研究spring boot集成kafka之spring-kafka底層原理

    深入研究spring boot集成kafka之spring-kafka底層原理

    這篇文章主要深入研究了spring boot集成kafka如何實(shí)現(xiàn)spring-kafka的底層原理分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2022-02-02
  • 值得Java程序猿閱讀的書籍

    值得Java程序猿閱讀的書籍

    這篇文章主要推薦了一些值得Java程序猿閱讀的書籍,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • MyBatis中#{}和${}的區(qū)別詳解

    MyBatis中#{}和${}的區(qū)別詳解

    mybatis和ibatis總體來講都差不多的。下面小編給大家探討下mybatis中#{}和${}的區(qū)別,感興趣的朋友一起學(xué)習(xí)吧
    2016-08-08

最新評論

越西县| 汨罗市| 新晃| 普陀区| 衡阳市| 台江县| 德兴市| 惠来县| 青川县| 炎陵县| 漳浦县| 华亭县| 吕梁市| 麦盖提县| 庆元县| 丰原市| 两当县| 彭州市| 东辽县| 兴安县| 福海县| 亳州市| 高密市| 平果县| 寿光市| 石景山区| 泰安市| 黄山市| 方城县| 揭东县| 定南县| 太和县| 大埔区| 乌苏市| 惠水县| 沅江市| 丰城市| 兴仁县| 新余市| 门头沟区| 新宁县|