首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

如何让jwt令牌自动刷新?弹簧护套角

JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在网络应用环境间安全地将信息作为JSON对象传输。JWT令牌自动刷新是一种机制,用于在令牌过期前自动获取新的令牌,以避免用户频繁登录。

基础概念

JWT通常由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。头部和载荷分别是Base64Url编码的JSON字符串,它们之间用一个点(.)分隔。签名是使用头部、载荷和一个密钥通过指定的算法生成的。

自动刷新机制

自动刷新JWT令牌通常涉及以下几个步骤:

  1. 设置合理的过期时间:JWT令牌应设置一个合理的过期时间,既不能太短以免频繁刷新,也不能太长以保证安全性。
  2. 客户端定时检查:客户端应用需要定时检查当前JWT令牌的过期时间。
  3. 刷新令牌:当检测到令牌即将过期时,客户端向服务器发送请求以获取新的令牌。
  4. 服务器端验证:服务器验证客户端的身份,并生成新的JWT令牌返回给客户端。

应用场景

自动刷新JWT令牌适用于需要长时间保持用户登录状态的Web应用和移动应用,例如社交网络、在线购物平台等。

实现方法

以下是一个简单的Spring Boot示例,展示如何实现JWT令牌的自动刷新:

1. 添加依赖

pom.xml中添加Spring Security和JWT相关的依赖:

代码语言:txt
复制
<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>

2. 创建JWT工具类

代码语言:txt
复制
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
public class JwtTokenUtil {

    @Value("${jwt.secret}")
    private String secret;

    public String generateToken(String username) {
        return Jwts.builder()
                .setSubject(username)
                .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10)) // 10小时过期
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();
    }

    public String refreshToken(String token) {
        String username = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody().getSubject();
        return generateToken(username);
    }

    public boolean validateToken(String token) {
        try {
            Jwts.parser().setSigningKey(secret).parseClaimsJws(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}

3. 创建JWT过滤器

代码语言:txt
复制
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
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 JwtAuthenticationFilter extends OncePerRequestFilter {

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

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

        if (header != null && header.startsWith("Bearer ")) {
            String token = header.substring(7);
            if (jwtTokenUtil.validateToken(token)) {
                Authentication authentication = jwtTokenUtil.getAuthentication(token);
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }

        chain.doFilter(request, response);
    }
}

4. 配置Spring Security

代码语言:txt
复制
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

    @Autowired
    private UserDetailsService jwtUserDetailsService;

    @Autowired
    private JwtAuthenticationFilter jwtAuthenticationFilter;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.csrf().disable()
                .authorizeRequests().antMatchers("/authenticate").permitAll()
                .anyRequest().authenticated()
                .and()
                .exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint)
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        httpSecurity.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

5. 客户端定时刷新

客户端可以使用JavaScript定时器来定期检查令牌的过期时间,并在需要时刷新令牌。

代码语言:txt
复制
function refreshToken() {
    const token = localStorage.getItem('token');
    const expirationTime = new Date(localStorage.getItem('expirationTime'));

    if (expirationTime && new Date() >= expirationTime - 60000) { // 提前1分钟刷新
        fetch('/refreshToken', {
            method: 'POST',
            headers: {
                'Authorization': `Bearer ${token}`
            }
        })
        .then(response => response.json())
        .then(data => {
            localStorage.setItem('token', data.token);
            localStorage.setItem('expirationTime', new Date().getTime() + 1000 * 60 * 60 * 10); // 10小时过期
        });
    }
}

setInterval(refreshToken, 60000); // 每分钟检查一次

参考链接

通过上述步骤,你可以实现JWT令牌的自动刷新机制,确保用户在应用中的持续登录状态。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

领券