在现代的Web开发中,JWT(JSON Web Token)被广泛应用于用户认证和授权。基于JWT的双token机制,即使用access_token和refresh_token的组合,能够有效地提高应用的安全性和用户体验。下面,我们将探讨如何在Spring Boot中实现这一方案。

1. 方案概述

  • Access Token:短期有效的令牌,用于用户的身份验证,通常在用户登录后生成,并具有较短的过期时间(如15分钟)。
  • Refresh Token:长期有效的令牌,用于获取新的access_token,通常具有较长的过期时间(如7天或更长)。

使用双token机制的好处在于,即使access_token被盗取,攻击者也只能在有效期内使用它,而refresh_token则可以通过更严格的策略来管理,从而进一步提升安全性。

2. 依赖配置

在Spring Boot项目中,首先需要添加JWT相关的依赖。可以在pom.xml中添加如下依赖:

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

3. JWT工具类

创建一个JWT工具类,用于生成和验证token。

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

import java.util.Date;

@Component
public class JwtUtil {
    private String secretKey = "your_secret_key";
    private long accessTokenValidity = 15 * 60 * 1000; // 15分钟
    private long refreshTokenValidity = 7 * 24 * 60 * 60 * 1000; // 7天

    public String generateAccessToken(String username) {
        return generateToken(username, accessTokenValidity);
    }

    public String generateRefreshToken(String username) {
        return generateToken(username, refreshTokenValidity);
    }

    private String generateToken(String username, long validity) {
        long now = System.currentTimeMillis();
        Date expiryDate = new Date(now + validity);
        JwtBuilder builder = Jwts.builder()
                .setSubject(username)
                .setIssuedAt(new Date(now))
                .setExpiration(expiryDate)
                .signWith(SignatureAlgorithm.HS512, secretKey);
        return builder.compact();
    }

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

4. 用户认证与授权

在用户登录成功后,将生成access_token和refresh_token,并将它们返回给前端。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/auth")
public class AuthController {

    @Autowired
    private JwtUtil jwtUtil;

    @PostMapping("/login")
    public ResponseEntity<Map<String, String>> login(@RequestBody LoginRequest loginRequest) {
        // 验证用户身份逻辑省略
        String username = loginRequest.getUsername();
        String accessToken = jwtUtil.generateAccessToken(username);
        String refreshToken = jwtUtil.generateRefreshToken(username);

        Map<String, String> tokens = new HashMap<>();
        tokens.put("access_token", accessToken);
        tokens.put("refresh_token", refreshToken);

        return ResponseEntity.ok(tokens);
    }
}

5. 刷新token逻辑

当access_token过期时,用户可以使用refresh_token获取新的access_token。

@PostMapping("/refresh")
public ResponseEntity<Map<String, String>> refresh(@RequestBody Map<String, String> token) {
    String refreshToken = token.get("refresh_token");
    Claims claims = jwtUtil.validateToken(refreshToken);

    // 检查refresh_token是否有效(可以添加更多逻辑)
    String username = claims.getSubject();
    String newAccessToken = jwtUtil.generateAccessToken(username);

    Map<String, String> tokens = new HashMap<>();
    tokens.put("access_token", newAccessToken);

    return ResponseEntity.ok(tokens);
}

6. 总结

基于JWT的双token机制在Spring Boot中实现相对简单,但仍需注意安全性问题,比如对refresh_token的存储和验证过程。在实际应用中,可以结合数据库和缓存技术以增强令牌的安全性和有效性。通过这种认证机制,可以有效地保护用户的敏感信息,提高用户的登录体验。

点赞(0) 打赏

微信小程序

微信扫一扫体验

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部