SpringSecurity自定义过滤器之后Session会话控制失效

J2EE 码拜 10年前 (2015-04-10) 1369次浏览 0个评论

最近在研究SpringSecurity开始一切正常但是自定义过滤器后却发现对Session控制的会话控制失效了。网上说如果重写了User类要重写equals和hashCode方法。但是我没有重写User类也不好使,之后我重写了后也重写了equals和hashCode方法,还是不好使。调试之后根本没有进入equals方法但是hashCode方法却走了很多遍。求大神指点。下面开帖代码。
applicationContext-security.xml代码

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

	<!-- 访问被拒绝时跳转到403界面 -->
	<http entry-point-ref="authenticationProcessingFilterEntryPoint"
		access-denied-page="/403.jsp" >
		<!-- 放行页面 -->
		<intercept-url pattern="/*.css" filters="none" />
		<intercept-url pattern="/error.jsp" filters="none" />
		<intercept-url pattern="/index*.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY" requires-channel="any" />
		<!-- 访问全部要通过身份验证 -->
		<intercept-url pattern="/**" access="isAuthenticated()" />
		<!-- 访问全部要有ROLE_USER权限 -->
		<intercept-url pattern="/**" access="ROLE_USER" />

		<!-- 安全退出后的页面 -->
		<logout logout-success-url="/logout.jsp" />
		<!-- 两周内记住我 -->
		<remember-me key="jbcpPetStore" />

		<!-- 检测失效的sessionId,超时时定位到另外一个URL, -->
		<session-management
			session-authentication-error-url="/No_certification.jsp"
			invalid-session-url="/index.jsp" session-fixation-protection="migrateSession">
			<!-- 防止多端登录 -->
			<concurrency-control max-sessions="1"
				error-if-maximum-exceeded="true" expired-url="/error.jsp" />
		</session-management>

			<custom-filter ref="loginFilter" position="FORM_LOGIN_FILTER" />
	</http>

	<!-- 自定义登录过滤 -->
	<beans:bean id="loginFilter"
		class="filter.UsernamePasswordAuthenticationExtendFilter">
		<!-- 验证页面 -->
		<beans:property name="filterProcessesUrl" value="/j_spring_security_check" />
		<!-- 验证成功后的处理 -->
		<beans:property name="authenticationSuccessHandler"
			ref="loginLogAuthenticationSuccessHandler" />
		<!-- 验证失败后的处理 -->
		<beans:property name="authenticationFailureHandler"
			ref="simpleUrlAuthenticationFailureHandler" />
		<!-- 认证器 -->
		<beans:property name="authenticationManager" ref="authenticationManager" />

	</beans:bean>

	<!-- 认证器 -->
	<authentication-manager alias="authenticationManager">
		<authentication-provider user-service-ref=""myUserDetailsService"" />
	</authentication-manager>

	<!-- 注入认证器 -->
	<beans:bean id="myUserDetailsService" class="filter.MyUserDetailService" />

	<!-- 开始注入登录过滤器 -->
	<beans:bean id="loginLogAuthenticationSuccessHandler"
		class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
		<beans:property name="defaultTargetUrl" value="/welcome.jsp"></beans:property>
	</beans:bean>
	<beans:bean id="simpleUrlAuthenticationFailureHandler"
		class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
		<beans:property name="defaultFailureUrl" value="/index.jsp?error=true"></beans:property>
	</beans:bean>
	<!-- 注入登录过滤器结束 -->

	<beans:bean id="authenticationProcessingFilterEntryPoint"
		class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
		<beans:property name="loginFormUrl" value="/index.jsp"></beans:property>
	</beans:bean>

</beans:beans>

web.xml页面

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	version="3.0">
	<display-name></display-name>
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
	<!-- 防止请求Spring乱码 -->
	<filter>
		<filter-name>characterEncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>utf-8</param-value>
		</init-param>
		<init-param>
			<!--强制转换编码(request和response均适用) -->
			<param-name>ForceEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>characterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	<!-- Spring Security过滤器 -->
	<filter>
		<filter-name>springSecurityFilterChain</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>springSecurityFilterChain</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	<!-- Struts2 -->
	<filter>
		<filter-name>struts2</filter-name>
		<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>struts2</filter-name>
		<url-pattern>*.action</url-pattern>
	</filter-mapping>
	<!-- Spring -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:applicationContext.xml,classpath:applicationContext-security.xml</param-value>
	</context-param>
	<!-- Spring监听 -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
		<!-- 监听session 防止多端登录 -->
	<listener>
		<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
	</listener>
	<!-- session有效期为30分 -->
	<session-config>
		<session-timeout>30</session-timeout>
	</session-config>
</web-app>
SpringSecurity自定义过滤器之后Session会话控制失效
继承UsernamePasswordAuthenticationFilter类的代码

package filter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
  

/** 
 * 重载SECURITY3的UsernamePasswordAuthenticationFilter的attemptAuthentication, 
 * obtainUsername,obtainPassword方法(完善逻辑) 增加验证码校验模块 添加验证码属性 添加验证码功能开关属性 
 *  
 * @author shadow 
 * @email 124010356@qq.com 
 * @create 2012.04.28 
 */
public class UsernamePasswordAuthenticationExtendFilter extends UsernamePasswordAuthenticationFilter  {

	private SessionAuthenticationStrategy  sessionAuthenticationStrategy = null;


	public SessionAuthenticationStrategy getSessionAuthenticationStrategy() {
		return sessionAuthenticationStrategy;
	}

	public void setSessionAuthenticationStrategy(
			SessionAuthenticationStrategy sessionAuthenticationStrategy) {
		this.sessionAuthenticationStrategy = sessionAuthenticationStrategy;
	}

		// 验证码字段
		private String validateCodeParameter = "validateCode";
		// 是否开启验证码功能
		private boolean openValidateCode = false;

		@Override
		public Authentication attemptAuthentication(HttpServletRequest request,
				HttpServletResponse response) throws AuthenticationException {
			request.getSession().removeAttribute("msg");
			// 只接受POST方式传递的数据
			if (!"POST".equals(request.getMethod())){
				throw new AuthenticationServiceException("不支持非POST方式的请求!");
			}

			// 开启验证码功能的情况
			if (isOpenValidateCode()){
				checkValidateCode(request);
			}

			// 获取Username和Password
			String username = obtainUsername(request);
			String password = obtainPassword(request);

			// UsernamePasswordAuthenticationToken实现Authentication校验
			UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
					username, password);

			// 允许子类设置详细属性
			setDetails(request, authRequest);

			// 运行UserDetailsService的loadUserByUsername 再次封装Authentication
			return this.getAuthenticationManager().authenticate(authRequest);
		}

		// 匹对验证码的正确性
		public void checkValidateCode(HttpServletRequest request) {
			String jcaptchaCode = obtainValidateCodeParameter(request);
			if (null == jcaptchaCode || "".equals(jcaptchaCode)){
				throw new AuthenticationServiceException("请输入验证码");    
			}
			if(null == request.getSession().getAttribute("rand")){
				throw new AuthenticationServiceException("验证码失效");    
			}
			//对比普通验证码
			if(!request.getSession().getAttribute("rand").equals(jcaptchaCode)){
				throw new AuthenticationServiceException("验证码错误!");    
			}
			return;
		}

		public String obtainValidateCodeParameter(HttpServletRequest request) {
			Object obj = request.getParameter(getValidateCodeParameter());
			return null == obj ? "" : obj.toString().trim();
		}

		@Override
		protected String obtainUsername(HttpServletRequest request) {
			Object obj = request.getParameter(getUsernameParameter());
			return null == obj ? "" : obj.toString().trim();
		}

		@Override
		protected String obtainPassword(HttpServletRequest request) {
			Object obj = request.getParameter(getPasswordParameter());
			return null == obj ? "" : obj.toString().trim();
		}

		public String getValidateCodeParameter() {
			return validateCodeParameter;
		}

		public void setValidateCodeParameter(String validateCodeParameter) {
			this.validateCodeParameter = validateCodeParameter;
		}

		public boolean isOpenValidateCode() {
			return openValidateCode;
		}

		public void setOpenValidateCode(boolean openValidateCode) {
			this.openValidateCode = openValidateCode;
		}
}

UserDetailsService页面代码

package filter;

import java.util.ArrayList;
import java.util.Collection;

import model.UserDetail;

import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

/**
 * 登录类
 * 
 * @author Administrator
 * @comment 在这个类中,你就可以从数据库中读入用户的密码、角色信息、是否锁定、 账号是否过期等. new User()方法参数说明, String
 *          username(用户名), String password(密码), boolean enabled(账户是否可用), boolean
 *          accountNonExpired(账户是否未过期), boolean accountNonLocked(账户是否未锁定),
 *          Collection<GrantedAuthority> authorities(账户所受权限).
 */
public class MyUserDetailService implements UserDetailsService {


	@Override
	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException, DataAccessException {
		Collection<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
		GrantedAuthorityImpl auth2 = new GrantedAuthorityImpl("ROLE_USER");// 进行授权
		auths.add(auth2);// 添加所授的权限 
		UserDetail user = new UserDetail("123", "123", true, true, true, true, auths);
		return  user;
	}
}

UserDetail类方法

package model;

import java.util.Collection;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

@SuppressWarnings("serial")
public class UserDetail implements UserDetails {
	private Collection<GrantedAuthority> authorities;
	private String password;
	private String username;
	private boolean isAccountNonExpired;
	private boolean isAccountNonLocked;
	private boolean isCredentialsNonExpired;
	private boolean isEnabled;

	/** default constructor */
	public UserDetail() {
	}

	public UserDetail(String username, String password,
			boolean isAccountNonExpired, boolean isAccountNonLocked,
			boolean isCredentialsNonExpired, boolean isEnabled, Collection<GrantedAuthority> authorities) {
		this.username = username;
		this.password = password;
		this.isAccountNonExpired = isAccountNonExpired;
		this.isAccountNonLocked = isAccountNonLocked;
		this.isCredentialsNonExpired = isCredentialsNonExpired;
		this.isEnabled = isEnabled;
		this.authorities = authorities;
	}

	// Constructors

	public Collection<GrantedAuthority> getAuthorities() {
		return authorities;
	}

	public void setAuthorities(Collection<GrantedAuthority> authorities) {
		this.authorities = authorities;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public boolean isAccountNonExpired() {
		return isAccountNonExpired;
	}

	public void setAccountNonExpired(boolean isAccountNonExpired) {
		this.isAccountNonExpired = isAccountNonExpired;
	}

	public boolean isAccountNonLocked() {
		return isAccountNonLocked;
	}

	public void setAccountNonLocked(boolean isAccountNonLocked) {
		this.isAccountNonLocked = isAccountNonLocked;
	}

	public boolean isCredentialsNonExpired() {
		return isCredentialsNonExpired;
	}

	public void setCredentialsNonExpired(boolean isCredentialsNonExpired) {
		this.isCredentialsNonExpired = isCredentialsNonExpired;
	}

	public boolean isEnabled() {
		return isEnabled;
	}

	public void setEnabled(boolean isEnabled) {
		this.isEnabled = isEnabled;
	}

	@Override
	public boolean equals(Object obj) {
		System.out.println("进入equals方法");
		if (obj instanceof UserDetail) {
			UserDetail another = (UserDetail)obj;
			return this.getUsername().equals(another.getUsername());
		}
		return super.equals(obj);
	}

	@Override
	public int hashCode() {
		System.out.println("进入hashCode方法");
		return this.getUsername().hashCode();
	}

}

SpringSecurity自定义过滤器之后Session会话控制失效
自顶!
SpringSecurity自定义过滤器之后Session会话控制失效
人工置顶!
SpringSecurity自定义过滤器之后Session会话控制失效
大神们呢??
不要沉啊!!
SpringSecurity自定义过滤器之后Session会话控制失效
人工置顶!

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明SpringSecurity自定义过滤器之后Session会话控制失效
喜欢 (0)
[1034331897@qq.com]
分享 (0)

文章评论已关闭!