📅  最后修改于: 2023-12-03 14:49:18.117000             🧑  作者: Mango
在使用 Spring Boot 构建 Web 应用程序时,我们常常会使用 JWT(JSON Web Tokens)来进行认证和授权。JWT 是一种安全的、轻量级的授权令牌机制,通常在请求的 Header
中携带 JWT 令牌来进行用户认证。
本文将介绍如何通过在 Spring Boot 中解析 JWT 令牌,从中提取出用户名信息。
以下是获取 JWT 令牌中的用户名的基本步骤:
TokenProvider
类,用于解析 JWT 令牌。import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.util.Base64;
import java.util.Date;
@Component
public class TokenProvider {
@Value("${jwt.secretKey}")
private String secretKey;
@Value("${jwt.tokenValidity}")
private long tokenValidity;
private static final String AUTHORIZATION_HEADER = "Authorization";
private static final String BEARER_PREFIX = "Bearer ";
private byte[] secretKeyBytes;
@PostConstruct
public void init() {
secretKeyBytes = Base64.getEncoder().encode(secretKey.getBytes());
}
// 生成 JWT 令牌
public String createToken(String username) {
Date now = new Date();
Date expirationDate = new Date(now.getTime() + tokenValidity);
return Jwts.builder()
.setSubject(username)
.setIssuedAt(now)
.setExpiration(expirationDate)
.signWith(SignatureAlgorithm.HS512, secretKeyBytes)
.compact();
}
// 从 HttpServletRequest 中解析 JWT 令牌
public String resolveToken(HttpServletRequest request) {
String bearerToken = request.getHeader(AUTHORIZATION_HEADER);
if (bearerToken != null && bearerToken.startsWith(BEARER_PREFIX)) {
return bearerToken.substring(BEARER_PREFIX.length());
}
return null;
}
// 验证并解析 JWT 令牌
public boolean validateToken(String token) {
try {
Jwts.parser()
.setSigningKey(secretKeyBytes)
.parseClaimsJws(token);
return true;
} catch (Exception e) {
// 处理异常情况
}
return false;
}
// 从 JWT 令牌中获取用户名
public String getUsername(String token) {
Claims claims = Jwts.parser()
.setSigningKey(secretKeyBytes)
.parseClaimsJws(token)
.getBody();
return claims.getSubject();
}
// 构建 Authentication 对象
public UsernamePasswordAuthenticationToken getAuthentication(String token) {
if (validateToken(token)) {
String username = getUsername(token);
// 根据用户名构建 Authentication 对象
// 这里可以根据业务需求自定义逻辑
return new UsernamePasswordAuthenticationToken(username, null, null);
}
return null;
}
}
jwt.secretKey=mySecretKey
jwt.tokenValidity=86400000
在上述配置中,jwt.secretKey
是用于对 JWT 进行签名的密钥,jwt.tokenValidity
是 JWT 令牌的有效期,单位为毫秒。
JwtFilter
类,用于过滤请求并解析 JWT 令牌。import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
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 JwtFilter extends OncePerRequestFilter {
private TokenProvider tokenProvider;
public JwtFilter(TokenProvider tokenProvider) {
this.tokenProvider = tokenProvider;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String jwtToken = tokenProvider.resolveToken(request);
if (jwtToken != null && tokenProvider.validateToken(jwtToken)) {
UsernamePasswordAuthenticationToken authenticationToken = tokenProvider.getAuthentication(jwtToken);
if (authenticationToken != null) {
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
}
}
filterChain.doFilter(request, response);
}
}
JwtFilter
添加到 Spring Security 配置中。import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private TokenProvider tokenProvider;
public SecurityConfig(TokenProvider tokenProvider) {
this.tokenProvider = tokenProvider;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/public").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(new JwtFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class);
}
@Bean
public FilterRegistrationBean<JwtFilter> jwtFilterRegistrationBean() {
FilterRegistrationBean<JwtFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new JwtFilter(tokenProvider));
// 设置过滤路径
registrationBean.addUrlPatterns("/api/*");
return registrationBean;
}
}
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class UserController {
@GetMapping("/username")
public String getUsername() {
// 从 SecurityContext 中获取当前登录用户的用户名
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return authentication.getName();
}
}
application.yml
或 application.properties
中配置 Spring Security 相关的配置项。这里简单配置 Basic 认证。spring.security.user.name=admin
spring.security.user.password=s3cr3t
spring.security.user.roles=USER
/api/username
路径,即可获取当前登录用户的用户名。GET /api/username HTTP/1.1
Host: localhost:8080
Authorization: Bearer {JWT Token}
以上就是从 JWT 令牌中获取用户名的步骤。通过配置和修改这些代码片段,您可以根据自己的需求进行定制化开发。