`
kong0itey
  • 浏览: 298983 次
社区版块
存档分类
最新评论

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.                 true true , resultAuths);  
  22.           
  23.           
  24.     }  
  25. }  
 

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. }  
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics