UsernamePasswordAuthenticationFilter,使用自定義 Controller 處理登錄邏輯,認證成功後手動構建 Authentication 註入 SecurityContext,複用後續授權機制。@PostMapping("/login")
public String login(@RequestParam String username, @RequestParam String password, HttpSession session) {
// 1. 調用 UserDetailsService 加載用戶
// 2. 密碼驗證(PasswordEncoder.matches)
// 3. 構建 Authentication
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(userDetails, null, authorities);
// 4. 註入 SecurityContext
SecurityContextHolder.getContext().setAuthentication(auth);
// 5. 可選:session 固化保護
session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());
return "redirect:/home";
}
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login", "/css/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin() // 保留表單登錄入口但不使用默認處理
.loginPage("/login")
.loginProcessingUrl("/login") // 自定義 Controller 映射同一 URL
.successHandler((req, res, auth) -> { /* 可選 */ })
.and()
.logout().permitAll();
}
}
formLogin().loginProcessingUrl() 映射同一路徑,Spring Security 仍會攔截該請求,但委托給 Controller 處理;Controller 手動構建 Authentication 後,後續 FilterSecurityInterceptor 等授權過濾器正常工作。通過「自定義 Controller + 手動註入 Authentication」模式,既保留了 Spring Security 強大的授權體系(@PreAuthorize、方法級權限、ACL),又獲得了登錄頁面、驗證邏輯、多因子認證的完全控制權。