JWT和网关双令牌登录验证

使用JWT(JSON Web Token)和网关实现双令牌登录验证是一种安全性较高的方案。双令牌通常包括一个短期有效的访问令牌(access token)和一个长期有效的刷新令牌(refresh token)。以下是如何在Spring Boot项目中使用JWT和网关实现双令牌登录验证的步骤:

1. 设计令牌生成与验证策略

  • 访问令牌(Access Token):访问令牌是一个短期有效的JWT,它包含用户的身份信息和权限。访问令牌通常用于保护API端点,以确保只有授权用户才能访问。
  • 刷新令牌(Refresh Token):刷新令牌是一个长期有效的令牌,它用于在访问令牌过期后获取新的访问令牌。刷新令牌通常比访问令牌更安全,因为它只用于刷新令牌,不用于访问API。

2. 引入依赖

Maven依赖:

<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Spring Boot Starter Security -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>

    <!-- Spring Cloud Gateway -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>

    <!-- JWT依赖 -->
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-api</artifactId>
        <version>0.11.2</version>
    </dependency>
</dependencies>

3. 生成和验证JWT

定义一个类,用于生成和验证JWT。可以使用JJWT库来处理JWT:

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;

public class JwtUtils {

    private static final String SECRET_KEY = "your-secret-key";
    private static final long ACCESS_TOKEN_EXPIRY = 5 * 60 * 1000; // 5分钟
    private static final long REFRESH_TOKEN_EXPIRY = 30 * 24 * 60 * 1000; // 30天

    // 生成访问令牌
    public static String generateAccessToken(String username) {
        return Jwts.builder()
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + ACCESS_TOKEN_EXPIRY))
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                .compact();
    }

    // 生成刷新令牌
    public static String generateRefreshToken(String username) {
        return Jwts.builder()
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + REFRESH_TOKEN_EXPIRY))
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                .compact();
    }

    // 验证令牌
    public static String verifyToken(String token) {
        try {
            return Jwts.parser()
                    .setSigningKey(SECRET_KEY)
                    .parseClaimsJws(token)
                    .getBody()
                    .getSubject();
        } catch (Exception e) {
            return null; // 验证失败
        }
    }
}

这个类负责生成访问令牌和刷新令牌,以及验证令牌。

4. 在登录接口中使用JWT

在登录接口中,验证用户的凭证(例如用户名和密码),如果验证成功,生成访问令牌和刷新令牌,并将它们返回给客户端。

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AuthController {

    @PostMapping("/login")
    public ResponseEntity<Map<String, String>> login(@RequestBody LoginRequest loginRequest) {
        // 验证用户凭证(例如用户名和密码)
        // 假设验证通过
        
        // 生成访问令牌和刷新令牌
        String accessToken = JwtUtils.generateAccessToken(loginRequest.getUsername());
        String refreshToken = JwtUtils.generateRefreshToken(loginRequest.getUsername());

        // 返回令牌
        Map<String, String> tokens = new HashMap<>();
        tokens.put("accessToken", accessToken);
        tokens.put("refreshToken", refreshToken);

        return ResponseEntity.ok(tokens);
    }
}

5. 在网关中验证访问令牌

在Spring Cloud Gateway中使用自定义过滤器来验证访问令牌:

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Configuration
public class JwtAuthenticationFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 从请求头中获取令牌
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");

        // 验证令牌
        String username = JwtUtils.verifyToken(token);
        if (username == null) {
            // 令牌验证失败
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }

        // 令牌验证成功,继续处理请求
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return -1; // 设置过滤器优先级
    }
}

这个过滤器会在请求到达网关时验证访问令牌。如果令牌无效或缺失,过滤器会返回HTTP 401 Unauthorized响应;否则,继续处理请求。

6. 刷新令牌

你可以提供一个接口,用于根据刷新令牌获取新的访问令牌。这通常是在访问令牌过期后客户端请求的。

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TokenController {

    @PostMapping("/refresh")
    public ResponseEntity<String> refresh(@RequestBody Map<String, String> request) {
        String refreshToken = request.get("refreshToken");
        String username = JwtUtils.verifyToken(refreshToken);

        if (username == null) {
            // 刷新令牌验证失败
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
        }

        // 生成新的访问令牌
        String newAccessToken = JwtUtils.generateAccessToken(username);

        return ResponseEntity.ok(newAccessToken);
    }
}

总结:

通过以上步骤,你可以使用JWT和网关实现双令牌登录验证。该方案通过访问令牌保护API端点,通过刷新令牌获取新的访问令牌,提高了安全性和用户体验。在生产环境中,记得对JWT的密钥和配置进行妥善管理。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在微服务架构中,网关作为服务的入口,扮演着非常重要的角色。对于网关的认证和鉴权,可以通过以下几种方式进行设计: 1. 使用JWT令牌认证:JWT令牌是一种轻量级的认证方式,可以在用户登录后颁发一个包含用户信息的JWT令牌,然后将该令牌存储在客户端中。当客户端请求微服务时,将JWT令牌携带在请求头中,网关可以通过验证JWT令牌中的签名和有效期来判断令牌是否有效,从而进行认证和鉴权。 2. 使用OAuth2认证:OAuth2是一种标准的认证协议,可以通过OAuth2服务器颁发访问令牌,然后将访问令牌存储在客户端中。当客户端请求微服务时,将访问令牌携带在请求头中,网关可以通过OAuth2服务器验证访问令牌的有效性,从而进行认证和鉴权。 3. 使用API密钥认证:API密钥是一种简单的认证方式,可以为每个微服务颁发一个唯一的API密钥,然后将API密钥存储在客户端中。当客户端请求微服务时,将API密钥携带在请求头中,网关可以通过验证API密钥的有效性来进行认证和鉴权。 4. 使用服务代理认证:服务代理是一种将多个微服务封装在一起的方式,可以通过服务代理对微服务进行统一的认证和鉴权。服务代理可以在请求微服务之前进行认证和鉴权,从而保证请求的合法性。 总之,在微服务中,网关的认证和鉴权非常重要,可以根据业务需求和安全要求,选择合适的认证方式进行设计。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

惊雲浅谈天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值