【问题标题】:How can I use a custom configured RememberMeAuthenticationFilter in spring security?如何在 Spring Security 中使用自定义配置的 RememberMeAuthenticationFilter?
【发布时间】:2016-02-10 11:28:28
【问题描述】:

我想在 spring security (3.1.0) 中使用稍微定制的记忆功能。

我这样声明rememberme标签:

<security:remember-me key="JNJRMBM" user-service-ref="gymUserDetailService" />

由于我有自己的 rememberme 服务,我需要将其注入到我这样定义的 RememberMeAuthenticationFilter 中:

<bean id="rememberMeFilter" class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
    <property name="rememberMeServices" ref="gymRememberMeService"/>
    <property name="authenticationManager" ref="authenticationManager" />
</bean>

我在 web.xml 中以标准方式集成了 Spring Security:

<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>

一切正常,除了 RememberMeAuthenticationFilter 使用标准的 RememberMeService,所以我认为我定义的 RememberMeAuthenticationFilter 没有被使用。

如何确保我的过滤器定义正在被使用? 我需要创建自定义过滤器链吗? 如果是这样,我如何查看我当前的“隐式”过滤器链并确保我使用相同的过滤器链,除了我的 RememberMeAuthenticationFilter 而不是默认的过滤器链?

感谢您的任何建议和/或指点!

这里是完整的 spring-security.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-3.1.xsd">

<security:http pattern="/_ui/**" security="none" />
<!-- Default security config -->
<security:http disable-url-rewriting="true">
    <security:anonymous username="anonymous" granted-authority="ROLE_ANONYMOUS" />

    <!-- session stealing is prevented by using secure GUID cookie -->
    <security:session-management session-fixation-protection="none" />

    <!-- SSL / AUTHENTICATED pages -->
    <security:intercept-url pattern="/my-account*" access="ROLE_CUSTOMERGROUP" requires-channel="https" />
    <security:intercept-url pattern="/my-account/**" access="ROLE_CUSTOMERGROUP" requires-channel="https" />

    <!-- SSL / ANONYMOUS pages Login pages need to be SSL, but occur before authentication -->
    <security:intercept-url pattern="/login" requires-channel="https"  />
    <security:intercept-url pattern="/login/**" requires-channel="https" />
    <security:intercept-url pattern="/register" requires-channel="https" />
    <security:intercept-url pattern="/register/**" requires-channel="https" />
    <security:intercept-url pattern="/j_spring_security_check" requires-channel="https" />
    <security:intercept-url pattern="/logout" requires-channel="https" />

    <!-- MiniCart and CartPopup can occur on either secure or insecure pages -->
    <security:intercept-url pattern="/cart/rollover/*" requires-channel="any" />
    <security:intercept-url pattern="/cart/miniCart/*" requires-channel="any" />
    <security:intercept-url pattern="/cart/show" requires-channel="any" />
    <security:intercept-url pattern="/cart/lightboxmybag" requires-channel="any" />
    <security:intercept-url pattern="/cart/remove/*" requires-channel="any" />
    <security:intercept-url pattern="/cart/update/*" requires-channel="any" />
    <security:intercept-url pattern="/cart/getProductSizes/**" requires-channel="any" />
    <security:intercept-url pattern="/cart/getShippingMethods" requires-channel="any" />
    <security:intercept-url pattern="/cart/setShippingMethod" requires-channel="any" />     
    <security:intercept-url pattern="/cart/applyVoucherDiscount" requires-channel="any" />
    <security:intercept-url pattern="/cart/removeVoucherDiscount" requires-channel="any" />

    <security:intercept-url pattern="/checkout/**" requires-channel="https" />

    <!-- product suggest  -->
    <security:intercept-url pattern="/suggest*" requires-channel="any" />

    <!-- cybersource response  -->
    <security:intercept-url pattern="/cybersource/response" requires-channel="any" />
    <security:intercept-url pattern="/cybersource/csResponse" requires-channel="http" />

    <!--  regions -->
    <security:intercept-url pattern="/regions*" requires-channel="any" />
    <security:intercept-url pattern="/regions/*" requires-channel="any" />

    <!-- popup links -->
    <security:intercept-url pattern="/popupLink/*" requires-channel="any" />

    <!--  addresses -->
    <security:intercept-url pattern="/my-addresses*" requires-channel="any" />
    <security:intercept-url pattern="/my-addresses/**" requires-channel="any" />

    <security:intercept-url pattern="/search/autocompleteSecure/**" requires-channel="https" />

    <!-- OPEN / ANONYMOUS pages Run all other (public) pages openly. Note that while credentials are secure, the session id can be sniffed.
        If this is a security concern, then this line should be re-considered -->
    <security:intercept-url pattern="/**" requires-channel="any" method="POST" /> <!-- Allow posts on either secure or insecure -->
    <security:intercept-url pattern="/**" requires-channel="http" /> <!-- Everything else should be insecure -->

    <security:form-login
            login-page="/login"
            authentication-failure-handler-ref="loginAuthenticationFailureHandler" 
            authentication-success-handler-ref="loginGuidAuthenticationSuccessHandler"  />

    <security:logout logout-url="/logout" success-handler-ref="logoutSuccessHandler" />

    <security:port-mappings>
        <security:port-mapping http="#{configurationService.configuration.getProperty('tomcat.http.port')}"
            https="#{configurationService.configuration.getProperty('tomcat.ssl.port')}" />
        <security:port-mapping http="80" https="443" />
        <!--security:port-mapping http="#{configurationService.configuration.getProperty('proxy.http.port')}"
            https="#{configurationService.configuration.getProperty('proxy.ssl.port')}" /-->
    </security:port-mappings>

    <security:request-cache ref="httpSessionRequestCache" />

    <security:remember-me key="JNJRMBM" user-service-ref="gymUserDetailService" />
</security:http>

<security:authentication-manager alias="authenticationManager">
    <security:authentication-provider ref="acceleratorAuthenticationProvider" />
</security:authentication-manager>

<bean id="acceleratorAuthenticationProvider" class="org.jnj.storefront.security.AcceleratorAuthenticationProvider"
    scope="tenant">
    <property name="userDetailsService" ref="gymUserDetailService" />
    <property name="adminGroup" value="ROLE_ADMINGROUP"/>
    <property name="userService" ref="userService"/>
    <property name="gymCustomerLoginService" ref="defaultGymCustomerLoginService"/>
</bean>

<bean id="gymUserDetailService" class="org.jnj.storefront.security.services.impl.GymCoreUserDetailsService" scope="tenant">
    <property name="baseDao" ref="asyBaseDao" />
</bean>

<bean id="coreUserDetailsService" class="de.hybris.platform.spring.security.CoreUserDetailsService" scope="tenant" />

<bean id="guidCookieStrategy" class="org.jnj.storefront.security.impl.DefaultGUIDCookieStrategy"
    scope="tenant">
    <property name="cookieGenerator" ref="guidCookieGenerator" />       
</bean>

<alias name="defaultGuidCookieGenerator" alias="guidCookieGenerator"/>
<bean id="defaultGuidCookieGenerator" class="org.jnj.storefront.security.cookie.EnhancedCookieGenerator" scope="tenant">
    <property name="cookieSecure" value="true" />
    <property name="cookieName" value="acceleratorSecureGUID" />        
    <property name="httpOnly" value="false"/>
    <!-- if context allows a httpOnly adjust to true  -->
</bean>

<bean id="autoLoginStrategy" class="org.jnj.storefront.security.impl.DefaultAutoLoginStrategy" scope="tenant">
</bean>

<bean id="httpSessionRequestCache" class="org.jnj.storefront.security.impl.WebHttpSessionRequestCache"
    scope="tenant" />

<bean id="loginUserType" class="org.jnj.storefront.security.impl.LoginUserTypeBean" scope="tenant" />

<bean id="redirectStrategy" class="org.springframework.security.web.DefaultRedirectStrategy" scope="tenant" />

<!-- Login Success Handlers -->

<bean id="loginGuidAuthenticationSuccessHandler" class="org.jnj.storefront.security.GUIDAuthenticationSuccessHandler" scope="tenant">
    <property name="authenticationSuccessHandler" ref="loginAuthenticationSuccessHandler" />
    <property name="guidCookieStrategy" ref="guidCookieStrategy" />
</bean>

<bean id="loginAuthenticationSuccessHandler" class="org.jnj.storefront.security.StorefrontAuthenticationSuccessHandler" scope="tenant">
    <property name="customerFacade" ref="customerFacade" />
    <property name="defaultTargetUrl" value="/my-account"/>
    <property name="useReferer" value="true"/>
    <property name="alwaysUseDefaultTargetUrl" value="false"/>
    <property name="requestCache" ref="httpSessionRequestCache" />
</bean>

<bean id="loginCheckoutGuidAuthenticationSuccessHandler" class="org.jnj.storefront.security.GUIDAuthenticationSuccessHandler" scope="tenant">
    <property name="authenticationSuccessHandler" ref="loginCheckoutAuthenticationSuccessHandler" />
    <property name="guidCookieStrategy" ref="guidCookieStrategy" />
    <property name="defaultGymCartFacade" ref="gymCartFacade"/>
</bean>

<bean id="loginCheckoutAuthenticationSuccessHandler" class="org.jnj.storefront.security.StorefrontAuthenticationSuccessHandler" scope="tenant">
    <property name="customerFacade" ref="customerFacade" />
    <property name="defaultTargetUrl" value="/checkout/single/summary"/>
</bean>

<!-- Login Failure Handlers -->

<bean id="loginAuthenticationFailureHandler" class="org.jnj.storefront.security.LoginAuthenticationFailureHandler">
    <property name="defaultFailureUrl" value="/login?error=auth"/>
    <property name="accountBlockedUrl" value="/login?error=blocked"/>
    <property name="passwordMigrationUrl" value="/login?error=migration"/>
</bean>

<bean id="loginCheckoutAuthenticationFailureHandler" class="org.jnj.storefront.security.LoginAuthenticationFailureHandler">
    <property name="defaultFailureUrl" value="/login/checkout?error=auth"/>     
    <property name="accountBlockedUrl" value="/login/checkout?error=blocked"/>
    <property name="passwordMigrationUrl" value="/login/checkout?error=migration"/>     
</bean>


<!-- Logout Success Handler -->

<bean id="logoutSuccessHandler" class="org.jnj.storefront.security.StorefrontLogoutSuccessHandler" scope="tenant">
    <property name="defaultTargetUrl" value="/?logout=true"/>
    <property name="guidCookieStrategy" ref="guidCookieStrategy"/>
    <property name="cmsSiteService" ref="cmsSiteService"/>
</bean>

<bean id="gymRememberMeService" class="org.jnj.storefront.security.cookie.DefaultRememberMeService" scope="tenant">
    <property name="tokenService" ref="secureTokenService" />
    <property name="rememberMeCookieGenerator" ref="defaultRememberMeCookieGenerator" />
</bean>

<bean id="rememberMeFilter" class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
    <property name="rememberMeServices" ref="gymRememberMeService"/>
    <property name="authenticationManager" ref="authenticationManager" />
</bean>

【问题讨论】:

  • 你能把完整的security-context.xml放在这里吗?
  • 嗨@Xaerxess,我刚刚添加了它.. 感谢您查看它!

标签: spring-security remember-me hybris


【解决方案1】:

你有没有尝试看看here (Spring Docs)? 他们说:

“不要忘记将 RememberMeServices 实现添加到您的 UsernamePasswordAuthenticationFilter.setRememberMeServices() 属性, 将 RememberMeAuthenticationProvider 包含在您的 AuthenticationManager.setProviders() 列表,并添加 记住MeAuthenticationFilter 到你的FilterChainProxy(通常 紧跟在您的 UsernamePasswordAuthenticationFilter 之后)。”

在您的情况下,RememberMeServices 是 gymRememberMeService;你有 RememberMeAuthenticationProvider 吗?

HTH

【讨论】:

  • 感谢@OhadR,这是难题的一部分。我基本上必须明确地使用登录表单和记住我(而不是通过各自的标签)。我现在将发布适合我的解决方案。
【解决方案2】:

我最终不得不明确声明 form-login 和 remember-me 标签,并在过滤器链中声明它们。

所以我不得不将相应的过滤器声明为 bean,而不是标签和标签,相应地配置它们,然后使用标签将它们定义在过滤器链中的相应位置。 (如果您使用自定义过滤器标签和显式标签,您会在启动时遇到 spring 错误)。

这对我有用:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-3.1.xsd">

<security:http pattern="/_ui/**" security="none" />


<!-- Default security config -->
<security:http disable-url-rewriting="true" entry-point-ref="gymAuthenticationEntryPoint">

    <!-- using custom login filter config and rememberme filter config  -->
    <security:custom-filter ref="gymRememberMeFilter" position="REMEMBER_ME_FILTER"/>
    <security:custom-filter ref="gymAuthenticationFilter" position="FORM_LOGIN_FILTER"/>

    <security:anonymous username="anonymous" granted-authority="ROLE_ANONYMOUS" />

    <!-- session stealing is prevented by using secure GUID cookie -->
    <security:session-management session-fixation-protection="none" />

    <!-- SSL / AUTHENTICATED pages -->
    <security:intercept-url pattern="/my-account*" access="ROLE_CUSTOMERGROUP" requires-channel="https" />

<!-- omitting intercept definitions for readability -->

<!-- use explicit FORM_LOGIN_FILTER (see above) and entry-point (see entry-point-ref in http tag) instead of form-login definition
    <security:form-login
            login-page="/login"
            authentication-failure-handler-ref="loginAuthenticationFailureHandler" 
            authentication-success-handler-ref="loginGuidAuthenticationSuccessHandler"  />
-->

    <security:logout logout-url="/logout" success-handler-ref="logoutSuccessHandler" />

    <security:port-mappings>
        <security:port-mapping http="#{configurationService.configuration.getProperty('tomcat.http.port')}"
            https="#{configurationService.configuration.getProperty('tomcat.ssl.port')}" />
        <security:port-mapping http="80" https="443" />
        <!--security:port-mapping http="#{configurationService.configuration.getProperty('proxy.http.port')}"
            https="#{configurationService.configuration.getProperty('proxy.ssl.port')}" /-->
    </security:port-mappings>

    <security:request-cache ref="httpSessionRequestCache" />


</security:http>

<security:authentication-manager alias="authenticationManager">
    <security:authentication-provider ref="acceleratorAuthenticationProvider" />
    <security:authentication-provider ref="rememberMeAuthenticationProvider" />
</security:authentication-manager>

<bean id="acceleratorAuthenticationProvider" class="org.jnj.storefront.security.AcceleratorAuthenticationProvider"
    scope="tenant">
    <property name="userDetailsService" ref="gymUserDetailService" />
    <property name="adminGroup" value="ROLE_ADMINGROUP"/>
    <property name="userService" ref="userService"/>
    <property name="gymCustomerLoginService" ref="defaultGymCustomerLoginService"/>
</bean>

<bean id="gymUserDetailService" class="org.jnj.storefront.security.services.impl.GymCoreUserDetailsService" scope="tenant">
    <property name="baseDao" ref="asyBaseDao" />
</bean>

<bean id="coreUserDetailsService" class="de.hybris.platform.spring.security.CoreUserDetailsService" scope="tenant" />


<!-- Login Success Handlers -->

<bean id="loginGuidAuthenticationSuccessHandler" class="org.jnj.storefront.security.GUIDAuthenticationSuccessHandler" scope="tenant">
    <property name="authenticationSuccessHandler" ref="loginAuthenticationSuccessHandler" />
    <property name="guidCookieStrategy" ref="guidCookieStrategy" />
</bean>

<bean id="loginAuthenticationSuccessHandler" class="org.jnj.storefront.security.StorefrontAuthenticationSuccessHandler" scope="tenant">
    <property name="customerFacade" ref="customerFacade" />
    <property name="defaultTargetUrl" value="/my-account"/>
    <property name="useReferer" value="true"/>
    <property name="alwaysUseDefaultTargetUrl" value="false"/>
    <property name="requestCache" ref="httpSessionRequestCache" />
</bean>

<bean id="loginCheckoutGuidAuthenticationSuccessHandler" class="org.jnj.storefront.security.GUIDAuthenticationSuccessHandler" scope="tenant">
    <property name="authenticationSuccessHandler" ref="loginCheckoutAuthenticationSuccessHandler" />
    <property name="guidCookieStrategy" ref="guidCookieStrategy" />
    <property name="defaultGymCartFacade" ref="gymCartFacade"/>
</bean>

<bean id="loginCheckoutAuthenticationSuccessHandler" class="org.jnj.storefront.security.StorefrontAuthenticationSuccessHandler" scope="tenant">
    <property name="customerFacade" ref="customerFacade" />
    <property name="defaultTargetUrl" value="/checkout/single/summary"/>
</bean>

<!-- Login Failure Handlers -->

<bean id="loginAuthenticationFailureHandler" class="org.jnj.storefront.security.LoginAuthenticationFailureHandler">
    <property name="defaultFailureUrl" value="/login?error=auth"/>
    <property name="accountBlockedUrl" value="/login?error=blocked"/>
    <property name="passwordMigrationUrl" value="/login?error=migration"/>
</bean>

<bean id="loginCheckoutAuthenticationFailureHandler" class="org.jnj.storefront.security.LoginAuthenticationFailureHandler">
    <property name="defaultFailureUrl" value="/login/checkout?error=auth"/>     
    <property name="accountBlockedUrl" value="/login/checkout?error=blocked"/>
    <property name="passwordMigrationUrl" value="/login/checkout?error=migration"/>     
</bean>


<!-- Logout Success Handler -->

<bean id="logoutSuccessHandler" class="org.jnj.storefront.security.StorefrontLogoutSuccessHandler" scope="tenant">
    <property name="defaultTargetUrl" value="/?logout=true"/>
    <property name="guidCookieStrategy" ref="guidCookieStrategy"/>
    <property name="cmsSiteService" ref="cmsSiteService"/>
</bean>


<!-- remember me services -->
<bean id="rememberMeServices" class="org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
    <property name="userDetailsService" ref="gymUserDetailService"/>
    <property name="key" value="someprivatekey"/> <!-- must match the rememberMeAuthenticationProvider key -->
    <property name="parameter" value="rememberMe" /><!-- must match the parameter in the login form -->
    <property name="cookieName" value="JNJ_RMMBRM" />
    <property name="useSecureCookie" value="false" /> <!-- if set to true "remember me" only gets detected when accessed via https -->
    <property name="tokenValiditySeconds" value="31536000" /> <!-- 1 year -->
</bean>

<bean id="rememberMeAuthenticationProvider" class="org.springframework.security.authentication.RememberMeAuthenticationProvider">
    <property name="key" value="someprivatekey"/>
</bean>

<bean id="gymRememberMeFilter" class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
    <property name="rememberMeServices" ref="rememberMeServices"/>
    <property name="authenticationManager" ref="authenticationManager" />
    <property name="authenticationSuccessHandler" ref="loginGuidAuthenticationSuccessHandler"/>
</bean>

<!-- login filter and entry point -->   
<bean id="gymAuthenticationFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
    <property name="authenticationManager" ref="authenticationManager"/>
    <property name="filterProcessesUrl" value="/j_spring_security_check"/>
    <property name="rememberMeServices" ref="rememberMeServices"/>
    <property name="authenticationSuccessHandler" ref="loginGuidAuthenticationSuccessHandler"/>
    <property name="authenticationFailureHandler" ref="loginAuthenticationFailureHandler"/>
</bean>
<bean id="gymAuthenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
    <property name="loginFormUrl" value="/login"/>
</bean>

【讨论】:

    【解决方案3】:

    Spring Security 3.2+ 支持 remember-me 元素上的 services-ref 属性。因此,在您的安全配置中,您将拥有:

    <security:http xmlns="http://www.springframework.org/schema/security">
      ...
      <remember-me services-ref="rememberMeServices" key="secret-key">
    </security:http>
    
    <bean id="rememberMeServices" class="com.example.MyRememberMeServices">
      <constructor-arg index="0" value="secret-key" />
      <constructor-arg index="1" ref="userDetailsService" />
      <property name="tokenValiditySeconds" value="1000000" />
    </bean>
    

    com.example.MyRememberMeServices 是您自定义的 RememberMeServices 实现类。这样就不再需要处理过滤器链、身份验证管理器或其他任何东西了。

    【讨论】:

      猜你喜欢
      • 2014-05-05
      • 1970-01-01
      • 2012-03-30
      • 2011-12-05
      • 2013-07-23
      • 1970-01-01
      • 1970-01-01
      • 2011-11-08
      • 1970-01-01
      相关资源
      最近更新 更多