基于Spring Boot的用户身份验证与授权方案
在现代Web应用程序中,用户身份验证和授权是确保系统安全的关键部分。本文将探讨如何使用Spring Boot实现一个安全、高效的用户身份验证和授权系统。
功能需求
- 用户可以注册、登录,并获取访问令牌(JWT)。
- 只有经过身份验证的用户才能访问受保护的API。
- 不同角色的用户具有不同的访问权限(如管理员和普通用户)。
- 令牌过期机制及刷新功能。
技术选型
- Spring Boot:简化Java Web应用开发。
- Spring Security:提供身份验证和授权功能。
- JWT(JSON Web Token):用于无状态身份验证。
- Spring Data JPA + MySQL:存储用户信息。
方案设计
1. 数据库设计
定义用户表(User)和角色表(Role),用户与角色是多对多关系。
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "user_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id")
)
private Set<Role> roles;
}
2. 用户注册与密码加密
使用Spring Security的BCryptPasswordEncoder进行密码加密存储。
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private PasswordEncoder passwordEncoder;
public User registerUser(String username, String password) {
User user = new User();
user.setUsername(username);
user.setPassword(passwordEncoder.encode(password));
return userRepository.save(user);
}
}
3. JWT 令牌生成与解析
使用jjwt库生成和验证JWT令牌。
@Component
public class JwtUtil {
private String secretKey = "mySecretKey";
public String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60))
.signWith(SignatureAlgorithm.HS256, secretKey)
.compact();
}
public String extractUsername(String token) {
return Jwts.parser()
.setSigningKey(secretKey)
.parseClaimsJws(token)
.getBody()
.getSubject();
}
}
4. Spring Security 配置
配置Spring Security,使其支持JWT身份验证。
@EnableWebSecurity
public class SecurityConfig {
@Autowired
private JwtFilter jwtFilter;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeHttpRequests(auth -> auth
.requestMatchers("/auth/login", "/auth/register").permitAll()
.anyRequest().authenticated()
)
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
5. 用户登录接口
用户登录后返回JWT令牌。
@RestController
@RequestMapping("/auth")
public class AuthController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtUtil jwtUtil;
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword())
);
String token = jwtUtil.generateToken(request.getUsername());
return ResponseEntity.ok(new AuthResponse(token));
}
}
总结
本文介绍了如何使用Spring Boot、Spring Security和JWT实现用户身份验证与授权。通过JWT令牌机制,我们可以实现无状态的安全认证,提高系统的可扩展性和安全性。