关于ZAKER 融媒体解决方案 合作 加入

java – 用于 RememberMeAuthenticationFilter 的 Spring.

CocoaChina 11-11

我想为我的登录过滤器实现一个自定义 AuthenticationSuccessHandler, 它是 org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.

这是我的 spring 安全配置

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security" 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 entry-point-ref="restAuthenticationEntryPoint" disable-url-rewriting = "true" auto-config="true" use-expressions="true"> <security:intercept-url pattern="/api/*" access="hasRole ( 'AUTHENTICATED_USER' ) "/> <security:remember-me key="spring_login_detail" services-ref="rememberMeServices"/> <security:form-login login-processing-url="/login"/> <security:logout invalidate-session="true" delete-cookies="JSESSIONID,SPRING_SECURITY_REMEMBER_ME_COOKIE" logout-url="/logout" /> </security:http> <security:global-method-security secured-annotations="enabled" pre-post-annotations="enabled"/> <security:authentication-manager alias="authenticationManager"> <security:authentication-provider ref="rememberMeAuthenticationProvider"/> <security:authentication-provider user-service-ref="customUserDetailsService"> <security:password-encoder ref="passwordEncoder"/> </security:authentication-provider> </security:authentication-manager> <bean class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" id="passwordEncoder"/> <bean id="mySuccessHandler" class="com.projectname.security.CustomSavedRequestAwareAuthenticationSuccessHandler"/> <bean id="customUserDetailsService" class="com.projectname.security.CustomUserDetailsService"/> <bean id="rememberMeServices" class="org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices"> <property name="key" value="jsfspring-sec" /> <property name="userDetailsService" ref="customUserDetailsService" /> <property name="alwaysRemember" value="false" /> <property name="tokenValiditySeconds" value="1209600" /> <property name="parameter" value="_spring_security_remember_me_input"/> </bean> <bean id="rememberMeAuthenticationProvider" class="org.springframework.security.authentication.RememberMeAuthenticationProvider"> <property name="key" value="spring_login_detail"/> </bean> <bean id="rememberMeFilter" class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter"> <property name="rememberMeServices" ref="rememberMeServices"/> <property name="authenticationManager" ref="authenticationManager" /> <property name="authenticationSuccessHandler" ref="mySuccessHandler"/> </bean> </beans>

这是我的自定义 AuthenticationSuccessHandler 实现

import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.security.core.Authentication;import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;import org.springframework.security.web.savedrequest.HttpSessionRequestCache;import org.springframework.security.web.savedrequest.RequestCache;import org.springframework.security.web.savedrequest.SavedRequest;import org.springframework.util.StringUtils;public class CustomSavedRequestAwareAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { private RequestCache requestCache = new HttpSessionRequestCache ( ) ; @Override public void onAuthenticationSuccess ( HttpServletRequest request, HttpServletResponse response, Authentication authentication ) throws ServletException, IOException { SavedRequest savedRequest = requestCache.getRequest ( request, response ) ; if ( savedRequest == null ) { clearAuthenticationAttributes ( request ) ; return; } String targetUrlParam = getTargetUrlParameter ( ) ; if ( isAlwaysUseDefaultTargetUrl ( ) || ( targetUrlParam != null && StringUtils.hasText ( request.getParameter ( targetUrlParam ) ) ) ) { requestCache.removeRequest ( request, response ) ; clearAuthenticationAttributes ( request ) ; return; } clearAuthenticationAttributes ( request ) ; } public void setRequestCache ( RequestCache requestCache ) { this.requestCache = requestCache; }}

问题是在成功验证之后根本没有调用 onAuthenticationSuccess. 我在 StackOverflow 上读到了一个答案 , 说我需要实现 onAuthenticationSuccess 而不是 SimpleUrlAuthenticationSuccessHandler. 我试过这样做 , 仍然没有奏效 . 其他一切都很好 , 唯一的问题是每次我登录时 , 春天只是将我重定向到’ / ’ . 这不是我想要的 , 我希望它只是返回’ 200 OK ’

最佳答案

假设我已经正确理解 , 无论身份验证如何发生 , 您都希望在身份验证成功时中断过滤器链并发送 HTTP 响应代码 ; 即它可以是登录表单或记住我的身份验证 .

因此 , 首先 , 将以下逻辑添加到 CustomSavedRequestAwareAuthenticationSuccessHandler:

// place where applicableif ( authentication != null ) { response.setStatus ( HttpServletResponse.SC_OK ) ;}

其次 , 定义一个新的过滤器 , 例如:

class HttpResponseAuthenticationFilter extends RememberMeAuthenticationFilter { protected void onSuccessfulAuthentication ( HttpServletRequest request, HttpServletResponse response, Authentication authResult ) { super.onSuccessfulAuthentication ( request, response, authResult ) ; if ( authResult != null ) { response.setStatus ( HttpServletResponse.SC_OK ) ; } }}

第三 , 在安全性中定义客户文件管理器:http 部分为:

<custom-filter position="LAST" ref="myHttpResponseAuthFilter" />

第四 , 为您的表单登录添加成功处理程序的引用 , 如下所示:

<form-login ... authentication-success-handler-ref="mySuccessHandler" ... />

因为表单身份验证中缺少此功能 .

此外 , 根据有关过滤器位置的Spring Security文档 , 建议您不要将 auto-config 与自定义过滤器一起使用 .

观察:

> 您看到此行为的原因是 , 当您看到登录表单时 , 它与 mem-me 服务无关 . 表单处理决定了最终目标 URL.

> 第一次之后 , 它是 remember-me 过滤器进行身份验证 , 并再次需要发送 HTTP 响应代码 .

我还建议阅读this answer, 因为它更深入地了解了 Spring Security 中 form-login,http-basic auth 和 remember-me 服务之间的区别 .

以上内容由"CocoaChina"上传发布 查看原文

觉得文章不错,微信扫描分享好友

扫码分享