Appearance
企业级实战案例
项目结构
text
com.example.demo
├── auth
│ ├── AuthController.java
│ ├── LoginRequest.java
│ ├── LoginResponse.java
│ └── RegisterRequest.java
├── security
│ ├── SecurityConfig.java
│ ├── JwtAuthenticationFilter.java
│ ├── JwtService.java
│ ├── RestAuthenticationEntryPoint.java
│ └── RestAccessDeniedHandler.java
├── service
│ └── CustomUserDetailsService.java
├── repository
└── domain注册接口
java
@RestController
@RequestMapping("/api/auth")
class AuthController {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
AuthController(UserRepository userRepository, PasswordEncoder passwordEncoder) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
}
@PostMapping("/register")
void register(@RequestBody RegisterRequest request) {
userRepository.save(new UserEntity(request.username(), passwordEncoder.encode(request.password())));
}
}java
public record RegisterRequest(String username, String password) {}登录接口
java
@PostMapping("/login")
LoginResponse login(@RequestBody LoginRequest request) {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(request.username(), request.password()));
String token = jwtService.generate(authentication.getName(), List.of("ROLE_USER"));
return new LoginResponse(token);
}java
public record LoginRequest(String username, String password) {}
public record LoginResponse(String accessToken) {}当前登录用户接口
java
@GetMapping("/me")
Map<String, Object> me(Authentication authentication) {
return Map.of(
"name", authentication.getName(),
"authorities", authentication.getAuthorities().stream()
.map(GrantedAuthority::getAuthority)
.toList());
}管理员接口
java
@PreAuthorize("hasRole('ADMIN')")
@DeleteMapping("/users/{id}")
void deleteUser(@PathVariable Long id) {
}企业项目里的常见拆分
- 登录注册接口独立在
auth模块。 - Token 解析和安全异常处理独立在
security模块。 - 用户查询逻辑落在
service和repository。 - 管理端、开放 API、内部接口建议用多条
SecurityFilterChain分开。
常见问题
- 注册时密码未编码,导致登录校验永远失败。
- JWT 过滤器插在
AuthorizationFilter后面,导致请求始终未认证。 permitAll范围写错,把敏感接口暴露出去。- Session 与 JWT 混用但未明确策略,出现状态不一致。
