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

SpringBoot集成JWT令牌詳細(xì)說(shuō)明

 更新時(shí)間:2023年10月25日 10:01:24   作者:刻苦的樊同學(xué)  
這篇文章主要介紹了SpringBoot集成JWT令牌詳細(xì)說(shuō)明,JWT方式校驗(yàn)方式更加簡(jiǎn)單便捷化,無(wú)需通過(guò)redis緩存,而是直接根據(jù)token取出保存的用戶信息,以及對(duì)token可用性校驗(yàn),單點(diǎn)登錄,驗(yàn)證token更為簡(jiǎn)單,需要的朋友可以參考下

一,傳統(tǒng)Cookie+Session與JWT對(duì)比

1, 在傳統(tǒng)的用戶登錄認(rèn)證中,因?yàn)閔ttp是無(wú)狀態(tài)的,所以都是采用session方式。用戶登錄成功,服務(wù)端會(huì)保證一個(gè)session,當(dāng)然會(huì)給客戶端一個(gè)sessionId,客戶端會(huì)把sessionId保存在cookie中,每次請(qǐng)求都會(huì)攜帶這個(gè)sessionId。

2,cookie+session這種模式通常是保存在內(nèi)存中,而且服務(wù)從單服務(wù)到多服務(wù)會(huì)面臨的session共享問(wèn)題,隨著用戶量的增多,開(kāi)銷就會(huì)越大。而JWT不是這樣的,只需要服務(wù)端生成token,客戶端保存這個(gè)token,每次請(qǐng)求攜帶這個(gè)token,服務(wù)端認(rèn)證解析就可。

3, JWT方式校驗(yàn)方式更加簡(jiǎn)單便捷化,無(wú)需通過(guò)redis緩存,而是直接根據(jù)token取出保存的用戶信息,以及對(duì)token可用性校驗(yàn),單點(diǎn)登錄,驗(yàn)證token更為簡(jiǎn)單。

二,springboot集成jwt

1,jwt的整合依賴

		<!-- JWT依賴 -->
		<dependency>
			<groupId>io.jsonwebtoken</groupId>
			<artifactId>jjwt</artifactId>
			<version>0.7.0</version>
		</dependency>
		<dependency>
			<groupId>com.auth0</groupId>
			<artifactId>java-jwt</artifactId>
			<version>3.4.0</version>
		</dependency>

2,jwt的自定義配置

server:
  port: 8080
spring:
  application:
    name: springboot-jwt

# 自定義配置
config:
  jwt:
    # 加密密鑰
    secret: abcdefg1234567
    # token有效時(shí)長(zhǎng)
    expire: 3600
     # header 名稱
    header: token

3,編寫JwtConfig

JwtConfig負(fù)責(zé)

  • 生成token
  • 獲取token中的注冊(cè)信息
  • 驗(yàn)證token是否過(guò)期失效
  • 獲取token失效時(shí)間
  • 從token中獲取用戶名
  • 獲取jwt發(fā)布時(shí)間
package com.ftx.jwt.config;

/**
 * @author FanJiangFeng
 * @version 1.0.0
 * @ClassName JwtConfig.java
 * @Description TODO
 * @createTime 2020年06月22日 15:43:00
 */

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * JWT的token,區(qū)分大小寫
 */
@ConfigurationProperties(prefix = "config.jwt", ignoreUnknownFields = true)
@Component
public class JwtConfig {

    private String secret;
    private long expire;
    private String header;

    /**
     * 生成token
     * @param subject
     * @return
     */
    public String createToken (String subject){
        Date nowDate = new Date();
        Date expireDate = new Date(nowDate.getTime() + expire * 1000);//過(guò)期時(shí)間

        return Jwts.builder()
                .setHeaderParam("typ", "JWT")
                .setSubject(subject)
                .setIssuedAt(nowDate)
                .setExpiration(expireDate)
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();
    }
    /**
     * 獲取token中注冊(cè)信息
     * @param token
     * @return
     */
    public Claims getTokenClaim (String token) {
        try {
            return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
        }catch (Exception e){
//            e.printStackTrace();
            return null;
        }
    }
    /**
     * 驗(yàn)證token是否過(guò)期失效
     * @param expirationTime
     * @return
     */
    public boolean isTokenExpired (Date expirationTime) {
        return expirationTime.before(new Date());
    }

    /**
     * 獲取token失效時(shí)間
     * @param token
     * @return
     */
    public Date getExpirationDateFromToken(String token) {
        return getTokenClaim(token).getExpiration();
    }
    /**
     * 獲取用戶名從token中
     */
    public String getUsernameFromToken(String token) {
        return getTokenClaim(token).getSubject();
    }

    /**
     * 獲取jwt發(fā)布時(shí)間
     */
    public Date getIssuedAtDateFromToken(String token) {
        return getTokenClaim(token).getIssuedAt();
    }

    // --------------------- getter & setter ---------------------

    public String getSecret() {
        return secret;
    }
    public void setSecret(String secret) {
        this.secret = secret;
    }
    public long getExpire() {
        return expire;
    }
    public void setExpire(long expire) {
        this.expire = expire;
    }
    public String getHeader() {
        return header;
    }
    public void setHeader(String header) {
        this.header = header;
    }
}


4,配置攔截器

在攔截器中對(duì)token進(jìn)行驗(yàn)證。

package com.ftx.jwt.config;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.SignatureException;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * @author FanJiangFeng
 * @version 1.0.0
 * @ClassName TokenInterceptor.java
 * @Description TODO
 * @createTime 2020年06月22日 15:47:00
 */
@Component
public class TokenInterceptor extends HandlerInterceptorAdapter {

    @Resource
    private JwtConfig jwtConfig ;
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws SignatureException {
        /** 地址過(guò)濾 */
        String uri = request.getRequestURI() ;
        if (uri.contains("/login")){
            return true ;
        }
        /** Token 驗(yàn)證 */
        String token = request.getHeader(jwtConfig.getHeader());
        if(StringUtils.isEmpty(token)){
            token = request.getParameter(jwtConfig.getHeader());
        }
        if(StringUtils.isEmpty(token)){
            throw new SignatureException(jwtConfig.getHeader()+ "不能為空");
        }

        Claims claims = null;
        try{
            claims = jwtConfig.getTokenClaim(token);
            if(claims == null || jwtConfig.isTokenExpired(claims.getExpiration())){
                throw new SignatureException(jwtConfig.getHeader() + "失效,請(qǐng)重新登錄。");
            }
        }catch (Exception e){
            throw new SignatureException(jwtConfig.getHeader() + "失效,請(qǐng)重新登錄。");
        }
		//該token可用,放行
        return true;
    }
}

注冊(cè)攔截器到SpringMvc

package com.ftx.jwt.config;

/**
 * @author FanJiangFeng
 * @version 1.0.0
 * @ClassName WebConfig.java
 * @Description TODO
 * @createTime 2020年06月22日 15:53:00
 */

import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.*;
import javax.annotation.Resource;
import java.util.List;

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Resource
    private TokenInterceptor tokenInterceptor ;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(tokenInterceptor).addPathPatterns("/**");
    }
}

5,編寫測(cè)試controller接口

package com.ftx.jwt.controller;
import com.alibaba.fastjson.JSONObject;
import com.ftx.jwt.config.JwtConfig;
import com.ftx.jwt.util.ResultTool;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

/**
 * @author FanJiangFeng
 * @version 1.0.0
 * @ClassName TokenController.java
 * @Description TODO
 * @createTime 2020年06月22日 16:05:00
 */
@RestController
public class TokenController {
    @Resource
    private JwtConfig jwtConfig ;

    /**
     * 用戶登錄接口
     * @param userName
     * @param passWord
     * @return
     */
    @PostMapping("/login")
    public JSONObject login (@RequestParam("userName") String userName,
                              @RequestParam("passWord") String passWord){
        JSONObject json = new JSONObject();

        /** 驗(yàn)證userName,passWord和數(shù)據(jù)庫(kù)中是否一致,如不一致,直接return ResultTool.errer(); 【這里省略該步驟】*/

        // 這里模擬通過(guò)用戶名和密碼,從數(shù)據(jù)庫(kù)查詢userId
        // 這里把userId轉(zhuǎn)為String類型,實(shí)際開(kāi)發(fā)中如果subject需要存userId,則可以JwtConfig的createToken方法的參數(shù)設(shè)置為L(zhǎng)ong類型
        String userId = 5 + "";
        String token = jwtConfig.createToken(userId) ;
        if (!StringUtils.isEmpty(token)) {
            json.put("token",token) ;
        }
        return ResultTool.success(json) ;
    }

    /**
     * 需要 Token 驗(yàn)證的接口
     */
    @PostMapping("/info")
    public JSONObject info (){
        return ResultTool.success("info") ;
    }

    /**
     * 根據(jù)請(qǐng)求頭的token獲取userId
     * @param request
     * @return
     */
    @GetMapping("/getUserInfo")
    public JSONObject getUserInfo(HttpServletRequest request){
        String usernameFromToken = jwtConfig.getUsernameFromToken(request.getHeader("token"));
        return ResultTool.success(usernameFromToken) ;
    }
}

用PostMan測(cè)試工具測(cè)試一下,訪問(wèn)登錄接口,當(dāng)對(duì)賬號(hào)密碼驗(yàn)證通過(guò)時(shí),則返回一個(gè)token給客戶端 說(shuō)明:token是在請(qǐng)求頭處,request.getHeader()得到token。

在這里插入圖片描述

當(dāng)直接去訪問(wèn)info接口時(shí),會(huì)返回token為空的異常 當(dāng)在請(qǐng)求頭加上正確token時(shí),則攔截器驗(yàn)證通過(guò),可以正常訪問(wèn)到接口

在這里插入圖片描述

當(dāng)在請(qǐng)求頭加入一個(gè)錯(cuò)誤token,則會(huì)返回token失效的異常 接下來(lái)測(cè)試一下獲取用戶信息,因?yàn)檫@里存的subject為userId,所以直接返回上面寫死的假數(shù)據(jù)5

在這里插入圖片描述

三,知識(shí)點(diǎn)概述

1,@Resource注解

  • @Autowired與@Resource都可以用來(lái)裝配bean. 都可以寫在字段上,或?qū)懺趕etter方法上。
  • @Autowired默認(rèn)按類型裝配(這個(gè)注解是屬于spring的),默認(rèn)情況下必須要求依賴對(duì)象必須存在,如果要允許null值,可以設(shè)置它的required屬性為false,如:@Autowired(required=false) 3,@Resource(這個(gè)注解屬于J2EE的),默認(rèn)按照名稱進(jìn)行裝配,名稱可以通過(guò)name屬性進(jìn)行指定,如果沒(méi)有指定name屬性,當(dāng)注解寫在字段上時(shí),默認(rèn)取字段名進(jìn)行安裝名稱查找,如果注解寫在setter方法上默認(rèn)取屬性名進(jìn)行裝配。當(dāng)找不到與名稱匹配的bean時(shí)才按照類型進(jìn)行裝配。但是需要注意的是,如果name屬性一旦指定,就只會(huì)按照名稱進(jìn)行裝配。

2,@ConfigurationProperties注解

@ConfigurationProperties:告訴SpringBoot將本類中的所有屬性和配置文件中相關(guān)的配置進(jìn)行綁定;prefix = "xxx":配置文件中哪個(gè)下面的所有屬性進(jìn)行一一映射

到此這篇關(guān)于SpringBoot集成JWT令牌詳細(xì)說(shuō)明的文章就介紹到這了,更多相關(guān)SpringBoot集成JWT令牌內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MyBatis中RowBounds實(shí)現(xiàn)內(nèi)存分頁(yè)

    MyBatis中RowBounds實(shí)現(xiàn)內(nèi)存分頁(yè)

    RowBounds是MyBatis提供的一種內(nèi)存分頁(yè)方式,適用于小數(shù)據(jù)量的分頁(yè)場(chǎng)景,本文就來(lái)詳細(xì)的介紹一下,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-12-12
  • Springboot整合kafka的示例代碼

    Springboot整合kafka的示例代碼

    這篇文章主要介紹了Springboot整合kafka的示例代碼,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-02-02
  • java abstract class interface之間的區(qū)別介紹

    java abstract class interface之間的區(qū)別介紹

    含有abstract修飾符的class即為抽象類,abstract 類不能創(chuàng)建的實(shí)例對(duì)象,abstract class類中定義抽象方法必須在具體(Concrete)子類中實(shí)現(xiàn),所以,不能有抽象構(gòu)造方法或抽象靜態(tài)方法
    2012-11-11
  • SpringBoot動(dòng)態(tài)定時(shí)任務(wù)、動(dòng)態(tài)Bean、動(dòng)態(tài)路由詳解

    SpringBoot動(dòng)態(tài)定時(shí)任務(wù)、動(dòng)態(tài)Bean、動(dòng)態(tài)路由詳解

    這篇文章主要介紹了SpringBoot動(dòng)態(tài)定時(shí)任務(wù)、動(dòng)態(tài)Bean、動(dòng)態(tài)路由詳解,之前用過(guò)Spring中的定時(shí)任務(wù),通過(guò)@Scheduled注解就能快速的注冊(cè)一個(gè)定時(shí)任務(wù),但有的時(shí)候,我們業(yè)務(wù)上需要?jiǎng)討B(tài)創(chuàng)建,或者根據(jù)配置文件、數(shù)據(jù)庫(kù)里的配置去創(chuàng)建定時(shí)任務(wù),需要的朋友可以參考下
    2023-10-10
  • 淺談springboot自動(dòng)配置原理

    淺談springboot自動(dòng)配置原理

    這篇文章主要介紹了淺談springboot自動(dòng)配置原理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Mybatis之@ResultMap,@Results,@Result注解的使用

    Mybatis之@ResultMap,@Results,@Result注解的使用

    這篇文章主要介紹了Mybatis之@ResultMap,@Results,@Result注解的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • SpringBoot居然有44種應(yīng)用啟動(dòng)器,你都知道嗎

    SpringBoot居然有44種應(yīng)用啟動(dòng)器,你都知道嗎

    很多人都不知道SpringBoot應(yīng)用啟動(dòng)器竟然有44個(gè),本文就一起來(lái)介紹一下,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2021-01-01
  • Java編程打印購(gòu)物小票實(shí)現(xiàn)代碼

    Java編程打印購(gòu)物小票實(shí)現(xiàn)代碼

    這篇文章主要介紹了Java編程打印購(gòu)物小票實(shí)現(xiàn)代碼,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • 如何將文件流轉(zhuǎn)換成byte[]數(shù)組

    如何將文件流轉(zhuǎn)換成byte[]數(shù)組

    這篇文章主要介紹了如何將文件流轉(zhuǎn)換成byte[]數(shù)組,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • SpringBoot3使用Swagger3的示例詳解

    SpringBoot3使用Swagger3的示例詳解

    本文介紹了如何在Spring Boot 3項(xiàng)目中使用Swagger3進(jìn)行后端接口的前端展示,首先,通過(guò)添加依賴并配置application.yml文件來(lái)快速啟動(dòng)Swagger,然后,詳細(xì)介紹了Swagger3的新注解與Swagger2的區(qū)別,并提供了一些常用注解的使用示例,感興趣的朋友跟隨小編一起看看吧
    2024-11-11

最新評(píng)論