Abh*_*kar 1 spring-mvc spring-security spring-java-config
我正在尝试使用自定义进行URL授权AccessDecisionVoter.我没有收到任何错误,调试显示我的选民在启动时被选中.但是,在运行时,vote不会调用该方法,从而允许每个经过身份验证的用户完全访问.
请注意,我不需要方法安全性.我也没有使用XML配置.这排除了互联网上有关此主题的每个例子.
@Configuration
@EnableWebSecurity
@EnableWebMvc
@ComponentScan
@Order(-10)
public class HttpSecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${trusted_ports}")
private List<Integer> 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<PreAuthenticatedAuthenticationToken> 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;
}
Run Code Online (Sandbox Code Playgroud)
背景:
经过几个小时的调试,我发现了问题的根本原因,这是非常深刻的.其中一部分原因是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<DispatcherType> getDispatcherTypes() {
return (isAsyncSupported() ? EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.ASYNC)
: EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE));
}
Run Code Online (Sandbox Code Playgroud)如果您DispatcherType.FORWARD从调度程序类型集中取出,则注册的过滤器不会为这种请求启动.
authFilter在我的问题,从延伸出UsernamePasswordAuthenticationFilter并有一个AuthenticationSuccessHandler它转发请求到目标URL验证成功后.默认的Spring实现使用一个SavedRequestAwareAuthenticationSuccessHandler重定向到网页的方法,这在REST应用程序的上下文中是不需要的.FilterSecurityInterceptor在成功验证后未调用,而后者又跳过授权链,导致我的原始帖子出现问题.固定:
AuthenticationSuccessHandler.只是让请求采取它的自然过程.自定义选民有一个vote方法,如下所示:
public int vote(Authentication authentication, FilterInvocation fi,
Collection<ConfigAttribute> attributes) {
}
Run Code Online (Sandbox Code Playgroud)将attributes在我的情况一样,在我原来的职位所示,是字符串表达式fullyAuthenticated.我没有使用它进行授权,因为我已经知道用户已通过身份验证流程中的各种过滤器进行了身份验证.
我希望这可以作为所有那些因Spring Security Java配置缺乏文档而遭受痛苦的人的文档.
| 归档时间: |
|
| 查看次数: |
2430 次 |
| 最近记录: |