【问题标题】:x509 validation fails before it can be capturedx509 验证在捕获之前失败
【发布时间】:2019-10-10 10:15:42
【问题描述】:

我有一个 Spring Boot 应用程序,它使用 x509 身份验证进一步验证用户是否符合数据库。当用户访问站点时,内部 Spring 代码调用 loadUserByUsername 方法,该方法反过来进行数据库调用。这一切都发生在控制器意识到发生任何事情之前。如果找不到用户,它会抛出 EntityNotFoundException 并在用户的浏览器上显示堆栈跟踪。

我正在使用 Spring Boot Starter。控制器具有捕获异常并返回“未授权”消息的代码,但这发生在很久以前。有没有其他人看到过这个,你有解决方法吗?

@Service
public class UserService implements UserDetailsService {
    public UserDetails loadUserByUsername(String dn) {
        ApprovedUser details = auService.getOne(dn);
        if (details ==  null){
            String message = "User not authorized: " + dn;
            throw new UsernameNotFoundException(message);
        }

        List<GrantedAuthority> authorities = new ArrayList<>();
        authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
        if (details.isAdminUser()){
            authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN_USER"));
        }
        return new AppUser(dn, "", authorities);
    }

【问题讨论】:

    标签: spring security x509


    【解决方案1】:

    通常,您会使用AuthenticationFailureHandler 来封装由AuthenticationException 触发的逻辑。 X509AuthenticationFilter 通常会调用PreAuthenticatedAuthenticationProvider 进行身份验证,这反过来又会从UserDetailsService 调用loadUserByUsername(...) 方法。 UserDetailsService 抛出的任何AuthenticationException 都会被过滤器捕获,并将控制权传递给注册的AuthenticationFailureHandler。这包括UsernameNotFoundException

    但是,如果您使用的是X509Configurer, (http.x509()),则无法直接在过滤器上设置处理程序。所以一旦抛出异常,X509AuthenticationFilter 就会捕获它,发现没有默认处理程序,然后简单地将请求传递给过滤器链中的下一个过滤器。

    解决此问题的一种方法是提供自定义X509AuthenticationFilter

    WebSecurityConfigurerAdapter:

    @Autowired
    private AuthenticationFailureHandler customFailureHandler;
    
    @Autowired
    private UserService customUserService;
    
    @Bean(name = BeanIds.AUTHENTICATION_MANAGER)
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    } 
    
    protected void configure(HttpSecurity http) throws Exception {
        ...
        http.x509().x509AuthenticationFilter(myX509Filter())
        .userDetailsService(customUserService)
        ...
    }
    
    private X509AuthenticationFilter myX509Filter() {
        X509AuthenticationFilter myCustomFilter = new X509AuthenticationFilter();
        myCustomFilter.setAuthenticationManager(authenticationManagerBean());
        ...
        myCustomFilter.setContinueFilterChainOnUnsuccessfulAuthentication(false);
        myCustomFilter.setAuthenticationFailureHandler(customFailureHandler);
        return myCustomFilter;
    }
    

    然后您可以编写自己的AuthenticationFailureHandler 实现并将其公开为一个bean。

    【讨论】:

      猜你喜欢
      • 2018-07-16
      • 1970-01-01
      • 1970-01-01
      • 2023-04-01
      • 2017-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-13
      相关资源
      最近更新 更多