欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

在SpringBoot中使用jwt實(shí)現(xiàn)token身份認(rèn)證的實(shí)例代碼

 更新時(shí)間:2023年09月02日 10:02:24   作者:金金金__  
你還不會(huì)在SpringBoot中使用jwt實(shí)現(xiàn)token身份認(rèn)證嗎,本文小編就給大家詳細(xì)的介紹一下在SpringBoot中使用jwt實(shí)現(xiàn)token身份認(rèn)證的實(shí)例代碼,感興趣的同學(xué)可以自己動(dòng)手試一試
  • jwt (JSON Web Tokens)

jwt結(jié)構(gòu)

  • 用(.)分割的三個(gè)部位組成
    • 標(biāo)頭
    • 有效載荷
    • 簽名

xxx.xxx.xxx

標(biāo)頭

  • 標(biāo)頭通常由兩部分組成:令牌的類型(JWT)和所使用的簽名算法(例如 HMAC SHA256 或 RSA
{ "alg": "HS256", "typ": "JWT" }
  • 然后,對(duì)該 JSON 進(jìn)行Base64Url編碼以形成 JWT 的第一部分。

有效載荷

  • 令牌的第二部分是有效負(fù)載,其中包含聲明。聲明是關(guān)于實(shí)體(通常是用戶)和附加數(shù)據(jù)的聲明。索賠分為三種類型:注冊(cè)索賠、公開索賠和私人索賠。
  1. 注冊(cè)聲明
    • 這些是一組預(yù)定義的聲明,不是強(qiáng)制性的,而是推薦的,以提供一組有用的、可互操作的聲明。其中一些是: iss(發(fā)行者)、 exp(到期時(shí)間)、 sub(主題)、 aud(受眾)等。
  2. 公共聲明
    • 這些可以由使用 JWT 的人隨意定義。但為了避免沖突,它們應(yīng)該在[IANA JSON Web Token Registry]中定義,或者定義為包含防沖突命名空間的 URI
  3. 私人聲明
    • 這些是為在同意使用它們的各方之間共享信息而創(chuàng)建的自定義聲明,既不是注冊(cè)聲明也不是公開聲明。

有效負(fù)載示例

{ "sub": "1234567890", "name": "John Doe", "admin": true }
  • 然后對(duì)有效負(fù)載進(jìn)行Base64Url編碼以形成 JSON Web 令牌的第二部分。

請(qǐng)注意,對(duì)于簽名令牌,此信息雖然受到防止篡改的保護(hù),但任何人都可以讀取。除非加密,否則請(qǐng)勿將秘密信息放入 JWT 的有效負(fù)載或標(biāo)頭元素中。

簽名

  • 要?jiǎng)?chuàng)建簽名部分,您必須獲取編碼的標(biāo)頭、編碼的有效負(fù)載、秘密、標(biāo)頭中指定的算法,然后對(duì)其進(jìn)行簽名。

使用HMAC SHA256算法,則將通過以下方式創(chuàng)建簽名

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

簽名用于驗(yàn)證消息在傳輸過程中沒有發(fā)生更改,并且在使用私鑰簽名的令牌的情況下,它還可以驗(yàn)證 JWT 的發(fā)送者是否是其所說的人。

將所有內(nèi)容放在一起

  • 輸出是三個(gè)由點(diǎn)分隔的 Base64-URL 字符串,可以在 HTML 和 HTTP 環(huán)境中輕松傳遞,同時(shí)與基于 XML 的標(biāo)準(zhǔn)(例如 SAML)相比更加緊湊。
  • 下面顯示了一個(gè) JWT,它具有先前的標(biāo)頭和有效負(fù)載編碼,并且使用密鑰進(jìn)行簽名。

image.png

  • 官網(wǎng)翻譯的,先了解一點(diǎn)前置知識(shí),開整!

使用

依賴

  • pom.xml文件咱們先加入jwt的依賴

image.png

JwtTokenUtils工具類

public class JwtTokenUtils {
  // token私鑰
  private static final String TOKEN_SECRET = "jwtSECRET";
  // token過期時(shí)長(zhǎng)30分鐘
  private static final long EXPIRE_TIME = 1800L; // 單位為秒
  /**
   * 生成用戶token,設(shè)置token超時(shí)時(shí)間
   *
   * @return 生成的token
   */
   public static String createToken(LoginVo loginVo) {
    Date expireDate = new Date(System.currentTimeMillis() + EXPIRE_TIME * 1000);
    // 創(chuàng)建 Token 的 payload
    Map<String, Object> map = new HashMap<>();
    map.put("alg", "HS256");
    map.put("typ", "JWT");
    // 生成 JWT Token
    String token = JWT.create()
      .withHeader(map)// 添加頭部
      .withClaim("account", loginVo.getAccount())
      .withExpiresAt(expireDate) //超時(shí)設(shè)置,設(shè)置過期的日期
      .withIssuedAt(new Date()) //簽發(fā)時(shí)間
      .sign(Algorithm.HMAC256(TOKEN_SECRET)); //SECRET加密
    return token;
  }
  /**
   * 檢驗(yàn)token是否正確
   * @param token 需要校驗(yàn)的token
   * @return 校驗(yàn)是否成功
   */
  public static Map<String, Claim> verifyToken(String token) {
    DecodedJWT jwt = null;
    token = token.replace("Bearer ", ""); // 這里要去掉Bearer ,postman默認(rèn)會(huì)加這個(gè),導(dǎo)致匹配不上
    try {
      //設(shè)置簽名的加密算法:HMAC256
      Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET); // 私鑰需要一致
      JWTVerifier verifier = JWT.require(algorithm).build();
      jwt = verifier.verify(token);
    } catch (Exception e) {
//      logger.error(e.getMessage()); // 還沒安裝log4j等日志依賴,先注釋
//      logger.error("token解碼異常");
      //解碼異常則拋出異常
      return null;
    }
    return jwt.getClaims();
  }
}
  1. createToken方法主要就是創(chuàng)建token,并把賬號(hào)密碼作為自定義聲明添加到 JWT 的 payload 中,最終返回
  2. verifyToken方法其實(shí)就是解碼 token 并將其轉(zhuǎn)換成 DecodedJWT 對(duì)象,通過 getClaims() 方法獲取 payload 中的所有聲明信息,并以 Map 的形式返回,如果 token 不合法或者解碼過程中出現(xiàn)異常,則返回 null,校驗(yàn)的效果。
  • 注意Bearer 這個(gè)玩意

JwtFilter.java

@Component
@WebFilter(filterName = "JwtFilter", urlPatterns = "/*")
public class JwtFilter implements Filter {
  @Override
  public void init(FilterConfig filterConfig) throws ServletException {
    System.out.println("jwt初始化方法");
  }
  @Override
  public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
    final HttpServletRequest request = (HttpServletRequest) req;
    final HttpServletResponse response = (HttpServletResponse) res;
    response.setCharacterEncoding("UTF-8");
    final String token = request.getHeader("Authorization");
    String requestPath = request.getRequestURI();
    // 登錄接口,直接放行
    if (requestPath.contains("/user/login")) {
      chain.doFilter(request, response);
      return;
    }
     if ("OPTIONS".equals(request.getMethod())) { // 是否是 OPTIONS 請(qǐng)求
      response.setStatus(HttpServletResponse.SC_OK);
      chain.doFilter(request, response);
    } else {
      if (token == null) {
        response.getWriter().write("沒有令牌");
        return;
      }
      Map<String, Claim> userData = JwtTokenUtils.verifyToken(token); // 檢驗(yàn) token
      if (userData == null) {
        response.getWriter().write("令牌非法");
        return;
      }
      String account = userData.get("account").asString(); // 獲取用戶名
      request.setAttribute("account", account); // 設(shè)置用戶名
      chain.doFilter(req, res); // 過濾成功
    }
  }
  @Override
  public void destroy() {
    System.out.println("jwt銷毀方法執(zhí)行的邏輯");
  }
}
  • 這其實(shí)就是一個(gè)過濾類,你請(qǐng)求接口前就會(huì)先到這里,執(zhí)行相對(duì)應(yīng)的邏輯。
  1. init: 初始化方法
  2. doFilter:過濾攔截方法(主要邏輯就寫在這)
  3. destroy:銷毀方法

注意

  1. urlPatterns = "/*" : 這個(gè)代表攔截所有的請(qǐng)求,我在 doFilter 里面判斷了包含 /login 直接放行。意思就是登錄接口直接放行,返回 token 給前端,如果是別的請(qǐng)求則走對(duì)應(yīng)邏輯。
  2. @Component :這個(gè)需要加上,這樣才能掃描到你這個(gè)類不然不生效的。或者你在啟動(dòng)類加上 @ServletComponentScan(basePackages = "com.yjx.boot.config") ,我的過濾器是寫在 config 包下的。

LoginController

@Controller
@RestController  // 可處理 HTTP 請(qǐng)求的控制器,并且能夠返回?cái)?shù)據(jù)給客戶端
@RequestMapping("/user")
@RequiredArgsConstructor
public class LoginController {
  private final AdminService adminService;
  // 用戶登陸
  @GetMapping("/login")
  ResultVO<Object> login(LoginVo loginVo) {
    Admin admin = new Admin();
    admin.setAccount(loginVo.getAccount());
    admin.setAdminPassword(loginVo.getAdminPassword());
    // 查找是否有該管理員
    Admin an = adminService.queryByAdmin(admin);
    if (an == null) {
      return ResultResponse.failure(ResultCodeEnum.INTERNAL_NOT_FOUND);
    } else {
      String token = JwtTokenUtils.createToken(loginVo);
      loginVo.setToken(token);
      an.setToken(token);
      return ResultResponse.success(an);
    }
  }
  @GetMapping("/secure/current_registrant")
  public String currentRegistrant(HttpServletRequest request) {
    System.out.println("request" + request);
    String id = request.getParameter("id");
    String account = request.getParameter("account");
    String user_password = request.getParameter("adminPassword");
    return "當(dāng)前用戶信息: id=" + id + " ,account=" + account + " ,user_password=" + user_password;
  }
}
  • 代碼部分就完事了,測(cè)試一下。

測(cè)試

  • 我們請(qǐng)求下/secure/current_registrant接口,此時(shí)是沒有token的。

image.png

正常,輸出了我們想要的:沒有令牌

  • 我們先去請(qǐng)求/login,看看token以及用戶信息會(huì)不會(huì)如我們所想 返回給我們呢?

image.png

很好,也拿到了我們想要的,token也返回了,我們復(fù)制一下這個(gè)token,我們?cè)俅握?qǐng)求/secure/current_registrant,并把token放入請(qǐng)求頭,試試能不能成功

image.png

  • 成功

我們來試試把token寫錯(cuò)一個(gè)字母會(huì)輸出什么。

image.png

我們?cè)谡?qǐng)求頭不傳入token呢

image.png

完事!測(cè)試成功!寫的并沒有很好 甚至可能有些地方都寫錯(cuò)了,慢慢完善吧

以上就是在SpringBoot中使用jwt實(shí)現(xiàn)token身份認(rèn)證的實(shí)例代碼的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot jwt實(shí)現(xiàn)token認(rèn)證的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • ssm項(xiàng)目改造spring?boot項(xiàng)目完整步驟

    ssm項(xiàng)目改造spring?boot項(xiàng)目完整步驟

    Spring?Boot現(xiàn)在已經(jīng)成為Java開發(fā)領(lǐng)域的一顆璀璨明珠,它本身是包容萬象的,可以跟各種技術(shù)集成,下面這篇文章主要給大家介紹了關(guān)于ssm項(xiàng)目改造spring?boot項(xiàng)目的相關(guān)資料,需要的朋友可以參考下
    2023-04-04
  • 在Spring Boot中如何使用數(shù)據(jù)緩存

    在Spring Boot中如何使用數(shù)據(jù)緩存

    本篇文章主要介紹了在Spring Boot中如何使用數(shù)據(jù)緩存,具有一定的參考價(jià)值,有興趣的可以了解一下。
    2017-04-04
  • Java8函數(shù)式編程應(yīng)用小結(jié)

    Java8函數(shù)式編程應(yīng)用小結(jié)

    Java8非常重要的就是引入了函數(shù)式編程的思想,使得這門經(jīng)典的面向?qū)ο笳Z言有了函數(shù)式的編程方式,彌補(bǔ)了很大程度上的不足,函數(shù)式思想在處理復(fù)雜問題上有著更為令人稱贊的特性,本文給大家介紹Java8函數(shù)式編程應(yīng)用小結(jié),感興趣的朋友一起看看吧
    2023-12-12
  • Spring打包jar包時(shí)jsp頁面無法訪問問題解決

    Spring打包jar包時(shí)jsp頁面無法訪問問題解決

    這篇文章主要介紹了Spring打包jar包時(shí)jsp頁面無法訪問問題解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • idea使用spring Initializr 快速搭建springboot項(xiàng)目遇到的坑

    idea使用spring Initializr 快速搭建springboot項(xiàng)目遇到的坑

    這篇文章主要介紹了idea使用spring Initializr 快速搭建springboot項(xiàng)目遇到的坑,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • 關(guān)于Seata基本使用及二階提交流程

    關(guān)于Seata基本使用及二階提交流程

    這篇文章主要介紹了關(guān)于Seata基本使用及二階提交流程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • SpringBoot整合Minio的過程(支持公有及私有bucket)

    SpringBoot整合Minio的過程(支持公有及私有bucket)

    Bucket 是存儲(chǔ)Object的邏輯空間,每個(gè)Bucket之間的數(shù)據(jù)是相互隔離的,對(duì)用戶而言,相當(dāng)于存放文件的頂層文件夾,這篇文章主要介紹了SpringBoot整合Minio的過程(支持公有及私有bucket),需要的朋友可以參考下
    2025-03-03
  • IntelliJ IDEA 2020.1 EAP4 發(fā)布,重命名/更改簽名新功能一覽

    IntelliJ IDEA 2020.1 EAP4 發(fā)布,重命名/更改簽名新功能一覽

    這篇文章主要介紹了IntelliJ IDEA 2020.1 EAP4 發(fā)布,重命名/更改簽名新功能,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-04-04
  • 圖文詳解java反射機(jī)制及常用應(yīng)用場(chǎng)景

    圖文詳解java反射機(jī)制及常用應(yīng)用場(chǎng)景

    這篇文章主要為大家介紹了圖文詳解java反射機(jī)制及常用應(yīng)用場(chǎng)景,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-03-03
  • JSONObject?toJSONString錯(cuò)誤的解決

    JSONObject?toJSONString錯(cuò)誤的解決

    這篇文章主要介紹了JSONObject?toJSONString錯(cuò)誤的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02

最新評(píng)論