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

SpringBoot集成JWT實(shí)現(xiàn)Token登錄驗(yàn)證的示例代碼

 更新時(shí)間:2023年12月11日 15:05:08   作者:深情不及里子  
隨著技術(shù)的發(fā)展,分布式web應(yīng)用的普及,通過(guò)session管理用戶登錄狀態(tài)成本越來(lái)越高,因此慢慢發(fā)展成為token的方式做登錄身份校驗(yàn),本文就來(lái)介紹一下SpringBoot集成JWT實(shí)現(xiàn)Token登錄驗(yàn)證的示例代碼,感興趣的可以了解一下

一,  JWT是什么?

JWT官網(wǎng)

在JWT官網(wǎng)中可以明確看到關(guān)于它的定義

JSON Web令牌(JWT)是一種開(kāi)放的標(biāo)準(zhǔn)(RFC 7519),它定義了一種緊湊而獨(dú)立的方式在各方之間安全地傳輸信息為JSON對(duì)象。該信息可以被驗(yàn)證和信任,因?yàn)樗菙?shù)字簽名的。JWT可以使用秘密(使用HMAC算法)或使用RSA或ECDSA的公開(kāi)/私有密鑰類型簽名。 雖然JWT可以被加密以提供各方之間的保密,但我們將重點(diǎn)關(guān)注簽名的令牌。被簽名的令牌可以驗(yàn)證包含在其中的聲明的完整性,而加密的令牌對(duì)其他各方隱藏這些聲明。當(dāng)使用公鑰/私鑰對(duì)簽名時(shí),簽名還證明只有持有私鑰的一方才是簽名方。

1.1 JWT主要使用場(chǎng)景

  • 授權(quán)(Authorization):這是使用JWT最常見(jiàn)的場(chǎng)景。一旦用戶登錄,每個(gè)后續(xù)請(qǐng)求都將包括JWT,允許用戶訪問(wèn)該令牌允許的路由、服務(wù)和資源。

  • 單點(diǎn)登錄(Single Sign On ):?jiǎn)吸c(diǎn)登錄是當(dāng)今廣泛使用的JWT特性,因?yàn)樗男∫?guī)模和易于跨不同領(lǐng)域使用的能力。

  • 信息交換(lnformation Exchange):信息交換在通信的雙方之間使用JWT對(duì)數(shù)據(jù)進(jìn)行編碼是一種非常安全的方式,由于它的信息是經(jīng)過(guò)簽名的,可以確保發(fā)送者發(fā)送的信息是沒(méi)有經(jīng)過(guò)偽造的。

  • 傳輸信息(transmitting information):在各方之間傳輸信息。由于JWT可以簽名--例如,使用公共/私鑰對(duì)--您可以確保發(fā)件人是他們所說(shuō)的發(fā)送者。此外,由于簽名是使用頭和有效載荷計(jì)算的,您還可以驗(yàn)證內(nèi)容沒(méi)有被篡改。

1.2 JWT請(qǐng)求流程

  • 用戶使用賬號(hào)和密碼發(fā)出post請(qǐng)求;
  • 服務(wù)器使用私鑰創(chuàng)建一個(gè)jwt;
  • 服務(wù)器返回這個(gè)jwt給瀏覽器;
  • 瀏覽器將該jwt串在請(qǐng)求頭中像服務(wù)器發(fā)送請(qǐng)求;
  • 服務(wù)器驗(yàn)證該jwt;
  • 返回響應(yīng)的資源給瀏覽器。

1.3 JWT結(jié)構(gòu)

JWT是由三段信息構(gòu)成的,將這三段信息文本用.連接一起就構(gòu)成了JWT字符串。

就像這樣:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

 JWT包含了三部分:

  • Header 頭部(標(biāo)題包含了令牌的元數(shù)據(jù),并且包含簽名和/或加密算法的類型)

  • Payload 負(fù)載 (類似于飛機(jī)上承載的物品)

  • Signature 簽名/簽證

Header

JWT的頭部承載兩部分信息:token類型和采用的加密算法。

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

聲明類型:這里是jwt

聲明加密的算法:通常直接使用 HMAC SHA256

加密算法是單向函數(shù)散列算法,常見(jiàn)的有MD5、SHA、HAMC。

MD5(message-digest algorithm 5) (信息-摘要算法)縮寫(xiě),廣泛用于加密和解密技術(shù),常用于文件校驗(yàn)。校驗(yàn)?不管文件多大,經(jīng)過(guò)MD5后都能生成唯一的MD5值

SHA (Secure Hash Algorithm,安全散列算法),數(shù)字簽名等密碼學(xué)應(yīng)用中重要的工具,安全性高于MD5

HMAC (Hash Message Authentication Code),散列消息鑒別碼,基于密鑰的Hash算法的認(rèn)證協(xié)議。用公開(kāi)函數(shù)和密鑰產(chǎn)生一個(gè)固定長(zhǎng)度的值作為認(rèn)證標(biāo)識(shí),用這個(gè)標(biāo)識(shí)鑒別消息的完整性。常用于接口簽名驗(yàn)證

Payload

載荷就是存放有效信息的地方。

有效信息包含三個(gè)部分:

  • 標(biāo)準(zhǔn)中注冊(cè)的聲明

  • 公共的聲明

  • 私有的聲明

標(biāo)準(zhǔn)中注冊(cè)的聲明 (建議但不強(qiáng)制使用) :

  • iss: jwt簽發(fā)者

  • sub: 面向的用戶(jwt所面向的用戶)

  • aud: 接收jwt的一方

  • exp: 過(guò)期時(shí)間戳(jwt的過(guò)期時(shí)間,這個(gè)過(guò)期時(shí)間必須要大于簽發(fā)時(shí)間)

  • nbf: 定義在什么時(shí)間之前,該jwt都是不可用的.

  • iat: jwt的簽發(fā)時(shí)間

  • jti: jwt的唯一身份標(biāo)識(shí),主要用來(lái)作為一次性token,從而回避重放攻擊。

公共的聲明:

公共的聲明可以添加任何的信息,一般添加用戶的相關(guān)信息或其他業(yè)務(wù)需要的必要信息.但不建議添加敏感信息,因?yàn)樵摬糠衷诳蛻舳丝山饷?

私有的聲明:

私有聲明是提供者和消費(fèi)者所共同定義的聲明,一般不建議存放敏感信息,因?yàn)閎ase64是對(duì)稱解密的,意味著該部分信息可以歸類為明文信息。

Signature

jwt的第三部分是一個(gè)簽證信息

這個(gè)部分需要base64加密后的header和base64加密后的payload使用.連接組成的字符串,然后通過(guò)header中聲明的加密方式進(jìn)行加鹽secret組合加密,然后就構(gòu)成了jwt的第三部分。最主要的目的:服務(wù)器應(yīng)用在接受到JWT后,會(huì)首先對(duì)頭部和載荷的內(nèi)容用同一算法再次簽名,如果服務(wù)器應(yīng)用對(duì)頭部和載荷再次以同樣方法簽名之后發(fā)現(xiàn),自己計(jì)算出來(lái)的簽名和接受到的簽名不一樣,那么就說(shuō)明這個(gè)Token的內(nèi)容被別人動(dòng)過(guò)的,我們應(yīng)該拒絕這個(gè)Token,返回一個(gè)HTTP 401 Unauthorized響應(yīng)。

密鑰secret是保存在服務(wù)端的,服務(wù)端會(huì)根據(jù)這個(gè)密鑰進(jìn)行生成token和進(jìn)行驗(yàn)證,所以需要保護(hù)好。

這些信息在官網(wǎng)上也有相關(guān)信息的說(shuō)明:

二,SpringBoot集成JWT具體實(shí)現(xiàn)過(guò)程

這里由于只涉及對(duì)驗(yàn)證功能的實(shí)現(xiàn),因此其他數(shù)據(jù)庫(kù),業(yè)務(wù)類編寫(xiě)一概省略,只對(duì)相關(guān)步驟做說(shuō)明。

2.1添加相關(guān)依賴

既然要使用JWT我們肯定需要引入其依賴

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

2.2自定義跳出攔截器的注解

方便我們后續(xù)不用對(duì)在配置攔截器時(shí)排除每一個(gè)接口,只用自定義注解去標(biāo)記即可。

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

/**
 * @author young
 * @date 2022/11/24 14:53
 * @description: 自定義通過(guò)token注解,如果不加該注解直接攔截
 */
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PassToken {
    boolean required() default true;
}

@Retention注解說(shuō)明

  • RetentionPolicy.SOURCE:這種類型的Annotations只在源代碼級(jí)別保留,編譯時(shí)就會(huì)被忽略,在class字節(jié)碼文件中不包含。

  • RetentionPolicy.CLASS:這種類型的Annotations編譯時(shí)被保留,默認(rèn)的保留策略,在class文件中存在,但JVM將會(huì)忽略,運(yùn)行時(shí)無(wú)法獲得。

  • RetentionPolicy.RUNTIME:這種類型的Annotations將被JVM保留,所以他們能在運(yùn)行時(shí)被JVM或其他使用反射機(jī)制的代碼所讀取和使用。

  • @Document:說(shuō)明該注解將被包含在javadoc中

  • @Inherited:說(shuō)明子類可以繼承父類中的該注解

2.3自定義全局統(tǒng)一返回值方法,異常類及相關(guān)枚舉

定義全局枚舉類

package com.yy.enums;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import java.util.UUID;

/**
 * @author young
 * @date 2022/8/19 21:36
 * @description: 響應(yīng)結(jié)果枚舉
 */

@AllArgsConstructor
@Getter
public enum ResponseEnum {
   /**響應(yīng)成功**/
   SUCCESS(200, "操作成功"),
   /**操作失敗*/
   FAIL(201,"獲取數(shù)據(jù)失敗"),
   
   NO_TOKEN(400,"無(wú)token,請(qǐng)重新登錄"), 
   TOKEN_EX(401,"token驗(yàn)證失敗,請(qǐng)重新登錄"),
   
   USER_EX(402,"用戶不存在,請(qǐng)重新登錄"),
   
   /**錯(cuò)誤請(qǐng)求**/
   ERROR(400,"錯(cuò)誤請(qǐng)求");

   /**響應(yīng)碼**/
   private final Integer code;
   
   /** 結(jié)果 **/
   private  final String  resultMessage;
   

   public static ResponseEnum getResultCode(Integer code){
      for (ResponseEnum value : ResponseEnum.values()) {
         if (code.equals(value.getCode())){
            return value;
         }
      }
      return ResponseEnum.ERROR;
   }
/*
簡(jiǎn)單測(cè)試一下
 */
   public static void main(String[] args) {
      ResponseEnum resultCode = ResponseEnum.getResultCode(100);
      System.out.println(resultCode);
   }
}

定義全局異常類

package com.yy.util;

import com.yy.Enums.ResultEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
 * @author young
 * @date 2022/9/25 19:15
 * @description: 自定義運(yùn)行時(shí)異常
 */
@Data
@ApiModel(value = "自定義全局異常類")
public class MyException extends RuntimeException{
    @ApiModelProperty(value = "異常狀態(tài)碼")
    private final Integer code;

    /**
     * 通過(guò)狀態(tài)碼和異常信息創(chuàng)建異常對(duì)象
     * @param code
     * @param message
     */
    public MyException(Integer code,String message) {
        super(message);
        this.code = code;
    }

    /**
     * 接受枚舉類型對(duì)象
     * @param resultEnum
     */
    public MyException(ResponseEnum responseEnum){
        super(responseEnum.getMessage());
        this.code = responseEnum.getCode();
    }
}
package com.yy.Config;

import com.yy.utils.MyException;
import com.yy.utils.R;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
 * @author young
 * @date 2022/9/12 15:43
 * @description: 自定義異常配置
 */
@RestControllerAdvice
public class GlobalExceptionConfig{
    @ExceptionHandler(MyException.class)
    public R<MyException> handle(MyException e){
        e.printStackTrace();
        return R.exception(e.getCode(),e.getMessage());
    }
}

定義統(tǒng)一返回結(jié)果類

package com.yy.utils;
import com.yy.enums.ResponseEnum;
import lombok.Data;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

/**
 * @author young
 * @date 2022/8/19 21:52
 * @description: 統(tǒng)一返回結(jié)果的類
 */

@Data
public class  R<T> implements Serializable {
    
    private static final long serialVersionUID = 56665257248936049L;
    /**響應(yīng)碼**/
    private Integer code;

    /**返回消息**/
    private String message;

    /**返回?cái)?shù)據(jù)**/
    private T data;

   private R(){}
    /**
     * 操作成功ok方法
     */
    public static <T> R<T> ok(T data) {
        R<T> response = new R<>();
     response.setCode(ResponseEnum.SUCCESS.getCode());   response.setMessage(ResponseEnum.SUCCESS.getResultMessage());
        response.setData(data);
        return response;
    }

    /**
     * 編譯失敗方法
     */
    public static <T> R<T> buildFailure(Integer errCode, String errMessage){
        R<T> response = new R<>();
        response.setCode(errCode);
        response.setMessage(errMessage);
        return response;
    }
    

    public static <T> R<T> exception(Integer errCode, String errMessage){
        R<T> response = new R<>();
        response.setCode(errCode);
        response.setMessage(errMessage);
        return response;
    }
}

2.4編寫(xiě)JWT工具類,用于生成Token令牌

package com.yy.utils;

import cn.hutool.core.date.DateUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import java.util.Date;
/**
 * @author young
 * @date 2022/9/12 14:46
 * @description: 整合JWT生成token
 */
public class JwtTokenUtils {
    private JwtTokenUtils() {
        throw new IllegalStateException("Utility class");
    }
    /**
     * 生成token
     * @param userId
     * @param sign
     * @return
     */
    public static String getToken(String userId,String sign){
      return  JWT.create()
              //簽收者
              .withAudience(userId)
              //主題
               .withSubject("token")
                //2小時(shí)候token過(guò)期
                .withExpiresAt(DateUtil.offsetHour(new Date(),2))
                //以password作為token的密鑰
                .sign(Algorithm.HMAC256(sign));
    }
}

Algorithm.HMAC256():使用HS256生成token,密鑰則是用戶的密碼,唯一密鑰的話可以保存在服務(wù)端。

withAudience():存入需要保存在token的信息,這里我們把用戶ID存入token中

2.5編寫(xiě)攔截器并注入容器

package com.yy.Config.inteceptor;

import cn.hutool.core.text.CharSequenceUtil;
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.yy.enums.ResponseEnum;
import com.yy.admin.pojo.Admin;
import com.yy.admin.service.Impl.AdminServiceImpl;
import com.yy.utils.MyException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * @author young
 * @date 2022/9/12 15:37
 * @description: 獲取token并驗(yàn)證
 */
@Component
public class MyJwtInterceptor implements HandlerInterceptor {
    @Autowired
    private AdminServiceImpl adminService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("token");
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        //檢查是否通過(guò)有PassToken注解
        if (method.isAnnotationPresent(PassToken.class)) {
            //如果有則跳過(guò)認(rèn)證檢查
            PassToken passToken = method.getAnnotation(PassToken.class);
            if (passToken.required()) {
                return true;
            }
        }
        //否則進(jìn)行token檢查
        if (CharSequenceUtil.isBlank(token)) {
            throw new MyException(ResponseEnum.TOKEN_EX.getCode(), ResponseEnum.TOKEN_EX.getResultMessage());
        }
        //獲取token中的用戶id
        String userId;
        try {
            userId = JWT.decode(token).getAudience().get(0);
        } catch (JWTDecodeException j) {
            throw new MyException(ResponseEnum.TOKEN_EX.getCode(), ResponseEnum.TOKEN_EX.getResultMessage());
        }
        //根據(jù)token中的userId查詢數(shù)據(jù)庫(kù)
        Admin user = adminService.getById(userId);
        if (user == null) {
            throw new MyException(ResponseEnum.USER_EX.getCode(), ResponseEnum.USER_EX.getResultMessage());
        }

        //驗(yàn)證token
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPwd())).build();
        try {
            jwtVerifier.verify(token);
        } catch (JWTVerificationException e) {
            throw new MyException(406, "權(quán)限驗(yàn)證失??!");
        }
        return true;
    }
}

這里需要說(shuō)明一下實(shí)現(xiàn)攔截器的方法,我們只需要實(shí)現(xiàn)HandlerInterceptor接口即可,它主要定義了三個(gè)方法:

boolean preHandle ()

預(yù)處理回調(diào)方法,實(shí)現(xiàn)處理器的預(yù)處理,第三個(gè)參數(shù)為響應(yīng)的處理器,自定義Controller,返回值為true表示繼續(xù)流程(如調(diào)用下一個(gè)攔截器或處理器)或者接著執(zhí)行postHandle()和afterCompletion();false表示流程中斷,不會(huì)繼續(xù)調(diào)用其他的攔截器或處理器,中斷執(zhí)行。

void postHandle()

后處理回調(diào)方法,實(shí)現(xiàn)處理器的后處理(DispatcherServlet進(jìn)行視圖返回渲染之前進(jìn)行調(diào)用),此時(shí)我們可以通過(guò)modelAndView(模型和視圖對(duì)象)對(duì)模型數(shù)據(jù)進(jìn)行處理或?qū)σ晥D進(jìn)行處理,modelAndView也可能為null。

void afterCompletion():

整個(gè)請(qǐng)求處理完畢回調(diào)方法,該方法也是需要當(dāng)前對(duì)應(yīng)的Interceptor的preHandle()的返回值為true時(shí)才會(huì)執(zhí)行,也就是在DispatcherServlet渲染了對(duì)應(yīng)的視圖之后執(zhí)行。用于進(jìn)行資源清理。

整個(gè)請(qǐng)求處理完畢回調(diào)方法。如性能監(jiān)控中我們可以在此記錄結(jié)束時(shí)間并輸出消耗時(shí)間,還可以進(jìn)行一些資源清理,類似于try-catch-finally中的finally,但僅調(diào)用處理器執(zhí)行鏈中。

這里我們主要需要調(diào)用預(yù)處理回調(diào)方法即可,如果有其他業(yè)務(wù)需求,也可自行更改。

主要流程:

  • 從 http 請(qǐng)求頭中取出 token,

  • 判斷是否映射到方法

  • 檢查是否有passtoken注釋,有則跳過(guò)認(rèn)證

  • 檢查有沒(méi)有需要用戶登錄的注解,有則需要取出并驗(yàn)證

  • 認(rèn)證通過(guò)則可以訪問(wèn),不通過(guò)會(huì)報(bào)相關(guān)錯(cuò)誤信息

然后通過(guò)配置類將我們自定義的攔截類注入到spring容器中,并進(jìn)行攔截配置。

package com.yy.Config.inteceptor;

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;

/**
 * @author young
 * @date 2022/9/12 15:36
 * @description: JWT攔截配置
 */
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(jwtInterceptor())
 //攔截所有請(qǐng)求,通過(guò)判斷token來(lái)決定是否需要登陸
                .addPathPatterns("/**");
    }

    @Bean
    public MyJwtInterceptor jwtInterceptor(){
        return new MyJwtInterceptor();
    }
}

至此,我們對(duì)于JWT在SpringBoot中的基本配置就算完成了。我們只需在controller層在自己想要放行的api接口上添加我們自定義的放行注解,即可實(shí)現(xiàn)對(duì)api接口的放行,其他接口均要進(jìn)行Token令牌的驗(yàn)證判斷。如果沒(méi)有Token則返回自定義的異常信息。

三,測(cè)試

3.1放行一般類接口

這里我們先只對(duì)一個(gè)業(yè)務(wù)接口進(jìn)行放行。

/**
     * 查找指定id信息
     *
     * @param id
     * @return
     */
    @GetMapping("/getOne/{id}")
    @CostTime
    @PassToken
    public R<TestUser> selectOne(@PathVariable Integer id) {
        TestUser user = testUserService.getById(id);
        return R.ok(user);
    }

進(jìn)行接口測(cè)試后發(fā)現(xiàn),該接口獲取數(shù)據(jù)正常。

 其他沒(méi)有加@PassToken的接口由于沒(méi)有token進(jìn)行驗(yàn)證,均會(huì)被攔截器攔截,并返回我們預(yù)期的異常信息"token驗(yàn)證失敗,請(qǐng)重新登錄"

因此,同理我們只需要在登陸注冊(cè)或其他不需要token驗(yàn)證的接口上添加自定義注解即可實(shí)現(xiàn)攔截。

為了達(dá)到業(yè)務(wù)需求,我們需要在用戶登錄成功后獲取到token,然后將token信息存放在每次的接口請(qǐng)求頭(headers)上,這樣就能實(shí)現(xiàn)對(duì)用戶接口信息基本保護(hù)了。

3.2放行登錄接口

在業(yè)務(wù)層處理token,將生成的token信息帶到用戶實(shí)體類中,這樣登錄獲取用戶信息時(shí)就能讀取到token信息了

package com.yy.admin.service.Impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yy.admin.pojo.Admin;
import com.yy.admin.service.AdminService;
import com.yy.admin.dao.AdminDao;
import com.yy.utils.JwtTokenUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Optional;

/**
* @author young
* @description 針對(duì)表【admin】的數(shù)據(jù)庫(kù)操作Service實(shí)現(xiàn)
* @createDate 2022-09-05 13:41:54
*/
@Service
@Slf4j
public class AdminServiceImpl extends ServiceImpl<AdminDao, Admin>
    implements AdminService{
  @Resource
  private AdminDao adminDao;

    @Override
    public Admin getMsg(String username, String pwd){
         Admin admin = adminDao.selectByUsernameAndPwd(username, pwd);
         Optional.ofNullable(admin).ifPresent(u->{
             //添加token信息設(shè)置到用戶實(shí)體上
             String token = JwtTokenUtils.getToken(String.valueOf(admin.getId()),pwd);
             log.info("token的值為:{}",token);
             admin.setToken(token);
         });
         return admin;
     }
}




編寫(xiě)用戶登錄的業(yè)務(wù)接口并放行Token

@PostMapping("/login")
    @PassToken
    public Object loginStatus(@RequestParam("username") String username, @RequestParam("password") String password){
        JSONObject object = new JSONObject();
        Admin admin = adminService.getMsg(username, password);
        if (admin!=null){
            object.put("code",1);
            object.put("msg","登陸成功");
            object.put("success",true);
            object.put("type","success");
            object.put("userMsg",admin);
        }else {
            object.put("code",0);
            object.put("success",false);
            object.put("msg","用戶名或密碼錯(cuò)誤");
            object.put("type","error");
        }
        return object;
    }

進(jìn)行接口測(cè)試

 這樣就可以看到生成的Token信息了,然后我們將token信息設(shè)置在請(qǐng)求頭上對(duì)其他接口進(jìn)行測(cè)試。

此時(shí)就能看到,接口請(qǐng)求成功。

注意:這里的參數(shù)名token對(duì)應(yīng)攔截器配置String token=request.getHeader("token")中的getHeader中設(shè)置的的參數(shù)名。

到此這篇關(guān)于SpringBoot集成JWT實(shí)現(xiàn)Token登錄驗(yàn)證的示例代碼的文章就介紹到這了,更多相關(guān)SpringBoot JWT Token登錄驗(yàn)證內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Mybatis-Plus的應(yīng)用場(chǎng)景描述及注入SQL原理分析

    Mybatis-Plus的應(yīng)用場(chǎng)景描述及注入SQL原理分析

    MyBatis-Plus是一個(gè) MyBatis 的增強(qiáng)工具,在 MyBatis 的基礎(chǔ)上只做增強(qiáng)不做改變,為簡(jiǎn)化開(kāi)發(fā)、提高效率而生,本文重點(diǎn)給大家介紹Mybatis-Plus的應(yīng)用場(chǎng)景及注入SQL原理分析,感興趣的朋友跟隨小編一起學(xué)習(xí)吧
    2021-05-05
  • SpringBoot AOP如何配置全局事務(wù)

    SpringBoot AOP如何配置全局事務(wù)

    這篇文章主要介紹了SpringBoot AOP如何配置全局事務(wù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • 使用Files.walkFileTree遍歷目錄文件

    使用Files.walkFileTree遍歷目錄文件

    這篇文章主要介紹了使用Files.walkFileTree遍歷目錄文件,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • 如何使用Java模擬退火算法優(yōu)化Hash函數(shù)

    如何使用Java模擬退火算法優(yōu)化Hash函數(shù)

    為了解決局部最優(yōu)解問(wèn)題,1983年,Kirkpatrick等提出了模擬退火算法(SA)能有效的解決局部最優(yōu)解問(wèn)題。模擬退火算法包含兩個(gè)部分即Metropolis算法和退火過(guò)程。Metropolis算法就是如何在局部最優(yōu)解的情況下讓其跳出來(lái),是退火的基礎(chǔ)
    2021-06-06
  • 在Spring Boot2中使用CompletableFuture的方法教程

    在Spring Boot2中使用CompletableFuture的方法教程

    這篇文章主要給大家介紹了關(guān)于在Spring Boot2中使用CompletableFuture的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧
    2019-01-01
  • MyBatis #{}和${} |與數(shù)據(jù)庫(kù)連接池使用詳解

    MyBatis #{}和${} |與數(shù)據(jù)庫(kù)連接池使用詳解

    本文將為大家說(shuō)說(shuō)關(guān)于 #{} 和 ${},這個(gè)是 MyBatis 在面試中最常問(wèn)的面試題,以及數(shù)據(jù)庫(kù)連接池相關(guān)的知識(shí),感興趣的朋友跟隨小編一起看看吧
    2024-01-01
  • Java8?Stream?collect(Collectors.toMap())的使用

    Java8?Stream?collect(Collectors.toMap())的使用

    這篇文章主要介紹了Java8?Stream?collect(Collectors.toMap())的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • SpringBoot DBUnit 單元測(cè)試(小結(jié))

    SpringBoot DBUnit 單元測(cè)試(小結(jié))

    這篇文章主要介紹了SpringBoot DBUnit 單元測(cè)試(小結(jié)),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-09-09
  • Java重寫(xiě)與重載之間的區(qū)別

    Java重寫(xiě)與重載之間的區(qū)別

    本文主要介紹了Java重寫(xiě)與重載之間的區(qū)別。具有一定的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-01-01
  • 序列化版本號(hào)serialVersionUID的作用_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    序列化版本號(hào)serialVersionUID的作用_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java序列化是將一個(gè)對(duì)象編碼成一個(gè)字節(jié)流,反序列化將字節(jié)流編碼轉(zhuǎn)換成一個(gè)對(duì)象,這篇文章主要介紹了序列化版本號(hào)serialVersionUID的作用,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05

最新評(píng)論