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

SpringBoot3中token攔截器鏈的設(shè)計(jì)與實(shí)現(xiàn)步驟

 更新時(shí)間:2024年03月08日 09:40:42   作者:蒾酒  
本文介紹了spring boot后端服務(wù)開(kāi)發(fā)中有關(guān)如何設(shè)計(jì)攔截器的思路,文中通過(guò)代碼示例和圖文講解的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下

流程分析

用戶(hù)在進(jìn)行登陸后服務(wù)器會(huì)發(fā)放token等信息一起返回給前端,前端會(huì)進(jìn)行保存,那么token里面是攜帶一些有關(guān)用戶(hù)的身份等信息的,用戶(hù)端在請(qǐng)求后端時(shí)需要在請(qǐng)求頭攜帶token,請(qǐng)求先被攔截器截獲,只有經(jīng)過(guò)多重?cái)r截器校驗(yàn)通過(guò)后才可以執(zhí)行對(duì)應(yīng)功能接口,否則會(huì)拋出異常返回對(duì)應(yīng)錯(cuò)誤信息。

需要清楚的

  • 每次登錄都要刷新token信息,
  • 不能在用戶(hù)訪問(wèn)的過(guò)程中token過(guò)期,只要用戶(hù)訪問(wèn),token就要刷新有效期。
  • 如果token正確解析token中的用戶(hù)id,根據(jù)用戶(hù)id查詢(xún)用戶(hù)信息。

實(shí)現(xiàn)步驟

總的來(lái)說(shuō)大致分為4步:

1定義攔截器--->2創(chuàng)建攔截器鏈配置類(lèi)--->3配置攔截器鏈順序--->4配置攔截排除項(xiàng)

1.定義攔截器

首先,需要定義第一個(gè)攔截器類(lèi),該攔截器類(lèi)需要實(shí)現(xiàn) Spring 框架提供的 HandlerInterceptor 接口。該攔截器只做一件事就是刷新token。

import cn.hutool.json.JSONUtil;
import com.mijiu.commom.util.JwtUtils;
import com.mijiu.commom.util.UserHolder;
import com.mijiu.entity.User;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
 
import java.util.Objects;
import java.util.concurrent.TimeUnit;
 
/**
 * @author mijiupro
 */
@Slf4j
@Component
public class RefreshTokenInterceptor implements HandlerInterceptor {
 
    private final JwtUtils jwtUtils;
    private final StringRedisTemplate stringRedisTemplate;
 
    public RefreshTokenInterceptor(JwtUtils jwtUtils, StringRedisTemplate stringRedisTemplate) {
        this.jwtUtils = jwtUtils;
        this.stringRedisTemplate = stringRedisTemplate;
    }
 
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
 
        // 1、從請(qǐng)求頭中獲取token
        String authorizationHeader = request.getHeader("authorization");
        if (StringUtils.isBlank(authorizationHeader)) {
            return true;
        }
        // 2.解析token
        Claims claims = jwtUtils.parseToken(authorizationHeader);
        if (Objects.isNull(claims)) {
            return true;
        }
 
        // 3.獲取用戶(hù)信息
        Integer userId = claims.get("userId", Integer.class);
 
        String userInfoJson = stringRedisTemplate.opsForValue().get("login:user:" + userId);
        if (StringUtils.isBlank(userInfoJson)) {
            return true;
        }
 
 
        // 4.刷新token
        String refreshToken = jwtUtils.refreshToken(authorizationHeader);
 
        response.setHeader("Access-Control-Expose-Headers", "Authorization");
        response.addHeader("Authorization", refreshToken);
        stringRedisTemplate.expire("login:user:" + userId, 30, TimeUnit.MINUTES);
 
        // 5.將用戶(hù)信息存入本地線(xiàn)程方便獲取
        User user = JSONUtil.toBean(userInfoJson, User.class);
        UserHolder.setInfoByToken(user);
 
        return true;
    }
 
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        // 清理本地線(xiàn)程
        UserHolder.clear();
    }
}

值得注意:因?yàn)橛行┙涌谑遣恍枰J(rèn)證的比如你在商城,瀏覽商品,是不是不登錄也可以瀏覽。不登錄就沒(méi)token,沒(méi)token就直接放行(認(rèn)證交給后續(xù)的認(rèn)證攔截器),有token就直接刷新(不可能你登錄了瀏覽了30分鐘,突然下單然后告訴你token過(guò)期重新登錄吧,所以登錄后調(diào)用的每個(gè)接口都要走一遍token刷新)。最后請(qǐng)求處理完一定要清理一下本地線(xiàn)程,不然用戶(hù)多的時(shí)候內(nèi)存占用會(huì)很大。

然后,就要實(shí)現(xiàn)一個(gè)認(rèn)證攔截器了,實(shí)現(xiàn)用戶(hù)身份認(rèn)證。

import com.mijiu.commom.util.UserHolder;
import com.mijiu.entity.User;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import java.util.Objects;
 
 
/**
 * @author mijiupro
 */
 
@Component
public class LoginInterceptor implements HandlerInterceptor {
 
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        User user = UserHolder.getInfoByToken();
 
        if (Objects.isNull(user)) {
            response.setStatus(401);
            return false;
        }
 
        return true;
    }
}

值得注意:在上個(gè)攔截器我們是做過(guò)解析token了并存在本地線(xiàn)程里面,所以只需要判斷本地線(xiàn)程有沒(méi)有即可。

2.創(chuàng)建攔截器鏈配置類(lèi)

創(chuàng)建一個(gè)配置類(lèi),用于配置攔截器鏈。在該配置類(lèi)中,通過(guò)實(shí)現(xiàn) WebMvcConfigurer 接口來(lái)添加攔截器,具體包括 addInterceptors 方法。

import com.mijiu.commom.interceptor.LoginInterceptor;
import com.mijiu.commom.interceptor.RefreshTokenInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
/**
 * @author mijiupro
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {
    private final RefreshTokenInterceptor refreshTokenInterceptor;
 
    private final LoginInterceptor loginInterceptor;
 
    public WebConfig(RefreshTokenInterceptor refreshTokenInterceptor, LoginInterceptor loginInterceptor) {
        this.refreshTokenInterceptor = refreshTokenInterceptor;
        this.loginInterceptor = loginInterceptor;
    }
 
 
    @Override
    public void addInterceptors( InterceptorRegistry registry) {
        registry.addInterceptor(refreshTokenInterceptor)
                .addPathPatterns("/**").order(0);//設(shè)置攔截器對(duì)所有路徑生效,執(zhí)行順序?yàn)?
 
        registry.addInterceptor(loginInterceptor)
                .excludePathPatterns("/captcha/graph-captcha")//排除用戶(hù)登錄獲取驗(yàn)證碼接口
                .excludePathPatterns("/","*/login","*.html","/images/**","/doc.html"
                        ,"/webjars/**","/swagger-resources","/swagger-resources/**","/v3/**")//排除登錄獲取靜態(tài)資源、swagger接口文檔等。
                .order(1);//設(shè)置攔截器對(duì)所有路徑生效,執(zhí)行順序?yàn)?
 
 
    }
 
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**") // 對(duì)所有路徑生效
                .allowedOrigins("*") //允許所有源地址
                .allowedMethods("GET", "POST", "PUT", "DELETE") // 允許的請(qǐng)求方法
                .allowedHeaders("*"); // 允許的請(qǐng)求頭
    }
}

3.配置攔截器鏈順序

刷新token的攔截器要最先執(zhí)行,接著才是認(rèn)證攔截器

4.配置攔截排除項(xiàng)

像用戶(hù)登錄的驗(yàn)證碼接口、登錄接口以及像一些靜態(tài)資源、網(wǎng)頁(yè)、圖片等需要進(jìn)行攔截排除,如果整合了swagger接口文檔也是需要排除的。

最后

token攔截器鏈的設(shè)計(jì)與實(shí)現(xiàn)核心就四步:

1定義攔截器--->2創(chuàng)建攔截器鏈配置類(lèi)--->3配置攔截器鏈順序--->4配置攔截排除項(xiàng)

到此這篇關(guān)于SpringBoot3中token攔截器鏈的設(shè)計(jì)與實(shí)現(xiàn)步驟的文章就介紹到這了,更多相關(guān)SpringBoot3 token攔截器鏈內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

神木县| 自治县| 宁河县| 延寿县| 富川| 杭锦旗| 恩施市| 洱源县| 上高县| 丹棱县| 巫山县| 榕江县| 云龙县| 绥宁县| 盱眙县| 巴林右旗| 时尚| 兴文县| 东台市| 江北区| 双峰县| 鄂托克前旗| 泾源县| 大田县| 徐闻县| 宜川县| 松溪县| 浪卡子县| 五家渠市| 盐边县| 贞丰县| 鲁山县| 南投县| 民乐县| 海林市| 高青县| 南郑县| 襄汾县| 永泰县| 郓城县| 岳西县|