I'm using Spring Security 3 and I want to perform some logic (saving some data in the session) when the user is visiting the site and he's remembered. I extended the GenericFilterBean class, perform the logic in the doFilter method, then complete the filter chain by calling the chain.doFilter method. I inserted that filter after the "remember me" filter in the security.xml file.
But the problem is that the filter is executed on each page regardless of whether the user is remembered or not. Is there something wrong with the filter implementation or the position of the filter?
Is the filter chain by default executed on each page? When making a custom filter should i add it to the web.xml too?
The filter class:
package projects.internal;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.GenericFilterBean;
import projects.ProjectManager;
public class rememberMeFilter extends GenericFilterBean {
private ProjectManager projectManager;
@Autowired
public rememberMeFilter(ProjectManager projectManager) {
this.projectManager = projectManager;
}
@Override
public void doFilter(ServletRequest req, ServletResponse res,
开发者_高级运维 FilterChain chain) throws IOException, ServletException {
System.out.println("In The Filter");
Authentication auth = (Authentication) SecurityContextHolder
.getContext().getAuthentication();
HttpServletResponse response = ((HttpServletResponse) res);
HttpServletRequest request = ((HttpServletRequest) req);
// if the user is not remembered,do nothing
if (auth == null) {
chain.doFilter(request, response);
}
else {
// the user is remembered save some data in the session
System.out.println("User Is Remembered");
chain.doFilter(request, response);
}
}
}
The security.xml file:
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" 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.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<global-method-security pre-post-annotations="enabled">
</global-method-security>
<http use-expressions="true" >
<remember-me data-source-ref="dataSource"/>
<intercept-url pattern="/" access="permitAll" />
<intercept-url pattern="/images/**" filters="none" />
<intercept-url pattern="/scripts/**" filters="none" />
<intercept-url pattern="/styles/**" filters="none" />
<intercept-url pattern="/p/login" filters="none" />
<intercept-url pattern="/p/register" filters="none" />
<intercept-url pattern="/p/forgot_password" filters="none" />
<intercept-url pattern="/p/**" access="isAuthenticated()" />
<custom-filter after="REMEMBER_ME_FILTER" ref="rememberMeFilter" />
<form-login login-processing-url="/j_spring_security_check"
login-page="/p/login" authentication-failure-url="/p/login?login_error=1"
default-target-url="/p/dashboard" authentication-success-handler-ref="myAuthenticationHandler"
always-use-default-target="false" />
<logout/>
</http>
<beans:bean id="myAuthenticationHandler" class="projects.internal.myAuthenticationHandler" />
<beans:bean id="rememberMeFilter" class="projects.internal.rememberMeFilter" >
</beans:bean>
<authentication-manager alias="authenticationManager">
<authentication-provider>
<password-encoder hash="md5" />
<jdbc-user-service data-source-ref="dataSource" />
</authentication-provider>
</authentication-manager>
</beans:beans>
Any help?
I think your confusion comes from the fact that the Spring Security Filter Chain is a single ServletFilter
, which contains it's own, internal, chain of SpringSecurityFilters
. If you want to add a filter to the that chain you need to subclass SpringSecurityFIlter
and implement it's doFilterHttp()
method. In your case I might try to write a Pre-Authentication filter that does the logic you want. If no user object is found (hence there was none in the session) then it does some logic and then Spring Security goes on to authenticate the user. Check this out for a more detailed example Pre-Authentication Mechanism.
精彩评论