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

使用SpringBoot簡單實現(xiàn)無感知的刷新 Token功能

 更新時間:2024年09月12日 08:29:46   作者:一只愛擼貓的程序猿  
實現(xiàn)無感知的刷新 Token 是一種提升用戶體驗的常用技術,可以在用戶使用應用時自動更新 Token,無需用戶手動干預,這種技術在需要長時間保持用戶登錄狀態(tài)的應用中非常有用,以下是使用Spring Boot實現(xiàn)無感知刷新Token的一個場景案例和相應的示例代碼

引言

實現(xiàn)無感知的刷新 Token 是一種提升用戶體驗的常用技術,可以在用戶使用應用時自動更新 Token,無需用戶手動干預。這種技術在需要長時間保持用戶登錄狀態(tài)的應用中非常有用,比如在一些需要頻繁訪問服務器資源的WEB和移動應用。以下是使用Spring Boot實現(xiàn)無感知刷新Token的一個場景案例和相應的示例代碼。

場景案例

假設我們有一個電子商務平臺,用戶登錄后可以瀏覽商品、加入購物車、提交訂單等。為了保持用戶會話的安全,我們使用JWT(JSON Web Tokens)技術。用戶的登錄會話由兩部分組成:access_tokenrefresh_token。access_token 有較短的有效期,例如15分鐘,而 refresh_token 有較長的有效期,例如7天。

用戶每次發(fā)起請求時,系統(tǒng)都會檢查 access_token 的有效性。如果 access_token 過期但 refresh_token 仍然有效,系統(tǒng)會自動發(fā)起一個刷新令牌的過程,為用戶頒發(fā)新的 access_tokenrefresh_token,從而實現(xiàn)無感知刷新。

技術實現(xiàn)

我們將使用Spring Boot框架實現(xiàn)這一功能,具體技術棧包括:

  • Spring Boot 2.x
  • Spring Security for Authentication
  • JWT for token generation and validation
  • Maven for dependency management

示例代碼

1. 引入依賴

pom.xml 中添加以下依賴:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.9.1</version>
    </dependency>
</dependencies>

2. 配置JWT工具類

創(chuàng)建一個工具類用于生成和解析JWT Token。

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
public class JwtTokenUtil {
    private String secretKey = "secret"; // 密鑰,實際應用中應保密

    public String generateAccessToken(String username) {
        return Jwts.builder()
                .setSubject(username)
                .setIssuer("YourApp")
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + 15 * 60 * 1000)) // 15分鐘后過期
                .signWith(SignatureAlgorithm.HS512, secretKey)
                .compact();
    }

    public String generateRefreshToken(String username) {
        return Jwts.builder()
                .setSubject(username)
                .setIssuer("YourApp")
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + 7 * 24 * 60 * 60 * 1000)) // 7天后過期
                .signWith(SignatureAlgorithm.HS512, secretKey)
                .compact();
    }

    public Claims getClaimsFromToken(String token) {
        return Jwts.parser()
                .setSigningKey(secretKey)
                .parseClaimsJws(token)
                .getBody();
    }
}

3. 配置Spring Security和Token驗證過濾器

創(chuàng)建一個Security配置類和一個JWT驗證過濾器,用于檢查和刷新Tokens。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        JwtTokenFilter jwtTokenFilter = new JwtTokenFilter(jwtTokenUtil, userDetailsService);
        
        http.csrf().disable()
            .authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class);
    }
}

在這里,JwtTokenFilter 是一個自定義的過濾器,它負責每次HTTP請求時檢查和刷新 access_token。這里我們使用 addFilterBefore 方法將 JwtTokenFilter 添加到 UsernamePasswordAuthenticationFilter 之前。這是因為我們希望在Spring Security執(zhí)行標準身份驗證之前處理JWT令牌的提取和驗證。我們通過Spring的自動裝配 (@Autowired) 功能注入了 JwtTokenUtilUserDetailsService。

4. JwtTokenFilter 實現(xiàn)

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class JwtTokenFilter extends OncePerRequestFilter {
    private JwtTokenUtil jwtTokenUtil;
    private UserDetailsService userDetailsService;

    public JwtTokenFilter(JwtTokenUtil jwtTokenUtil, UserDetailsService userDetailsService) {
        this.jwtTokenUtil = jwtTokenUtil;
        this.userDetailsService = userDetailsService;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        String accessToken = request.getHeader("Authorization");
        String username = null;
        Claims claims = null;

        if (accessToken != null && accessToken.startsWith("Bearer ")) {
            accessToken = accessToken.substring(7);
            try {
                claims = jwtTokenUtil.getClaimsFromToken(accessToken);
                username = claims.getSubject();
            } catch (ExpiredJwtException e) {
                // 在這里處理 access_token 過期的情況
                String refreshToken = request.getHeader("Refresh-Token");
                if (refreshToken != null && jwtTokenUtil.validateToken(refreshToken)) {
                    // 驗證 refresh_token,如果有效則重新生成 tokens
                    username = jwtTokenUtil.getClaimsFromToken(refreshToken).getSubject();
                    String newAccessToken = jwtTokenUtil.generateAccessToken(username);
                    String newRefreshToken = jwtTokenUtil.generateRefreshToken(username);
                    
                    // 將新的 tokens 放入響應頭
                    response.setHeader("Access-Token", newAccessToken);
                    response.setHeader("Refresh-Token", newRefreshToken);
                }
            }
        }

        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
            if (jwtTokenUtil.validateToken(accessToken, userDetails)) {
                Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }
        chain.doFilter(request, response);
    }
}

過濾器首先從HTTP請求的 Authorization 頭中提取 access_token。如果令牌已過期,它將嘗試從 Refresh-Token 頭獲取 refresh_token。如果 refresh_token 有效,過濾器將生成新的 access_tokenrefresh_token 并將它們放入HTTP響應頭中。如果從Token中解析出的用戶信息有效,過濾器將創(chuàng)建一個認證對象并將其設置到 SecurityContextHolder 中,這樣,Spring Security就可以在后續(xù)處理中使用這個認證信息。

結(jié)論

通過上述代碼,你可以在Spring Boot應用中實現(xiàn)一個基本的無感知Token刷新機制。這只是一個基礎示例,實際應用中你可能需要添加更多的錯誤處理、日志記錄以及安全措施。此外,處理和存儲 refresh_token 需要特別小心,因為它具有較長的有效期并能用于獲取新的 access_token

以上就是使用SpringBoot簡單實現(xiàn)無感知的刷新 Token功能的詳細內(nèi)容,更多關于SpringBoot無感知刷新Token的資料請關注腳本之家其它相關文章!

相關文章

  • Spring中基于XML的AOP配置詳解

    Spring中基于XML的AOP配置詳解

    這篇文章主要介紹了Spring中基于XML的AOP配置,本文通過圖文實例相結(jié)合給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-10-10
  • SpringBoot上傳文件到本服務器 目錄與jar包同級問題

    SpringBoot上傳文件到本服務器 目錄與jar包同級問題

    這篇文章主要介紹了SpringBoot上傳文件到本服務器 目錄與jar包同級問題,需要的朋友可以參考下
    2018-11-11
  • 詳解Spring Cloud中Hystrix的請求合并

    詳解Spring Cloud中Hystrix的請求合并

    這篇文章主要介紹了詳解Spring Cloud中Hystrix的請求合并,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-05-05
  • 詳解spring多線程與定時任務

    詳解spring多線程與定時任務

    本篇文章主要介紹了spring多線程與定時任務,詳細的介紹了spring多線程任務和spring定時任務,有興趣的可以了解一下。
    2017-04-04
  • Springboot集成GraphicsMagick

    Springboot集成GraphicsMagick

    本文主要是教大家如何將GraphicsMagick命令行工具集成到Springboot項目中,便可以使用Java進行圖片處理相關開發(fā)。
    2021-05-05
  • Java實現(xiàn)常見排序算法的優(yōu)化

    Java實現(xiàn)常見排序算法的優(yōu)化

    今天給大家?guī)淼氖顷P于Java的相關知識,文章圍繞著Java實現(xiàn)常見排序算法的優(yōu)化展開,文中有非常詳細的介紹及代碼示例,需要的朋友可以參考下
    2021-01-01
  • MyBatis?在使用上的注意事項及其辨析(最新最全整理)

    MyBatis?在使用上的注意事項及其辨析(最新最全整理)

    這篇文章主要介紹了MyBatis的在使用上的注意事項及其辨析,本文內(nèi)容比較長,是小編用心給大家整理的,圖文實例代碼相結(jié)合給大家講解的非常詳細,需要的朋友參考下吧
    2024-06-06
  • 如何使用Jenkins編譯并打包SpringCloud微服務目錄

    如何使用Jenkins編譯并打包SpringCloud微服務目錄

    這篇文章主要介紹了如何使用Jenkins編譯并打包SpringCloud微服務目錄,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-11-11
  • Spring使用注解更簡單的讀取和存儲對象的方法

    Spring使用注解更簡單的讀取和存儲對象的方法

    這篇文章主要介紹了Spring使用注解更簡單的讀取和存儲對象的方法,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2023-07-07
  • Spring中@ConfigurationProperties的用法解析

    Spring中@ConfigurationProperties的用法解析

    這篇文章主要介紹了Spring中@ConfigurationProperties的用法解析,傳統(tǒng)的Spring一般都是基本xml配置的,后來spring3.0新增了許多java config的注解,特別是spring boot,基本都是清一色的java config,需要的朋友可以參考下
    2023-11-11

最新評論