我正在编写一个 grails 1.3.2 应用程序并使用 spring-security-core 1.0 实现安全性。由于此问题范围之外的原因,除了开箱即用的拦截器之外,我还实现了一个自定义 FilterSecurityInterceptor 。我从一篇关于该主题的博客文章开始,并尝试针对 Spring Security 3 对其进行调整,但没有取得多大成功。
松散地关注博客(因为它基于旧版本的 Spring Security),我创建了以下类:
- 一个 org.springframework.security.authentication.AbstractAuthenticationToken 子类来保存我的凭据。
- 一个 org.springframework.security.authentication.AuthenticationProvider 子类,用于实现身份验证并支持使用来自我的 UserDetailsService 的数据填充身份验证实例的方法。
- 一个 org.springframework.security.web.access.intercept.FilterSecurityInterceptor 子类来实现 doFilter 和 afterPropertiesSet 方法。
- bean 和 spring-security-core 插件的一些配置,用于识别我的 AuthenticationProvider 并将我的过滤器插入过滤器链。
我的 AbstractAuthenticationToken 非常简单:
class InterchangeAuthenticationToken extends AbstractAuthenticationToken {
String credentials
Integer name
Integer principal
String getCredentials() { //necessary or I get compilation error
return credentials
}
Integer getPrincipal() { //necessary or I get compilation error
return principal
}
}
我的 AuthenticationProvider 非常简单:
class InterchangeAuthenticationProvider implements org.springframework.security.authentication.AuthenticationProvider {
Authentication authenticate(Authentication customAuth) {
def authUser = AuthUser.get(customAuth.principal)
if (authUser) {
customAuth.setAuthorities(authUser.getAuthorities())
customAuth.setAuthenticated(true)
return customAuth
} else {
return null
}
}
boolean supports(Class authentication) {
return InterchangeAuthenticationToken.class.isAssignableFrom(authentication)
}
}
我已经实现了一个简单的 FilterSecurityInterceptor。最终这会做一些有趣的事情:
class InterchangeFilterSecurityInterceptor extends FilterSecurityInterceptor implements InitializingBean {
def authenticationManager
def interchangeAuthenticationProvider
def securityMetadataSource
void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) {
if (SecurityContextHolder.getContext().getAuthentication() == null) {
def myAuth = new InterchangeAuthenticationToken()
myAuth.setName(1680892)
myAuth.setCredentials('SDYLWUYa:nobody::27858cff')
myAuth.setPrincipal(1680892)
myAuth = authenticationManager.authenticate(myAuth);
if (myAuth) {
println "Successfully Authenticated ${userId} in object ${myAuth}"
// Store to SecurityContextHolder
SecurityContextHolder.getContext().setAuthentication(myAuth);
}
}
chain.doFilter(request, response)
}
void afterPropertiesSet() {
def providers = authenticationManager.providers
providers.add(interchangeAuthenticationProvider)
authenticationManager.providers = providers
}
}
最后我配置了一些bean:
beans = {
interchangeAuthenticationProvider(com.bc.commerce.core.InterchangeAuthenticationProvider) {
}
interchangeFilterSecurityInterceptor(com.bc.commerce.core.InterchangeFilterSecurityInterceptor) {
authenticationManager = ref('authenticationManager')
interchangeAuthenticationProvider = ref('interchangeAuthenticationProvider')
securityMetadataSource = ref('objectDefinitionSource')
}
}
并对插件进行一些配置:
grails.plugins.springsecurity.dao.hideUserNotFoundExceptions = true //not setting this causes exception
grails.plugins.springsecurity.providerNames = [
'interchangeAuthenticationProvider',
'daoAuthenticationProvider',
'anonymousAuthenticationProvider',
'rememberMeAuthenticationProvider'
]
并在 Bootstrap.groovy 中设置过滤顺序:
def init = {servletContext ->
//insert our custom filter just after the filter security interceptor
SpringSecurityUtils.clientRegisterFilter('interchangeFilterSecurityInterceptor', SecurityFilterPosition.SECURITY_CONTEXT_FILTER.order + 10)
<snip />
}
当我点击一个 URL 时,我得到以下异常,这让我很困惑:
2010-07-30 15:07:16,763 [http-8080-1] ERROR [/community-services].[default] - Servlet.service() for servlet default threw exception
java.lang.NullPointerException
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:171)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:106)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:112)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:187)
at org.codehaus.groovy.grails.plugins.springsecurity.RequestHolderAuthenticationFilter.doFilter(RequestHolderAuthenticationFilter.java:40)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.codehaus.groovy.grails.plugins.springsecurity.MutableLogoutFilter.doFilter(MutableLogoutFilter.java:79)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:149)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.codehaus.groovy.grails.web.servlet.filter.GrailsReloadServletFilter.doFilterInternal(GrailsReloadServletFilter.java:104)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:67)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.codehaus.groovy.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:66)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
at java.lang.Thread.run(Thread.java:637)
那么我在哪里搞砸了,还是我把它弄得太复杂了,我错过了一些简单的东西?