java-JWT鉴权

前言:

JWT,也就是JSON Web Token,通常用于身份验证和授权。用户登录后,服务器生成一个JWT,客户端之后每次请求都带着这个Token,服务器验证Token的有效性来鉴权。


完整示例:

第一步:添加依赖(pom.xml)

<dependencies>
    <!-- Spring Boot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- JJWT 库 -->
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-api</artifactId>
        <version>0.11.5</version>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-impl</artifactId>
        <version>0.11.5</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-jackson</artifactId>
        <version>0.11.5</version>
        <scope>runtime</scope>
    </dependency>
</dependencies>

第二步:创建 JWT 工具类

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.springframework.stereotype.Component;
import javax.crypto.SecretKey;
import java.util.Date;

@Component
public class JwtUtil {
    // 密钥(示例代码硬编码,实际应存储在安全位置)
    private final SecretKey SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);
    // Token 有效期(30分钟)
    private final long EXPIRATION_TIME = 1800000;

    // 生成 JWT
    public String generateToken(String username) {
        return Jwts.builder()
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                .signWith(SECRET_KEY)
                .compact();
    }

    // 验证并解析 JWT
    public Claims parseToken(String token) {
        return Jwts.parserBuilder()
                .setSigningKey(SECRET_KEY)
                .build()
                .parseClaimsJws(token)
                .getBody();
    }

    // 检查 Token 是否过期
    public boolean isTokenExpired(String token) {
        return parseToken(token).getExpiration().before(new Date());
    }
}

第三步:创建登录接口和受保护接口

import org.springframework.web.bind.annotation.*;

@RestController
public class AuthController {
    private final JwtUtil jwtUtil;

    public AuthController(JwtUtil jwtUtil) {
        this.jwtUtil = jwtUtil;
    }

    // 登录接口(模拟)
    @PostMapping("/login")
    public String login(@RequestParam String username, @RequestParam String password) {
        // 这里应该验证用户名密码(示例直接返回Token)
        return jwtUtil.generateToken(username);
    }

    // 需要鉴权的接口
    @GetMapping("/secure")
    public String secureEndpoint() {
        return "访问受保护资源成功";
    }
}

第四步:创建 JWT 过滤器

import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;

public class JwtFilter extends OncePerRequestFilter {
    private final JwtUtil jwtUtil;

    public JwtFilter(JwtUtil jwtUtil) {
        this.jwtUtil = jwtUtil;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, 
                                   HttpServletResponse response, 
                                   FilterChain filterChain)
            throws ServletException, IOException {
        String authHeader = request.getHeader("Authorization");
        
        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            String token = authHeader.substring(7);
            try {
                Claims claims = jwtUtil.parseToken(token);
                if (jwtUtil.isTokenExpired(token)) {
                    response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Token已过期");
                    return;
                }
                // 可以在此处将用户信息存入请求上下文
                request.setAttribute("username", claims.getSubject());
            } catch (JwtException e) {
                response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "无效Token");
                return;
            }
        } else {
            // 放行登录接口
            if (!request.getServletPath().equals("/login")) {
                response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "缺少Token");
                return;
            }
        }
        filterChain.doFilter(request, response);
    }
}

第五步:配置 Spring Boot 应用

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class JwtDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(JwtDemoApplication.class, args);
    }

    @Bean
    public FilterRegistrationBean<JwtFilter> jwtFilter(JwtUtil jwtUtil) {
        FilterRegistrationBean<JwtFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new JwtFilter(jwtUtil));
        registrationBean.addUrlPatterns("/secure");
        return registrationBean;
    }
}

使用示例:

  1. 启动应用后,发送登录请求获取Token:

    curl -X POST http://localhost:8080/login?username=admin&password=123

  2. 使用返回的Token访问受保护接口:

    curl -H "Authorization: Bearer <your_token>" http://localhost:8080/secure

注意事项:

  1. 实际生产环境中:

    • 密钥应存储在安全位置(如配置中心)

    • 密码需要加密存储和验证

    • 需要使用HTTPS保证传输安全

    • 需要考虑Token刷新机制

  2. 该示例使用HS256算法,如需更安全可选择RS256算法

  3. 可根据需要添加更多用户信息到Token Claims中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

在下陈平安

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

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

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

打赏作者

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

抵扣说明:

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

余额充值