本文目录导读:

我来为您提供一个完整的Spring Boot整合JWT的案例,包含完整的代码实现。
项目结构
spring-boot-jwt-demo/
├── pom.xml
└── src/main/java/com/example/jwt/
├── JwtDemoApplication.java
├── config/
│ ├── SecurityConfig.java
│ └── JwtProperties.java
├── controller/
│ ├── AuthController.java
│ └── UserController.java
├── filter/
│ └── JwtAuthenticationFilter.java
├── model/
│ ├── User.java
│ └── Role.java
├── repository/
│ └── UserRepository.java
├── security/
│ └── JwtUtil.java
└── dto/
├── LoginRequest.java
├── LoginResponse.java
├── RegisterRequest.java
└── ApiResponse.java
pom.xml 依赖配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.14</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>spring-boot-jwt-demo</artifactId>
<version>1.0.0</version>
<name>spring-boot-jwt-demo</name>
<description>Spring Boot JWT Demo</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- Spring Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- 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>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 配置处理器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- 测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
application.yml 配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/jwt_demo?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf-8
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
format_sql: true
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
# JWT配置
jwt:
secret: your-secret-key-at-least-256-bits-long-for-hs256-algorithm
expiration: 3600000 # 1小时(毫秒)
header: Authorization
prefix: "Bearer "
server:
port: 8080
核心代码实现
1 实体类
User.java
package com.example.jwt.model;
import javax.persistence.*;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.Set;
@Entity
@Table(name = "users")
@Data
@NoArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true, nullable = false, length = 50)
private String username;
@Column(nullable = false)
private String password;
@Column(unique = true, nullable = false)
private String email;
@Column(name = "created_at")
private LocalDateTime createdAt;
@Column(name = "updated_at")
private LocalDateTime updatedAt;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "user_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id")
)
private Set<Role> roles = new HashSet<>();
@PrePersist
protected void onCreate() {
createdAt = LocalDateTime.now();
updatedAt = LocalDateTime.now();
}
@PreUpdate
protected void onUpdate() {
updatedAt = LocalDateTime.now();
}
}
Role.java
package com.example.jwt.model;
import javax.persistence.*;
import lombok.Data;
import lombok.NoArgsConstructor;
@Entity
@Table(name = "roles")
@Data
@NoArgsConstructor
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true, nullable = false)
private String name;
private String description;
}
2 Repository
UserRepository.java
package com.example.jwt.repository;
import com.example.jwt.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
Optional<User> findByEmail(String email);
Boolean existsByUsername(String username);
Boolean existsByEmail(String email);
}
3 JWT工具类
JwtUtil.java
package com.example.jwt.security;
import io.jsonwebtoken.*;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
@Component
public class JwtUtil {
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expiration}")
private Long expiration;
// 从token中提取用户名
public String extractUsername(String token) {
return extractClaim(token, Claims::getSubject);
}
// 从token中提取过期时间
public Date extractExpiration(String token) {
return extractClaim(token, Claims::getExpiration);
}
// 提取指定的claim
public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
final Claims claims = extractAllClaims(token);
return claimsResolver.apply(claims);
}
// 提取所有claims
private Claims extractAllClaims(String token) {
return Jwts.parserBuilder()
.setSigningKey(getSignKey())
.build()
.parseClaimsJws(token)
.getBody();
}
// 判断token是否过期
private Boolean isTokenExpired(String token) {
return extractExpiration(token).before(new Date());
}
// 生成token
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
claims.put("roles", userDetails.getAuthorities());
return createToken(claims, userDetails.getUsername());
}
// 创建token
private String createToken(Map<String, Object> claims, String subject) {
return Jwts.builder()
.setClaims(claims) // 设置自定义claims
.setSubject(subject) // 设置主题(用户名)
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + expiration))
.signWith(getSignKey(), SignatureAlgorithm.HS256)
.compact();
}
// 验证token
public Boolean validateToken(String token, UserDetails userDetails) {
final String username = extractUsername(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
// 获取签名密钥
private Key getSignKey() {
byte[] keyBytes = Decoders.BASE64.decode(secret);
return Keys.hmacShaKeyFor(keyBytes);
}
}
4 JWT认证过滤器
JwtAuthenticationFilter.java
package com.example.jwt.filter;
import com.example.jwt.security.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
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;
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private JwtUtil jwtUtil;
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// 从请求头中提取token
String token = getTokenFromRequest(request);
// 验证token
if (StringUtils.hasText(token) && SecurityContextHolder.getContext().getAuthentication() == null) {
try {
String username = jwtUtil.extractUsername(token);
if (username != null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (jwtUtil.validateToken(token, userDetails)) {
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(
userDetails,
null,
userDetails.getAuthorities()
);
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
} catch (Exception e) {
logger.error("Cannot set user authentication: {}", e);
}
}
filterChain.doFilter(request, response);
}
// 从请求中提取token
private String getTokenFromRequest(HttpServletRequest request) {
String bearerToken = request.getHeader("Authorization");
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
return null;
}
}
5 自定义UserDetailsService
package com.example.jwt.security;
import com.example.jwt.model.User;
import com.example.jwt.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.stream.Collectors;
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
@Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found with username: " + username));
return org.springframework.security.core.userdetails.User
.builder()
.username(user.getUsername())
.password(user.getPassword())
.authorities(user.getRoles().stream()
.map(role -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toList()))
.build();
}
}
6 Security配置
SecurityConfig.java
package com.example.jwt.config;
import com.example.jwt.filter.JwtAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/users/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.exceptionHandling().authenticationEntryPoint((request, response, authException) -> {
response.setStatus(401);
response.getWriter().write("Unauthorized");
});
// 添加JWT过滤器
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
return configuration.getAuthenticationManager();
}
}
7 DTO类
LoginRequest.java
package com.example.jwt.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class LoginRequest {
@NotBlank(message = "用户名不能为空")
private String username;
@NotBlank(message = "密码不能为空")
private String password;
}
LoginResponse.java
package com.example.jwt.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class LoginResponse {
private String token;
private String tokenType = "Bearer";
private Long expiresIn;
private String username;
public LoginResponse(String token, Long expiresIn, String username) {
this.token = token;
this.expiresIn = expiresIn;
this.username = username;
}
}
RegisterRequest.java
package com.example.jwt.dto;
import lombok.Data;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
@Data
public class RegisterRequest {
@NotBlank(message = "用户名不能为空")
@Size(min = 3, max = 50, message = "用户名长度应在3-50之间")
private String username;
@NotBlank(message = "密码不能为空")
@Size(min = 6, max = 100, message = "密码长度应在6-100之间")
private String password;
@NotBlank(message = "邮箱不能为空")
@Email(message = "邮箱格式不正确")
private String email;
}
ApiResponse.java
package com.example.jwt.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ApiResponse<T> {
private boolean success;
private String message;
private T data;
public static <T> ApiResponse<T> success(T data) {
return new ApiResponse<>(true, "操作成功", data);
}
public static <T> ApiResponse<T> success(String message, T data) {
return new ApiResponse<>(true, message, data);
}
public static <T> ApiResponse<T> error(String message) {
return new ApiResponse<>(false, message, null);
}
}
8 Controller
AuthController.java
package com.example.jwt.controller;
import com.example.jwt.dto.*;
import com.example.jwt.model.User;
import com.example.jwt.repository.UserRepository;
import com.example.jwt.security.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
import org.springframework.security.core.userdetails.UserDetailsService;
import javax.validation.Valid;
import java.util.HashSet;
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private UserRepository userRepository;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private JwtUtil jwtUtil;
// 登录
@PostMapping("/login")
public ResponseEntity<?> login(@Valid @RequestBody LoginRequest loginRequest) {
try {
// 认证
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
loginRequest.getUsername(),
loginRequest.getPassword()
)
);
// 加载用户信息
UserDetails userDetails = userDetailsService.loadUserByUsername(loginRequest.getUsername());
// 生成token
String token = jwtUtil.generateToken(userDetails);
return ResponseEntity.ok(ApiResponse.success("登录成功",
new LoginResponse(token, 3600L, loginRequest.getUsername())));
} catch (BadCredentialsException e) {
return ResponseEntity.badRequest().body(ApiResponse.error("用户名或密码错误"));
} catch (Exception e) {
return ResponseEntity.badRequest().body(ApiResponse.error("登录失败:" + e.getMessage()));
}
}
// 注册
@PostMapping("/register")
public ResponseEntity<?> register(@Valid @RequestBody RegisterRequest registerRequest) {
try {
// 检查用户是否存在
if (userRepository.existsByUsername(registerRequest.getUsername())) {
return ResponseEntity.badRequest().body(ApiResponse.error("用户名已存在"));
}
if (userRepository.existsByEmail(registerRequest.getEmail())) {
return ResponseEntity.badRequest().body(ApiResponse.error("邮箱已被注册"));
}
// 创建新用户
User user = new User();
user.setUsername(registerRequest.getUsername());
user.setEmail(registerRequest.getEmail());
user.setPassword(passwordEncoder.encode(registerRequest.getPassword()));
user.setRoles(new HashSet<>());
userRepository.save(user);
return ResponseEntity.ok(ApiResponse.success("注册成功", null));
} catch (Exception e) {
return ResponseEntity.badRequest().body(ApiResponse.error("注册失败:" + e.getMessage()));
}
}
// 刷新token
@PostMapping("/refresh")
public ResponseEntity<?> refreshToken(@RequestHeader("Authorization") String token) {
try {
String actualToken = token.replace("Bearer ", "");
String username = jwtUtil.extractUsername(actualToken);
if (username != null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
String newToken = jwtUtil.generateToken(userDetails);
return ResponseEntity.ok(ApiResponse.success("刷新成功",
new LoginResponse(newToken, 3600L, username)));
}
return ResponseEntity.badRequest().body(ApiResponse.error("无效的token"));
} catch (Exception e) {
return ResponseEntity.badRequest().body(ApiResponse.error("刷新失败:" + e.getMessage()));
}
}
}
UserController.java
package com.example.jwt.controller;
import com.example.jwt.dto.ApiResponse;
import com.example.jwt.model.User;
import com.example.jwt.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserRepository userRepository;
// 获取当前用户信息
@GetMapping("/me")
public ResponseEntity<?> getCurrentUser(@RequestAttribute("username") String username) {
User user = userRepository.findByUsername(username).orElse(null);
if (user != null) {
user.setPassword(null); // 不返回密码
return ResponseEntity.ok(ApiResponse.success(user));
}
return ResponseEntity.badRequest().body(ApiResponse.error("用户不存在"));
}
// 获取所有用户(需要ADMIN权限)
@GetMapping
public ResponseEntity<?> getAllUsers() {
List<User> users = userRepository.findAll();
// 隐藏密码
users.forEach(user -> user.setPassword(null));
return ResponseEntity.ok(ApiResponse.success(users));
}
// 获取指定用户(需要ADMIN权限)
@GetMapping("/{id}")
public ResponseEntity<?> getUserById(@PathVariable Long id) {
User user = userRepository.findById(id).orElse(null);
if (user != null) {
user.setPassword(null);
return ResponseEntity.ok(ApiResponse.success(user));
}
return ResponseEntity.badRequest().body(ApiResponse.error("用户不存在"));
}
}
9 启动类
JwtDemoApplication.java
package com.example.jwt;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@SpringBootApplication
public class JwtDemoApplication {
public static void main(String[] args) {
SpringApplication.run(JwtDemoApplication.class, args);
}
}
测试
1 初始化数据
创建测试用的角色和用户:
-- 插入角色 INSERT INTO roles (id, name, description) VALUES (1, 'ROLE_ADMIN', '管理员'); INSERT INTO roles (id, name, description) VALUES (2, 'ROLE_USER', '普通用户');
2 测试接口
注册用户
POST http://localhost:8080/api/auth/register
Content-Type: application/json
{
"username": "testuser",
"password": "123456",
"email": "test@example.com"
}
登录获取token
POST http://localhost:8080/api/auth/login
Content-Type: application/json
{
"username": "testuser",
"password": "123456"
}
访问受保护资源
GET http://localhost:8080/api/users/me Authorization: Bearer [token]
管理员接口
GET http://localhost:8080/api/users Authorization: Bearer [admin_token]
扩展功能
1 添加全局异常处理
package com.example.jwt.exception;
import com.example.jwt.dto.ApiResponse;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.HashMap;
import java.util.Map;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<?> handleValidationExceptions(MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getAllErrors().forEach((error) -> {
String fieldName = ((FieldError) error).getField();
String errorMessage = error.getDefaultMessage();
errors.put(fieldName, errorMessage);
});
return ResponseEntity.badRequest().body(ApiResponse.error("参数校验失败:" + errors));
}
@ExceptionHandler(AccessDeniedException.class)
public ResponseEntity<?> handleAccessDeniedException(AccessDeniedException ex) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(ApiResponse.error("没有权限访问"));
}
@ExceptionHandler(Exception.class)
public ResponseEntity<?> handleGenericException(Exception ex) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(ApiResponse.error("服务器内部错误:" + ex.getMessage()));
}
}
2 添加CORS配置
package com.example.jwt.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("*"); // 或指定域名
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
使用说明
- 配置数据库:修改application.yml中的数据库配置
- 创建数据库:执行
CREATE DATABASE jwt_demo; - 启动应用:运行
mvn spring-boot:run或直接运行启动类 - 测试接口:使用Postman或curl测试上述接口
这个案例包含了JWT认证的完整实现,包括:
- 用户注册和登录
- JWT令牌生成和验证
- Spring Security集成
- 角色权限控制
- 异常处理
- 参数校验
您可以根据实际需求进行调整和扩展。