You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Security中AuthenticationManager的可用扩展点有哪些?

推荐的3种无侵入扩展方案,完全保留原生认证流程

方案1:直接在控制器层处理(最简单,适配你当前的场景)

你本身已经在控制器中拿到了HttpServletRequest对象,也能直接提取IP,只需要在authenticationManager.authenticate执行成功(无异常抛出)之后,直接执行IP记录逻辑即可:

@RequestMapping(value = "login", method = RequestMethod.POST)
public void loginUser(@Valid @RequestBody LoginUserRequest request, HttpServletRequest httpServletRequest) {
    Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(request.getEmail(), request.getPassword()));
    SecurityContextHolder.getContext().setAuthentication(authentication);
    // 直接在这里追加自定义逻辑,只有认证成功才会执行到这一步
    String clientIp = getClientIp(httpServletRequest); // 自行实现客户端IP提取逻辑
    userRepository.addIp(request.getEmail(), clientIp);
}

该方案没有任何侵入性,不需要修改任何Spring Security原生配置,100%复用现有认证流程。

方案2:监听认证成功事件(适合全局统一处理认证成功逻辑的场景)

Spring Security在认证成功后会自动发布AuthenticationSuccessEvent事件,你只需要实现一个事件监听器,即可全局捕获所有认证成功的请求:

  1. 首先在构造认证Token时把IP信息塞到Token的details属性中:
// 控制器中修改逻辑
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(request.getEmail(), request.getPassword());
authToken.setDetails(getClientIp(httpServletRequest)); // 把IP存入details字段
Authentication authentication = authenticationManager.authenticate(authToken);
  1. 编写事件监听器:
@Component
public class AuthenticationSuccessListener implements ApplicationListener<AuthenticationSuccessEvent> {

    private final UserRepository userRepository;

    @Autowired
    public AuthenticationSuccessListener(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public void onApplicationEvent(AuthenticationSuccessEvent event) {
        Authentication auth = event.getAuthentication();
        String email = auth.getName();
        String ip = (String) auth.getDetails();
        userRepository.addIp(email, ip);
    }
}

该方案适合存在多个认证入口的场景,所有认证成功的请求都会统一执行自定义逻辑,不需要每个入口单独加代码。

方案3:自定义AuthenticationProvider(适合需要在认证流程中插入逻辑的场景)

如果你需要在认证流程中间(比如密码校验通过后、返回认证对象前)插入逻辑,可以继承原生的DaoAuthenticationProvider,复用它所有的认证逻辑,仅追加自己的扩展:

public class CustomAuthenticationProvider extends DaoAuthenticationProvider {

    private final UserRepository userRepository;

    public CustomAuthenticationProvider(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder, UserRepository userRepository) {
        setUserDetailsService(userDetailsService);
        setPasswordEncoder(passwordEncoder);
        this.userRepository = userRepository;
    }

    @Override
    protected Authentication createSuccessAuthentication(Object principal, Authentication authentication, UserDetails user) {
        // 调用父类方法生成原生认证对象,保留所有原生校验逻辑
        Authentication successAuth = super.createSuccessAuthentication(principal, authentication, user);
        // 插入自定义逻辑
        String ip = (String) authentication.getDetails();
        userRepository.addIp(user.getUsername(), ip);
        return successAuth;
    }
}

然后在你的Security配置类中替换默认Provider即可:

@Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
    authenticationManagerBuilder.authenticationProvider(
        new CustomAuthenticationProvider(userDetailsService, passwordEncoder, userRepository)
    );
}

该方案完全保留Spring Security原生的认证校验逻辑,仅在认证成功的节点插入自定义操作,适合需要深度定制认证流程的场景。


内容的提问来源于stack exchange,提问作者Johnyb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 03:21:02