- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我想为我的登录过滤器实现自定义 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
。我试过这样做,仍然没有用。其他一切都很好,唯一的问题是每次我登录时,spring 都会将我重定向到 '/'
。这不是我想要的,我只想返回 '200 OK'
最佳答案
假设我理解正确,无论身份验证如何发生,您都希望在身份验证成功时中断过滤器链并发送 HTTP 响应代码;即它可以是登录表单或记住我的身份验证。
因此,首先,将以下逻辑添加到您的 CustomSavedRequestAwareAuthenticationSuccessHandler
:
// place where applicable
if (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);
}
}
}
第三,在security:http
部分定义customer filer为:
<custom-filter position="LAST" ref="myHttpResponseAuthFilter" />
第四,将成功处理程序的引用添加到您的 form-login
中:
<form-login ... authentication-success-handler-ref="mySuccessHandler" ... />
因为您的表单例份验证中缺少它。
此外,基于 Spring Security关于过滤器位置的文档,建议您不要对自定义过滤器使用auto-config
。
注意:
我还建议阅读 this answer因为它可以更深入地了解 Spring Security 中表单登录、http 基本身份验证和记住我服务之间的区别。
关于java - RememberMeAuthenticationFilter 的 Spring Security authenticationSuccessHandler,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18864459/
我已经使用 Spring Security 3.1 在 Spring MVC 应用程序中实现了“记住我”功能 我的 security-context.xml 如下所示:
我正在尝试将 RememberMe 功能集成到 Spring 3 webapp 中。该应用运行良好,未显示任何其他问题。 当我启用“记住我”检查时,cookie 会正确创建并随任何请求一起发送(我已经
我想为我的登录过滤器实现自定义 AuthenticationSuccessHandler,即 org.springframework.security.web.authentication.remem
提供 AuthenticationSuccessHandler对于 RememberMeAuthenticationFilter打破了过滤器链,因此我想覆盖它的 onSuccessfulAuthent
我是一名优秀的程序员,十分优秀!