当前位置:  开发笔记 > 编程语言 > 正文

Spring Security:为什么我的自定义AccessDecisionVoter没有被调用

如何解决《SpringSecurity:为什么我的自定义AccessDecisionVoter没有被调用》经验,为你挑选了1个好方法。

我正在尝试使用自定义进行URL授权AccessDecisionVoter.我没有收到任何错误,调试显示我的选民在启动时被选中.但是,在运行时,vote不会调用该方法,从而允许每个经过身份验证的用户完全访问.

请注意,我不需要方法安全性.我也没有使用XML配置.这排除了互联网上有关此主题的每个例子.

@Configuration
@EnableWebSecurity
@EnableWebMvc
@ComponentScan
@Order(-10)
public class HttpSecurityConfig extends WebSecurityConfigurerAdapter {
    @Value("${trusted_ports}")
    private List trustedPorts;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private ServiceIdAwareVoter serviceIdAwareVoter;

    RequestMatcher requestMatcher = new OrRequestMatcher(
        // @formatter:off
        new AntPathRequestMatcher("/**", GET.name()),
        new AntPathRequestMatcher("/**", POST.name()), 
        new AntPathRequestMatcher("/**", DELETE.name()),
        new AntPathRequestMatcher("/**", PATCH.name()), 
        new AntPathRequestMatcher("/**", PUT.name())
        // @formatter:on
    );

    @Override
    protected UserDetailsService userDetailsService() {
        return userDetailsService;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(preAuthProvider());
        auth.authenticationProvider(authProvider());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http.
            httpBasic().and().
            authorizeRequests().anyRequest().fullyAuthenticated().
            accessDecisionManager(accessDecisionManager()).and().
            csrf().disable().
            logout().disable().
            exceptionHandling().and().
            sessionManagement().sessionCreationPolicy(STATELESS).and().
            anonymous().disable().
            addFilterAfter(preAuthFilter(), X509AuthenticationFilter.class).
            addFilter(authFilter());
        // @formatter:on
    }

    AccessDecisionManager accessDecisionManager() {
        return new UnanimousBased(ImmutableList.of(serviceIdAwareVoter));
    }

    Filter preAuthFilter() throws Exception {
        PreAuthenticationFilter preAuthFilter = new PreAuthenticationFilter(trustedPorts);

        preAuthFilter.setAuthenticationManager(super.authenticationManager());

        return preAuthFilter;
    }

    PreAuthenticatedAuthenticationProvider preAuthProvider() {
        PreAuthenticatedAuthenticationProvider preAuthProvider = new PreAuthenticatedAuthenticationProvider();
        UserDetailsByNameServiceWrapper userDetailsServiceWrapper = new UserDetailsByNameServiceWrapper<>();

        userDetailsServiceWrapper.setUserDetailsService(userDetailsService());

        preAuthProvider.setPreAuthenticatedUserDetailsService(userDetailsServiceWrapper);

        return preAuthProvider;
    }

    Filter authFilter() throws Exception {
        AppIdAppKeyAuthenticationFilter authFilter = new AppIdAppKeyAuthenticationFilter(requestMatcher);
        authFilter.setAuthenticationFailureHandler(new ExceptionStoringAuthenticationFailureHandler());
        authFilter.setAuthenticationSuccessHandler(new UrlForwardingAuthenticationSuccessHandler());

        authFilter.setAuthenticationManager(authenticationManagerBean());

        return authFilter;
    }

    AuthenticationProvider authProvider() {
        AppIdAppKeyAuthenticationProvider authProvider = new AppIdAppKeyAuthenticationProvider();
        authProvider.setUserDetailsService(userDetailsService());

        return authProvider;
    }

Abhijit Sark.. 6

背景:

经过几个小时的调试,我发现了问题的根本原因,这是非常深刻的.其中一部分原因是Spring Security Java配置文档很少(为此我打开了JIRA票证).他们以及大多数在线示例都是从XML配置中复制粘贴的,而自2010年以来世界已经停止使用Spring XML配置.另一部分原因是REST服务安全性是Spring Security设计中的事后想法,没有一流的支持来保护没有登录页面,错误页面和通常的视图层的应用程序.最后但并非最不重要的是,我的应用程序中存在多个(错误)配置,这些配置全部汇集在一起​​,创造了令人难以置信的复杂风暴.

技术背景:

使用authorizeRequests()配置ExpressionUrlAuthorizationConfigurer最终设置a UnanimousBased AccessDecisionManager与a WebExpressionVoter.这AccessDecisionManager是从FilterSecurityInterceptor身份验证成功的情况下调用的(显然,如果用户首先未通过身份验证,则授权没有意义).

问题:

在我的AbstractAnnotationConfigDispatcherServletInitializer子类中,它基本上是Java版本web.xml,我配置过滤器不拦截前向请求.我不打算在这里讨论原因.对于感兴趣的人,这是一个如何完成它的例子:

private Dynamic registerCorsFilter(ServletContext ctx) {
    Dynamic registration = ctx.addFilter("CorsFilter", CorsFilter.class);

    registration.addMappingForUrlPatterns(getDispatcherTypes(), false, "/*");    
    return registration;
}

private EnumSet getDispatcherTypes() {
    return (isAsyncSupported() ? EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.ASYNC)
  : EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE));
}

如果您DispatcherType.FORWARD从调度程序类型集中取出,则注册的过滤器不会为这种请求启动.

authFilter在我的问题,从延伸出UsernamePasswordAuthenticationFilter并有一个AuthenticationSuccessHandler它转发请求到目标URL验证成功后.默认的Spring实现使用一个SavedRequestAwareAuthenticationSuccessHandler重定向到网页的方法,这在REST应用程序的上下文中是不需要的.

由于上述两个原因,FilterSecurityInterceptor在成功验证后未调用,而后者又跳过授权链,导致我的原始帖子出现问题.

固定:

从Web应用初始化器中删除自定义调度程序配置.

不要前进或重定向AuthenticationSuccessHandler.只是让请求采取它的自然过程.

自定义选民有一个vote方法,如下所示:

public int vote(Authentication authentication, FilterInvocation fi,
        Collection attributes) {
}

attributes在我的情况一样,在我原来的职位所示,是字符串表达式fullyAuthenticated.我没有使用它进行授权,因为我已经知道用户已通过身份验证流程中的各种过滤器进行了身份验证.

我希望这可以作为所有那些因Spring Security Java配置缺乏文档而遭受痛苦的人的文档.



1> Abhijit Sark..:

背景:

经过几个小时的调试,我发现了问题的根本原因,这是非常深刻的.其中一部分原因是Spring Security Java配置文档很少(为此我打开了JIRA票证).他们以及大多数在线示例都是从XML配置中复制粘贴的,而自2010年以来世界已经停止使用Spring XML配置.另一部分原因是REST服务安全性是Spring Security设计中的事后想法,没有一流的支持来保护没有登录页面,错误页面和通常的视图层的应用程序.最后但并非最不重要的是,我的应用程序中存在多个(错误)配置,这些配置全部汇集在一起​​,创造了令人难以置信的复杂风暴.

技术背景:

使用authorizeRequests()配置ExpressionUrlAuthorizationConfigurer最终设置a UnanimousBased AccessDecisionManager与a WebExpressionVoter.这AccessDecisionManager是从FilterSecurityInterceptor身份验证成功的情况下调用的(显然,如果用户首先未通过身份验证,则授权没有意义).

问题:

在我的AbstractAnnotationConfigDispatcherServletInitializer子类中,它基本上是Java版本web.xml,我配置过滤器不拦截前向请求.我不打算在这里讨论原因.对于感兴趣的人,这是一个如何完成它的例子:

private Dynamic registerCorsFilter(ServletContext ctx) {
    Dynamic registration = ctx.addFilter("CorsFilter", CorsFilter.class);

    registration.addMappingForUrlPatterns(getDispatcherTypes(), false, "/*");    
    return registration;
}

private EnumSet getDispatcherTypes() {
    return (isAsyncSupported() ? EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.ASYNC)
  : EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE));
}

如果您DispatcherType.FORWARD从调度程序类型集中取出,则注册的过滤器不会为这种请求启动.

authFilter在我的问题,从延伸出UsernamePasswordAuthenticationFilter并有一个AuthenticationSuccessHandler它转发请求到目标URL验证成功后.默认的Spring实现使用一个SavedRequestAwareAuthenticationSuccessHandler重定向到网页的方法,这在REST应用程序的上下文中是不需要的.

由于上述两个原因,FilterSecurityInterceptor在成功验证后未调用,而后者又跳过授权链,导致我的原始帖子出现问题.

固定:

从Web应用初始化器中删除自定义调度程序配置.

不要前进或重定向AuthenticationSuccessHandler.只是让请求采取它的自然过程.

自定义选民有一个vote方法,如下所示:

public int vote(Authentication authentication, FilterInvocation fi,
        Collection attributes) {
}

attributes在我的情况一样,在我原来的职位所示,是字符串表达式fullyAuthenticated.我没有使用它进行授权,因为我已经知道用户已通过身份验证流程中的各种过滤器进行了身份验证.

我希望这可以作为所有那些因Spring Security Java配置缺乏文档而遭受痛苦的人的文档.

推荐阅读
低调pasta_730
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有