SpringSecurity3.X--一个简单实现

目录

SpringSecurity3.X--一个简单实现

SpringSecurity3.X--前台与后台登录认证

SpringSecurity3.X--remember-me

SpringSecurity3.X--验证码

 

作者对springsecurity研究不深,算是个初学者吧,最近很不完整的看了一下翻译的很是生硬的《Spring3Security-3.0.1中文官方文档.pdf》,为了便于学习和记忆,所以将所学知识在此记录下来。

这里给出一个简单的安全验证的实现例子,先说一下需求:

1.通过登录页面进行登录

2.用户登录前访问被保护的地址时自动跳转到登录页面

3.用户信息存储在数据表中

4.用户权限信息存在在数据表中

5.用户登录成功后访问没有权限访问的地址时跳转到登录页面

 

ok,以上就是一个基本的需求了,大部分的系统都是基于该需求实现登录模块的。

 

给出实现之前,先简单说明一下springsecurity的原理,

1.AccessDecisionManager

和我们一般实现登录验证采用filter的方式一样,springsecurity也是一个过滤器,当请求被springsecurity拦截后,会先对用户请求的资源进行安全认证,如果用户有权访问该资源,则放行,否则将阻断用户请求或提供用户登录,

在springsecurity中,负责对用户的请求资源进行安全认证的是AccessDecisionManager,它就是一组投票器的集合,默认的策略是使用一个AffirmativeBased,既只要有一个投票器通过验证就允许用户访问,

所以如果希望实现自己的权限验证策略,实现自己的投票器是一个很好的选择。

 

2.UserDetailsService

如果用户没有登录就访问某一个受保护的资源,则springsecurity会提示用户登录,用户登录后,由UserDetailsService来验证用户是否合法,既验证用户名和密码是否正确,同时验证用户是否具备相应的资源权限,

即对应的access的value。

如果用户验证通过,则由AccessDecisionManager来决定是否用户可以访问该资源。

 

下面给出具体实现:

web.xml

基本上都是这样配置,就不废话了。

Xml代码 复制代码  收藏代码
  1. <filter>  
  2.     <filter-name>springSecurityFilterChain</filter-name>  
  3.     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
  4. </filter>  
  5. <filter-mapping>  
  6.     <filter-name>springSecurityFilterChain</filter-name>  
  7.     <url-pattern>/*</url-pattern>  
  8. </filter-mapping>  
 

applicationContext-security.xml

 

Xml代码 复制代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans:beans xmlns="http://www.springframework.org/schema/security"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"  
  4.     xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"  
  5.     xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"  
  6.     xmlns:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc"  
  7.     xmlns:tool="http://www.springframework.org/schema/tool" xmlns:beans="http://www.springframework.org/schema/beans"  
  8.     xsi:schemaLocation="   
  9.             http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd   
  10.             http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd   
  11.             http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd   
  12.             http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd   
  13.             http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd   
  14.             http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd   
  15.             http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd   
  16.             http://www.springframework.org/schema/tool http://www.springframework.org/schema/tool/spring-tool-3.0.xsd   
  17.             http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"   
  18.     default-lazy-init="true">  
  19.   
  20.         <!-- 不需要进行认证的资源,3.0之后才改为这样配置 -->  
  21.     <http security="none" pattern="/index.do" />  
  22.   
  23.         <!-- 因为要使用自己的权限验证规则,所以这里要配置access-decision-manager-ref   
  24.          实际上,我只是在accessDecisionManager中增加了一个投票器,其它的属性都比较简单,不多说了 -->  
  25.     <http auto-config='true' access-decision-manager-ref="accessDecisionManager"  
  26.         access-denied-page="/index.do">  
  27.         <intercept-url pattern="/demo.do*" access="IS_AUTHENTICATED_REMEMBERED" />  
  28.         <intercept-url pattern="/**/*.do*" access="HODLE" />  
  29.         <logout logout-url="/logout.do" invalidate-session="true"  
  30.             logout-success-url="/logout.jsp" />  
  31.         <form-login login-page="/index.do" default-target-url="/frame.do"  
  32.             always-use-default-target="true" authentication-failure-url="/index.do?login_error=1" />  
  33.         <session-management>  
  34.             <concurrency-control max-sessions="1" />  
  35.         </session-management>  
  36.     </http>  
  37.   
  38.   
  39.   
  40.     <!-- Automatically receives AuthenticationEvent messages -->  
  41.     <beans:bean id="loggerListener"  
  42.         class="org.springframework.security.authentication.event.LoggerListener" />  
  43.   
  44.        <!-- 认证管理器,使用自定义的UserDetailsService,并对密码采用md5加密-->  
  45.     <authentication-manager>  
  46.         <authentication-provider user-service-ref="userService">  
  47.             <password-encoder hash="md5" />  
  48.         </authentication-provider>  
  49.     </authentication-manager>  
  50.   
  51.     <beans:bean id="userService" class="com.piaoyi.common.security.UserService" />  
  52.   
  53.          <!-- 访问决策管理器,这里使用AffirmativeBased,并加入一个自定义的投票器DynamicRoleVoter -->  
  54.     <beans:bean id="accessDecisionManager"  
  55.         class="org.springframework.security.access.vote.AffirmativeBased">  
  56.         <beans:property name="decisionVoters">  
  57.             <beans:list>  
  58.                 <beans:bean class="org.springframework.security.access.vote.RoleVoter" />  
  59.                 <beans:bean  
  60.                     class="org.springframework.security.access.vote.AuthenticatedVoter" />  
  61.                 <beans:bean class="com.piaoyi.common.security.DynamicRoleVoter" />  
  62.             </beans:list>  
  63.         </beans:property>  
  64.     </beans:bean>  
  65. </beans:beans>  
 

UserService.java

 

Java代码 复制代码  收藏代码
  1. public class UserService implements UserDetailsService{   
  2.   
  3.     @Autowired  
  4.     private ISystemUserService userService;   
  5.     @Override  
  6.     public UserDetails loadUserByUsername(String username)   
  7.             throws UsernameNotFoundException {   
  8.         // TODO Auto-generated method stub   
  9.         SystemUser user = userService.findById(username);          
  10.         if (user == null)   
  11.             throw new UsernameNotFoundException("The user name " + username   
  12.                     + " can not be found!");   
  13.   
  14.         List<GrantedAuthority> resultAuths = new ArrayList<SystemAuthority>();   
  15.                //增加access中配置的权限,实际上这里就是让所有登陆用户都具备该权限,   
  16.                //而真正的资源权限验证留给AccessDecisionManager来决定   
  17.                 resultAuths.add(new GrantedAuthorityImpl("HODLE"));   
  18.            
  19.         //验证用户名和密码是否正确,以及是否权限正确   
  20.         return new User(username, user.getPassword().toLowerCase(), user.isStatus(), true,   
  21.                 truetrue, resultAuths);   
  22.            
  23.            
  24.     }   
  25. }  
public class UserService implements UserDetailsService{

	@Autowired
	private ISystemUserService userService;
	@Override
	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException {
		// TODO Auto-generated method stub
		SystemUser user = userService.findById(username);		
		if (user == null)
			throw new UsernameNotFoundException("The user name " + username
					+ " can not be found!");

		List<GrantedAuthority> resultAuths = new ArrayList<SystemAuthority>();
               //增加access中配置的权限,实际上这里就是让所有登陆用户都具备该权限,
               //而真正的资源权限验证留给AccessDecisionManager来决定
                resultAuths.add(new GrantedAuthorityImpl("HODLE"));
		
		//验证用户名和密码是否正确,以及是否权限正确
		return new User(username, user.getPassword().toLowerCase(), user.isStatus(), true,
				true, true, resultAuths);
		
		
	}
}
 

DynamicRoleVoter.java

Java代码 复制代码  收藏代码
  1. public class DynamicRoleVoter  implements  
  2.         AccessDecisionVoter {   
  3.   
  4.     @Autowired  
  5.     private ISystemUserService userService;   
  6.   
  7.     private PathMatcher pathMatcher = new AntPathMatcher();   
  8.     /*  
  9.      * (non-Javadoc)  
  10.      *   
  11.      * @see  
  12.      * org.springframework.security.vote.AccessDecisionVoter#supports(java.lang  
  13.      * .Class)  
  14.      */  
  15.     @SuppressWarnings("unchecked")   
  16.     public boolean supports(Class clazz) {   
  17.         return true;   
  18.     }   
  19.   
  20.     /*  
  21.      * (non-Javadoc)  
  22.      *   
  23.      * @seeorg.springframework.security.vote.AccessDecisionVoter#supports(org.  
  24.      * springframework.security.ConfigAttribute)  
  25.      */  
  26.     public boolean supports(ConfigAttribute attribute) {   
  27.         return true;   
  28.     }   
  29.   
  30.     /*  
  31.      * (non-Javadoc)  
  32.      *   
  33.      * @seeorg.springframework.security.vote.AccessDecisionVoter#vote(org.  
  34.      * springframework.security.Authentication, java.lang.Object,  
  35.      * org.springframework.security.ConfigAttributeDefinition)  
  36.      */  
  37.     public int vote(Authentication authentication, Object object,   
  38.             java.util.Collection arg2) {   
  39.         int result = ACCESS_ABSTAIN;   
  40.         if (!(object instanceof FilterInvocation))   
  41.             return result;   
  42.         FilterInvocation invo = (FilterInvocation) object;   
  43.         String url = invo.getRequestUrl();//当前请求的URL   
  44.         Set<GrantedAuthority> authorities = null;   
  45.         String userId = authentication.getName();   
  46.         //获得当前用户的可访问资源,自定义的查询方法,之后和当前请求资源进行匹配,成功则放行,否则拦截       
  47.         authorities = loadUserAuthorities(userService.findById(userId));   
  48.         Map<String, Set<String>> urlAuths = authService.getUrlAuthorities();   
  49.         Set<String> keySet = urlAuths.keySet();   
  50.         for (String key : keySet) {   
  51.             boolean matched = pathMatcher.match(key, url);   
  52.             if (!matched)   
  53.                 continue;   
  54.             Set<String> mappedAuths = urlAuths.get(key);   
  55.             if (contain(authorities, mappedAuths)) {   
  56.                 result = ACCESS_GRANTED;   
  57.                 break;   
  58.             }   
  59.         }   
  60.         return result;   
  61.     }   
  62.        
  63.        
  64.     protected boolean contain(Set<GrantedAuthority> authorities,   
  65.             Set<String> mappedAuths) {   
  66.         if (CollectionUtils.isEmpty(mappedAuths)   
  67.                 || CollectionUtils.isEmpty(authorities))   
  68.             return false;   
  69.         for (GrantedAuthority item : authorities) {   
  70.             if (mappedAuths.contains(item.getAuthority()))   
  71.                 return true;   
  72.         }   
  73.         return false;   
  74.     }   
  75. }  
public class DynamicRoleVoter  implements
		AccessDecisionVoter {

	@Autowired
	private ISystemUserService userService;

	private PathMatcher pathMatcher = new AntPathMatcher();
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.springframework.security.vote.AccessDecisionVoter#supports(java.lang
	 * .Class)
	 */
	@SuppressWarnings("unchecked")
	public boolean supports(Class clazz) {
		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seeorg.springframework.security.vote.AccessDecisionVoter#supports(org.
	 * springframework.security.ConfigAttribute)
	 */
	public boolean supports(ConfigAttribute attribute) {
		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seeorg.springframework.security.vote.AccessDecisionVoter#vote(org.
	 * springframework.security.Authentication, java.lang.Object,
	 * org.springframework.security.ConfigAttributeDefinition)
	 */
	public int vote(Authentication authentication, Object object,
			java.util.Collection arg2) {
		int result = ACCESS_ABSTAIN;
		if (!(object instanceof FilterInvocation))
			return result;
		FilterInvocation invo = (FilterInvocation) object;
		String url = invo.getRequestUrl();//当前请求的URL
		Set<GrantedAuthority> authorities = null;
		String userId = authentication.getName();
		//获得当前用户的可访问资源,自定义的查询方法,之后和当前请求资源进行匹配,成功则放行,否则拦截	
		authorities = loadUserAuthorities(userService.findById(userId));
		Map<String, Set<String>> urlAuths = authService.getUrlAuthorities();
		Set<String> keySet = urlAuths.keySet();
		for (String key : keySet) {
			boolean matched = pathMatcher.match(key, url);
			if (!matched)
				continue;
			Set<String> mappedAuths = urlAuths.get(key);
			if (contain(authorities, mappedAuths)) {
				result = ACCESS_GRANTED;
				break;
			}
		}
		return result;
	}
	
	
	protected boolean contain(Set<GrantedAuthority> authorities,
			Set<String> mappedAuths) {
		if (CollectionUtils.isEmpty(mappedAuths)
				|| CollectionUtils.isEmpty(authorities))
			return false;
		for (GrantedAuthority item : authorities) {
			if (mappedAuths.contains(item.getAuthority()))
				return true;
		}
		return false;
	}
}
 

 

OK。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值