使用 Spring Security 3.2.4 for Jersey 2.9 REST 服务的全局方法安全性的正确配置是啥?
Posted
技术标签:
【中文标题】使用 Spring Security 3.2.4 for Jersey 2.9 REST 服务的全局方法安全性的正确配置是啥?【英文标题】:What are the right configurations for global method security with Spring Security 3.2.4 for Jersey 2.9 REST services?使用 Spring Security 3.2.4 for Jersey 2.9 REST 服务的全局方法安全性的正确配置是什么? 【发布时间】:2014-07-29 06:05:02 【问题描述】:我正在尝试将我的 Jersey REST 服务配置为使用 Spring 提供的全局方法安全性来保护。我想我在整个画面中遗漏了一些东西。这是我的代码片段:
我的安全配置类(我试图纯粹在 java 代码中执行此操作,问题之一是大多数示例都使用 .xml 配置):
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class GlobalMethodSecurityConfig extends WebSecurityConfigurerAdapter
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception
auth.inMemoryAuthentication().withUser("user").password("password")
.roles("USER");
@Override
protected void configure(HttpSecurity http) throws Exception
http.authorizeRequests().anyRequest().permitAll();
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception
return super.authenticationManagerBean();
网络安全通过以下方式初始化:
public class WebSecurityInitializer extends
AbstractSecurityWebApplicationInitializer
(这其实和在web.xml中添加spring过滤器是一样的)
带有注释@PreAuthorized("permitAll")
的方法被正确打开。但是当我打开一个映射到带有@PreAuthorized("hasRole('ROLE_USER')")
注释的方法的 URL 时,我得到了这个异常:
java.lang.IllegalStateException: Cannot create a session after the response has been committed
org.apache.catalina.connector.Request.doGetSession(Request.java:2934)
org.apache.catalina.connector.Request.getSession(Request.java:2310)
org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:897)
org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:909)
javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:238)
javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:238)
javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:238)
org.springframework.security.web.savedrequest.HttpSessionRequestCache.saveRequest(HttpSessionRequestCache.java:40)
org.springframework.security.web.access.ExceptionTranslationFilter.sendStartAuthentication(ExceptionTranslationFilter.java:184)
org.springframework.security.web.access.ExceptionTranslationFilter.handleSpringSecurityException(ExceptionTranslationFilter.java:168)
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:131)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:85)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
【问题讨论】:
此异常可能是症状,而不是原因。提交的请求意味着某些内容已经发送到浏览器(客户端)。你能用萤火虫检查发送的内容吗? 【参考方案1】:您收到异常是因为 spring security 的 @PreAuthorized("hasRole('ROLE_USER')") 注释中的 "hasRole('ROLE_USER')" 是由 SecurityExpressionRoot 实现的表达式。它默认返回false。 您可能必须为 SecurityExpressionRoot 添加自定义实现并覆盖“hasRole”方法。更多详情请参考:http://docs.spring.io/spring-security/site/docs/3.0.x/reference/el-access.html 我希望这会有所帮助!
【讨论】:
【参考方案2】:我也没有运气扩展AbstractSecurityWebApplicationInitializer
,尽管以下似乎对我有用:
public class WebApplicationConfiguration extends AbstractAnnotationConfigDispatcherServletInitializer
@Override
public void onStartup(ServletContext servletContext) throws ServletException
super.onStartup(servletContext);
servletContext.addFilter("springSecurityFilterChain", DelegatingFilterProxy.class)
.addMappingForUrlPatterns(EnumSet.<DispatcherType>of(DispatcherType.REQUEST, DispatcherType.ERROR, DispatcherType.ASYNC), false, "/*");
@Override
protected Class<?>[] getRootConfigClasses()
return new Class<?>[]
GlobalMethodSecurityConfig.class,
// other java config classes come here
;
@Override
protected Class<?>[] getServletConfigClasses()
return null;
@Override
protected String[] getServletMappings()
return null;
【讨论】:
以上是关于使用 Spring Security 3.2.4 for Jersey 2.9 REST 服务的全局方法安全性的正确配置是啥?的主要内容,如果未能解决你的问题,请参考以下文章
添加 Spring Security 插件 3.1.1 后,Grails 3.2.4 应用程序不会加载
Spring Security 应用程序中的 Sitemesh 未装饰自定义错误页面
Spring Framework,Spring Security - 可以在没有 Spring Framework 的情况下使用 Spring Security?