我如何使用grails 1.3.2和插件spring-security-core 1来实现一个自定义的FilterSecurityInterceptor? [英] How do I implement a custom FilterSecurityInterceptor using grails 1.3.2 and the plugin spring-security-core 1?

查看:240
本文介绍了我如何使用grails 1.3.2和插件spring-security-core 1来实现一个自定义的FilterSecurityInterceptor?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个grails 1.3.2应用程序,并使用spring-security-core 1.0来实现安全性。由于这个问题范围之外的原因,除了开箱即用的拦截器,我还实现了一个自定义的FilterSecurityInterceptor。我已经开始使用博客文章关于这个主题,并试图调整它为Spring Security 3没有太大的成功。



松散地跟随博客(因为它是基于旧版本的Spring Security),我创建了以下类:
$ b $ ol
一个org.springframework.security.authentication。 AbstractAuthenticationToken子类保存我的凭证。
一个org.springframework.security.authentication.AuthenticationProvider子类,用于实现身份验证,并支持使用UserDetailsS​​ervice中的数据填充Authentication实例的方法。 >

  • org.springframework.security.web.access.intercept.FilterSecurityInterceptor子类实现doFilter和afterPropertiesSet方法。
  • Bean的一些配置和spring-security -C我的AbstractAuthenticationToken非常简单:

     类InterchangeAuthenticationToken扩展AbstractAuthenticationToken {
    字符串凭证
    整数名称
    整数主数

    字符串getCredentials(){//必要或我得到编译错误
    返回凭证
    }

    整数getPrincipal(){//必要或我得到编译错误
    返回主体


    $ / code $ / pre
    $ b $我的AuthenticationProvider非常简单: b
    $ b

      class InterchangeAuthenticationProvider实现org.springframework.security.authentication.AuthenticationProvider {

    认证认证(认证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。最后这会做一些有趣的事情:
    $ b $ pre $ class InterchangeFilterSecurityInterceptor extends FilterSecurityInterceptor implements InitializingBean {

    def authenticationManager
    def interchangeAuthenticationProvider $ b $ def def securityMetadataSource
    $ b void doFilter(HttpServletRequest请求,HttpServletResponse响应,FilterChain链){

    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在$ {myAuth}对象中成功验证$ {userId}

    //存储到SecurityContextHolder
    SecurityContextHolder.getContext() .setAuthentication(myAuth);


    chain.doFilter(request,response)

    $ b 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')


    $ b $ $ b

    然后做一些插件配置:

      grails.plugins.springsecurity.dao.hideUs erNotFoundExceptions = true //不设置这个会导致异常
    grails.plugins.springsecurity.providerNames = [
    'interchangeAuthenticationProvider',$ b $'daoAuthenticationProvider',$ b $'anonymousAuthenticationProvider',
    'rememberMeAuthenticationProvider'
    ]

    在Bootstrap.groovy中设置过滤顺序: p>

      def init = {servletContext  - > 
    //在过滤器安全拦截器后插入我们的自定义过滤器
    SpringSecurityUtils.clientRegisterFilter('interchangeFilterSecurityInterceptor',SecurityFilterPosition.SECURITY_CONTEXT_FILTER.order + 10)
    < snip />

    $ / code $ / pre

    当我点击一个URL的时候,我得到了下面这个例外: / p>

      2010-07-30 15:07:16,763 [http-8080-1]错误[/community-services].[default ]  -  Servlet.service()为servlet默认抛出异常
    java.lang.NullPointerException $ b $在org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:171)
    在org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:106)
    在org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
    在org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    在org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java: 112)
    在org.springframework.security.we b.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    在org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
    在org.springframework.security。 web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    处org.codehaus.groovy org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:187)
    。 grails.plugins.springsecurity.RequestHolderAuthenticationFilter.doFilter(RequestHolderAuthenticationFilter.java:40)维持在org.codehaus org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:355)

    。 groovy.grails.plugins.springsecurity.MutableLogoutFilter.doFilter(MutableLogoutFilter.java:79)
    在org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    。在组织。 SPRI ngframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
    在org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    。在组织。 springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:149)
    处org.springframework.web org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
    。 filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
    处org.apache.catalina.core.ApplicationFilterChain org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    。的doFilter(ApplicationFilterChain.java:206)
    处org.springframework.web.filter org.codehaus.groovy.grails.web.servlet.filter.GrailsReloadServletFilter.doFilterInternal(GrailsReloadServletFilter.java:104)
    。 OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    在org.apache.ca在org.codehaus.groovy.grails的
    org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    (ApplicationFilterChain.java:235)。 web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:67)
    处org.apache.catalina org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    。 core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    在org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    在org.codehaus.groovy.grails.web。 filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:66)
    在org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    在org.apache.catalina.core.ApplicationFilterChain。 internalDoFilter(ApplicationFilterChain.java:235)
    在org.apache.catalina.core.ApplicationFilterChain.do过滤器(ApplicationFilterChain.java:206)
    在org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
    在org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter。的java:在org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237 76)

    。在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)
    在org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    在org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    在org.apache .catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    在org.apache.catalina.valves.ErrorReportValve.in voke(ErrorReportValve.java:102)
    在org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    在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)
    在org.apache.tomcat.util.net.JIoEndpoint $ Worker.run(JIoEndpoint.java:454)$ b $在java.lang.Thread.run(Thread.java:637)

    那么我搞乱了什么,还是我做得太复杂了,我错过了一些简单的东西?

    解决方案

    最后,我实现了一个自定义过滤器,但不是FilterSecurityInterceptor。我在OOTB rememberMe过滤器后插入了我的过滤器。此外,我发现我的身份验证实施有点资源密集和缓慢,所以我让它设置rememberMe cookie成功身份验证。总体而言,这是一个痛苦的经历,所以我会试图在这里记录它。



    我的过滤器实现如下:

      import javax.servlet.FilterChain 
    import javax.servlet.http.HttpServletRequest
    import javax.servlet.http.HttpServletResponse
    import javax.servlet.ServletException
    import javax.servlet.ServletRequest
    import javax.servlet.ServletResponse
    import org.springframework.context.ApplicationEventPublisher
    import org.springframework.context。 ApplicationEventPublisherAware
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
    import org.springframework.security.core.Authentication
    import org.springframework.security.core.AuthenticationException
    import org。 springframework.security.core.context.SecurityContextHolder
    import org.springframework.web.filter.GenericFilterBean
    $ b $ class CustomRememberMeAuthenticationFilter extends Gene ricFilterBean实现了ApplicationEventPublisherAware {

    def authenticationManager
    def eventPublisher
    def customService
    def rememberMeServices
    def springSecurityService

    //确定我们已经指定了bean
    void afterPropertiesSet(){
    assert authenticationManager!= null,'authenticationManager must be specified'
    assert customService!= null,'customService must be specified'
    断言rememberMeServices!= null,'rememberMeServices必须指定'
    }

    void doFilter(ServletRequest req,ServletResponse res,FilterChain链)throws IOException,ServletException {
    HttpServletRequest请求=(HttpServletRequest)req
    HttpServletResponse response =(HttpServletResponse)res
    $ b if(SecurityContextHolder.getContext()。getAuthentication()== null){
    认证au ($ auth.getPrincipal(),auth.getCredentials())
    auth = customService.getUsernamePasswordAuthenticationToken(request)
    if(auth!= null){

    logger.debug(SecurityContextHolder填充为auth:'
    + SecurityContextHolder.getContext()。getAuthentication()+')
    onSuccessfulAuthentication(request,response,SecurityContextHolder.getContext ).getAuthentication())
    } else {
    logger.debug('customService没有从请求中返回认证信息')

    catch(AuthenticationException authenticationException){
    logger.warn(SecurityContextHolder未使用auth填充,如
    +springSecurityService拒绝customService返回的认证:
    + auth +',authenticationException)
    onUnsuccessfulAuthentication(request,response,auth)
    } catch(e){
    logger.warn(Unsuccessful authentication in customRememberMeAuthenticationFilter ,e)
    onUnsuccessfulAuthentication(request,response,auth)
    }
    } else {
    logger.debug(SecurityContextHolder没有填充auth,因为它已经包含:'
    + SecurityContextHolder.getContext()。getAuthentication()+')
    }
    chain.doFilter(request,response)
    }

    protected void onSuccessfulAuthentication(HttpServletRequest请求,HttpServletResponse响应,身份验证authResult){
    //设置rememberMe Cookie,但不能调用loginSuccess,因为它过滤掉请求
    //不设置rememberMe cookie这一块
    r eMemoryMessage.getLoginSuccess(request,response,authResult)
    }
    $ b protected void onUnsuccessfulAuthentication(HttpServletRequest请求,HttpServletResponse响应,AuthenticationException失败){
    //清除rememberMe cookie
    rememberMeServices.loginFail(request,response)
    }

    public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher){
    this.eventPublisher = eventPublisher
    }
    }

    希望其他人在实现自定义身份验证解决方案时能够找到有用的信息。我们发现在将我们的应用程序与我们的遗留系统集成在一起时,这对我们有效。


    I'm writing a grails 1.3.2 application and implementing security with spring-security-core 1.0. For reasons outside the scope of this question, I'm implementing a custom FilterSecurityInterceptor in addition to the out of the box interceptors. I've started with a blog entry on the topic and attempted to adjust it for Spring Security 3 without much success.

    Loosely following the blog (since it is based on an older version of Spring Security), I've created the following classes:

    1. A org.springframework.security.authentication.AbstractAuthenticationToken subclass to hold my credentials.
    2. A org.springframework.security.authentication.AuthenticationProvider subclass to implement the authenticate and supports methods for populating an Authentication instance with data from my UserDetailsService.
    3. A org.springframework.security.web.access.intercept.FilterSecurityInterceptor subclass to implement doFilter and afterPropertiesSet methods.
    4. Some configuration of beans and the spring-security-core plugin to recognize my AuthenticationProvider and insert my filter into the filter chain.

    My AbstractAuthenticationToken is pretty simple:

    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
     }
    }
    

    My AuthenticationProvider is pretty simple:

    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)
     }
    
    }
    

    I've implemented a trivial FilterSecurityInterceptor. Eventually this will do something interesting:

    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
     }
    }           
    

    Finally I configure some beans:

    beans = {
      interchangeAuthenticationProvider(com.bc.commerce.core.InterchangeAuthenticationProvider) {
      }
      interchangeFilterSecurityInterceptor(com.bc.commerce.core.InterchangeFilterSecurityInterceptor) {
        authenticationManager = ref('authenticationManager')
        interchangeAuthenticationProvider = ref('interchangeAuthenticationProvider')
        securityMetadataSource = ref('objectDefinitionSource')
      }
    }
    

    And do some configuration of the plugin:

    grails.plugins.springsecurity.dao.hideUserNotFoundExceptions = true //not setting this causes exception
    grails.plugins.springsecurity.providerNames = [
    'interchangeAuthenticationProvider',
    'daoAuthenticationProvider',
    'anonymousAuthenticationProvider',
    'rememberMeAuthenticationProvider'
    ]
    

    And set the filter order in 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 />
    }
    

    When I hit a URL, I get the following exception which stumps me:

    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)
    

    So where am I messing up, or did I make this too complex and I missed something simple?

    解决方案

    In the end, I implemented a custom filter, but not a FilterSecurityInterceptor. I inserted my filter after the OOTB rememberMe filter. Furthermore I found my authentication implementation to be somewhat resource-intensive and slow, so I made it set the rememberMe cookie on successful authentication. On the whole, this was a painful experience so I'll make an attempt to document it here.

    My filter implementation was as follows:

    import javax.servlet.FilterChain
    import javax.servlet.http.HttpServletRequest
    import javax.servlet.http.HttpServletResponse
    import javax.servlet.ServletException
    import javax.servlet.ServletRequest
    import javax.servlet.ServletResponse
    import org.springframework.context.ApplicationEventPublisher
    import org.springframework.context.ApplicationEventPublisherAware
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
    import org.springframework.security.core.Authentication
    import org.springframework.security.core.AuthenticationException
    import org.springframework.security.core.context.SecurityContextHolder
    import org.springframework.web.filter.GenericFilterBean
    
    class CustomRememberMeAuthenticationFilter extends GenericFilterBean implements ApplicationEventPublisherAware {
    
        def authenticationManager
        def eventPublisher
        def customService
        def rememberMeServices
        def springSecurityService
    
        //make certain that we've specified our beans
        void afterPropertiesSet() {
            assert authenticationManager != null, 'authenticationManager must be specified'
            assert customService != null, 'customService must be specified'
            assert rememberMeServices != null, 'rememberMeServices must be specified'
        }
    
        void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
            HttpServletRequest request = (HttpServletRequest) req
            HttpServletResponse response = (HttpServletResponse) res
    
            if (SecurityContextHolder.getContext().getAuthentication() == null) {           
                Authentication auth
                try {
                    auth = customService.getUsernamePasswordAuthenticationToken(request)
                    if (auth != null) {
                        springSecurityService.reauthenticate(auth.getPrincipal(), auth.getCredentials())
                        logger.debug("SecurityContextHolder populated with auth: '"
                            + SecurityContextHolder.getContext().getAuthentication() + "'")
                        onSuccessfulAuthentication(request, response, SecurityContextHolder.getContext().getAuthentication())
                    } else {
                        logger.debug('customService did not return an authentication from the request')
                    }
                } catch (AuthenticationException authenticationException) {
                    logger.warn("SecurityContextHolder not populated with auth, as "
                        + "springSecurityService rejected Authentication returned by customService: '"
                        + auth + "'", authenticationException)
                    onUnsuccessfulAuthentication(request, response, auth)
                } catch(e) {
                    logger.warn("Unsuccessful authentication in customRememberMeAuthenticationFilter", e)
                    onUnsuccessfulAuthentication(request, response, auth)
                }
            } else {
                logger.debug("SecurityContextHolder not populated with auth, as it already contained: '"
                    + SecurityContextHolder.getContext().getAuthentication() + "'")
            }
            chain.doFilter(request, response)
        }
    
        protected void onSuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authResult) {
            //sets the rememberMe cookie, but cannot call "loginSuccess" because that filters out requests
            //that don't set the rememberMe cookie, like this one
            rememberMeServices.onLoginSuccess(request, response, authResult)
        }
    
        protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) {
            //clear the rememberMe cookie
            rememberMeServices.loginFail(request, response)
        }
    
        public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) {
            this.eventPublisher = eventPublisher
        }
    }
    

    Hopefully others find this helpful when implementing their custom authentication solutions. We found this worked for us when integrating our application with our legacy system.

    这篇关于我如何使用grails 1.3.2和插件spring-security-core 1来实现一个自定义的FilterSecurityInterceptor?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆