本文目录导读:

- 添加依赖
- JWT工具类
- 用户认证Controller
- JWT认证过滤器
- Spring Security配置
- 受保护的API示例
- 测试示例
- 使用Interceptor方式(不依赖Spring Security)
- 前端调用示例
- 最佳实践建议
我来详细说明如何在Java中实现JWT令牌认证,包含完整的示例代码。
添加依赖
Maven依赖
<!-- JWT -->
<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>
JWT工具类
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import javax.crypto.SecretKey;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class JwtUtil {
// 密钥(生产环境建议从配置文件中读取)
private static final String SECRET = "YourSuperSecretKeyForJWTTokenGeneration2024!@#$%^&*()";
// 过期时间(24小时)
private static final long EXPIRATION_TIME = 24 * 60 * 60 * 1000;
private static SecretKey getSigningKey() {
return Keys.hmacShaKeyFor(SECRET.getBytes());
}
/**
* 生成JWT令牌
*/
public static String generateToken(String username, Map<String, Object> claims) {
if (claims == null) {
claims = new HashMap<>();
}
return Jwts.builder()
.setClaims(claims) // 自定义声明
.setSubject(username) // 主题(通常是用户名)
.setIssuedAt(new Date()) // 签发时间
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) // 过期时间
.signWith(getSigningKey(), SignatureAlgorithm.HS256) // 签名算法
.compact();
}
/**
* 解析JWT令牌
*/
public static Claims parseToken(String token) {
try {
return Jwts.parserBuilder()
.setSigningKey(getSigningKey())
.build()
.parseClaimsJws(token)
.getBody();
} catch (JwtException | IllegalArgumentException e) {
throw new RuntimeException("JWT令牌无效或已过期");
}
}
/**
* 验证令牌是否有效
*/
public static boolean validateToken(String token) {
try {
Jwts.parserBuilder()
.setSigningKey(getSigningKey())
.build()
.parseClaimsJws(token);
return true;
} catch (JwtException | IllegalArgumentException e) {
return false;
}
}
/**
* 从令牌中获取用户名
*/
public static String getUsernameFromToken(String token) {
Claims claims = parseToken(token);
return claims.getSubject();
}
/**
* 检查令牌是否过期
*/
public static boolean isTokenExpired(String token) {
try {
Claims claims = parseToken(token);
return claims.getExpiration().before(new Date());
} catch (Exception e) {
return true;
}
}
}
用户认证Controller
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/api/auth")
public class AuthController {
// 模拟用户数据库
private static final Map<String, String> USERS = new HashMap<>();
static {
USERS.put("admin", "admin123");
USERS.put("user", "user123");
}
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) {
String username = loginRequest.getUsername();
String password = loginRequest.getPassword();
// 验证用户名密码
if (USERS.containsKey(username) && USERS.get(username).equals(password)) {
// 创建自定义声明
Map<String, Object> claims = new HashMap<>();
claims.put("role", username.equals("admin") ? "ADMIN" : "USER");
// 生成JWT令牌
String token = JwtUtil.generateToken(username, claims);
// 返回令牌信息
Map<String, Object> response = new HashMap<>();
response.put("token", token);
response.put("username", username);
response.put("expiresIn", 24 * 60 * 60); // 秒
return ResponseEntity.ok(response);
} else {
return ResponseEntity.status(401).body("用户名或密码错误");
}
}
}
// 登录请求对象
class LoginRequest {
private String username;
private String password;
// getter和setter方法
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
}
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;
import java.util.ArrayList;
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain)
throws ServletException, IOException {
String token = extractTokenFromRequest(request);
if (token != null && JwtUtil.validateToken(token)) {
String username = JwtUtil.getUsernameFromToken(token);
// 创建认证对象
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(
username, null, new ArrayList<>());
// 设置认证信息到安全上下文
SecurityContextHolder.getContext().setAuthentication(authentication);
}
filterChain.doFilter(request, response);
}
/**
* 从请求中提取JWT令牌
*/
private String extractTokenFromRequest(HttpServletRequest request) {
String bearerToken = request.getHeader("Authorization");
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
return null;
}
}
Spring Security配置
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.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable() // 禁用CSRF保护
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 无状态会话
.and()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll() // 认证接口不需要认证
.antMatchers("/api/admin/**").hasRole("ADMIN") // 管理员接口
.antMatchers("/api/**").authenticated() // 其他API需要认证
.and()
.addFilterBefore(new JwtAuthenticationFilter(),
UsernamePasswordAuthenticationFilter.class); // 添加JWT过滤器
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
受保护的API示例
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/api")
public class UserController {
@GetMapping("/profile")
public ResponseEntity<?> getProfile(@RequestHeader("Authorization") String token) {
// 从令牌中获取用户信息
String jwtToken = token.replace("Bearer ", "");
String username = JwtUtil.getUsernameFromToken(jwtToken);
Map<String, Object> profile = new HashMap<>();
profile.put("username", username);
profile.put("email", username + "@example.com");
profile.put("createTime", "2024-01-01");
return ResponseEntity.ok(profile);
}
@GetMapping("/admin/users")
public ResponseEntity<?> getAllUsers() {
// 只有管理员可以访问
return ResponseEntity.ok("Admin data");
}
}
测试示例
public class JwtTest {
public static void main(String[] args) {
// 1. 生成令牌
Map<String, Object> claims = new HashMap<>();
claims.put("role", "ADMIN");
claims.put("email", "admin@example.com");
String token = JwtUtil.generateToken("admin", claims);
System.out.println("生成的Token: " + token);
// 2. 验证令牌
boolean isValid = JwtUtil.validateToken(token);
System.out.println("令牌是否有效: " + isValid);
// 3. 解析令牌
Claims parsedClaims = JwtUtil.parseToken(token);
System.out.println("用户名: " + parsedClaims.getSubject());
System.out.println("角色: " + parsedClaims.get("role"));
System.out.println("邮箱: " + parsedClaims.get("email"));
System.out.println("过期时间: " + parsedClaims.getExpiration());
// 4. 获取用户名
String username = JwtUtil.getUsernameFromToken(token);
System.out.println("从Token获取的用户名: " + username);
// 5. 检查是否过期
boolean isExpired = JwtUtil.isTokenExpired(token);
System.out.println("是否过期: " + isExpired);
}
}
使用Interceptor方式(不依赖Spring Security)
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class JwtInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
// 放行登录请求
if (request.getRequestURI().contains("/api/auth/login")) {
return true;
}
String token = extractToken(request);
if (token == null || !JwtUtil.validateToken(token)) {
response.setStatus(401);
response.getWriter().write("{\"error\": \"未授权访问\"}");
return false;
}
// 将用户信息设置到请求属性中
String username = JwtUtil.getUsernameFromToken(token);
request.setAttribute("username", username);
return true;
}
private String extractToken(HttpServletRequest request) {
String bearerToken = request.getHeader("Authorization");
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
return null;
}
}
前端调用示例
// 登录
async function login() {
const response = await fetch('/api/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: 'admin',
password: 'admin123'
})
});
const data = await response.json();
const token = data.token;
// 存储token到本地
localStorage.setItem('jwt_token', token);
// 后续请求携带token
const profileResponse = await fetch('/api/profile', {
headers: {
'Authorization': `Bearer ${token}`
}
});
const profile = await profileResponse.json();
console.log(profile);
}
最佳实践建议
- 密钥管理:使用密钥管理服务,不要硬编码
- 令牌过期:设置合理的过期时间(通常15-30分钟)
- HTTPS:生产环境必须使用HTTPS
- 刷新机制:实现Token刷新机制
- 黑名单:考虑实现Token黑名单机制
- 日志记录:记录重要的认证事件
这个实现提供了完整的JWT认证流程,你可以根据具体需求进行调整和扩展。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播