spring security3进级篇III

  在spring security3进级篇II中,虽然将用户和权限存入到数据库中,但在配置文件中仍然要对URL地址配置角色进行控制访问,如何将用户,角色,资源存放 到数据库中,进行统一管理,逐步实现RBAC的模型呢,这需要更复杂的实现,这一篇将实现将所有的信息存储到数据库中,但不涉及组,许可等表。

 

1、首先建立数据表

Sql代码   收藏代码
  1. CREATE   DATABASE  IF  NOT  EXISTS spring_securityiii;  
  2. USE spring_securityiii;  
  3.   
  4. --   
  5. -- Definition of table `pub_resources`   
  6. --   
  7.   
  8. DROP   TABLE  IF EXISTS `pub_resources`;  
  9. CREATE   TABLE  `pub_resources` (  
  10.   `id` bigint (20)  NOT   NULL  AUTO_INCREMENT,  
  11.   `resource_name` varchar (50)  NOT   NULL ,  
  12.   `resource_type` varchar (50)  NOT   NULL ,  
  13.   `resource_string` varchar (200)  NOT   NULL ,  
  14.   `resource_enabled` tinyint(1) NOT   NULL ,  
  15.   `resource_desc` varchar (200)  DEFAULT   NULL ,  
  16.   PRIMARY   KEY  (`id`),  
  17.   UNIQUE   KEY  `uk_pub_resource` (`resource_name`)  
  18. ) ENGINE=InnoDB AUTO_INCREMENT=402 DEFAULT  CHARSET=utf8;  
  19.   
  20. --   
  21. -- Dumping data for table `pub_resources`   
  22. --   
  23.   
  24. /*!40000 ALTER   TABLE  `pub_resources` DISABLE KEYS */;  
  25. INSERT   INTO  `pub_resources` (`id`,`resource_name`,`resource_type`,`resource_string`,`resource_enabled`,`resource_desc`)  VALUES    
  26.  (400,'index页面' , 'url' , '/index.*' ,1, 'index页面' ),  
  27.  (401,'admin页面' , 'url' , '/admin.*' ,1, 'admin页面' );  
  28. /*!40000 ALTER   TABLE  `pub_resources` ENABLE KEYS */;  
  29.   
  30.   
  31. --   
  32. -- Definition of table `pub_roles`   
  33. --   
  34.   
  35. DROP   TABLE  IF EXISTS `pub_roles`;  
  36. CREATE   TABLE  `pub_roles` (  
  37.   `id` bigint (20)  NOT   NULL  AUTO_INCREMENT,  
  38.   `role_name` varchar (100)  NOT   NULL ,  
  39.   `role_enabled` tinyint(1) NOT   NULL ,  
  40.   `role_desc` varchar (200)  DEFAULT   NULL ,  
  41.   PRIMARY   KEY  (`id`),  
  42.   UNIQUE   KEY  `uk_pub_role` (`role_name`)  
  43. ) ENGINE=InnoDB AUTO_INCREMENT=202 DEFAULT  CHARSET=utf8;  
  44.   
  45. --   
  46. -- Dumping data for table `pub_roles`   
  47. --   
  48.   
  49. /*!40000 ALTER   TABLE  `pub_roles` DISABLE KEYS */;  
  50. INSERT   INTO  `pub_roles` (`id`,`role_name`,`role_enabled`,`role_desc`)  VALUES    
  51.  (200,'ROLE_ADMIN' ,1, '管理员角色' ),  
  52.  (201,'ROLE_USER' ,1, '普通用户角色' );  
  53. /*!40000 ALTER   TABLE  `pub_roles` ENABLE KEYS */;  
  54.   
  55.   
  56. --   
  57. -- Definition of table `pub_roles_resources`   
  58. --   
  59.   
  60. DROP   TABLE  IF EXISTS `pub_roles_resources`;  
  61. CREATE   TABLE  `pub_roles_resources` (  
  62.   `id` bigint (20)  NOT   NULL  AUTO_INCREMENT,  
  63.   `role_id` bigint (20)  NOT   NULL ,  
  64.   `resource_id` bigint (20)  NOT   NULL ,  
  65.   PRIMARY   KEY  (`id`),  
  66.   KEY  `roles_resources_ibfk_1` (`role_id`),  
  67.   KEY  `roles_resources_ibfk_2` (`resource_id`),  
  68.   CONSTRAINT  `roles_resources_ibfk_1`  FOREIGN   KEY  (`role_id`)  REFERENCES  `pub_roles` (`id`),  
  69.   CONSTRAINT  `roles_resources_ibfk_2`  FOREIGN   KEY  (`resource_id`)  REFERENCES  `pub_resources` (`id`)  
  70. ) ENGINE=InnoDB AUTO_INCREMENT=503 DEFAULT  CHARSET=utf8;  
  71.   
  72. --   
  73. -- Dumping data for table `pub_roles_resources`   
  74. --   
  75.   
  76. /*!40000 ALTER   TABLE  `pub_roles_resources` DISABLE KEYS */;  
  77. INSERT   INTO  `pub_roles_resources` (`id`,`role_id`,`resource_id`)  VALUES    
  78.  (500,200,400),  
  79.  (501,200,401),  
  80.  (502,201,400);  
  81. /*!40000 ALTER   TABLE  `pub_roles_resources` ENABLE KEYS */;  
  82.   
  83.   
  84. --   
  85. -- Definition of table `pub_users`   
  86. --   
  87.   
  88. DROP   TABLE  IF EXISTS `pub_users`;  
  89. CREATE   TABLE  `pub_users` (  
  90.   `id` bigint (20)  NOT   NULL  AUTO_INCREMENT,  
  91.   `user_account` varchar (50)  NOT   NULL ,  
  92.   `user_password` varchar (20)  NOT   NULL ,  
  93.   `user_enabled` tinyint(1) NOT   NULL ,  
  94.   `user_desc` varchar (200)  DEFAULT   NULL ,  
  95.   PRIMARY   KEY  (`id`),  
  96.   UNIQUE   KEY  `uk_pub_user` (`user_account`)  
  97. ) ENGINE=InnoDB AUTO_INCREMENT=102 DEFAULT  CHARSET=utf8;  
  98.   
  99. --   
  100. -- Dumping data for table `pub_users`   
  101. --   
  102.   
  103. /*!40000 ALTER   TABLE  `pub_users` DISABLE KEYS */;  
  104. INSERT   INTO  `pub_users` (`id`,`user_account`,`user_password`,`user_enabled`,`user_desc`)  VALUES    
  105.  (100,'admin' , 'admin' ,1, '管理员' ),  
  106.  (101,'user' , 'user' ,1, '普通用户' );  
  107. /*!40000 ALTER   TABLE  `pub_users` ENABLE KEYS */;  
  108.   
  109.   
  110. --   
  111. -- Definition of table `pub_users_roles`   
  112. --   
  113.   
  114. DROP   TABLE  IF EXISTS `pub_users_roles`;  
  115. CREATE   TABLE  `pub_users_roles` (  
  116.   `id` bigint (20)  NOT   NULL  AUTO_INCREMENT,  
  117.   `user_id` bigint (20)  NOT   NULL ,  
  118.   `role_id` bigint (20)  NOT   NULL ,  
  119.   `ur_enabled` tinyint(1) NOT   NULL ,  
  120.   PRIMARY   KEY  (`id`),  
  121.   KEY  `users_roles_ibfk_1` (`user_id`),  
  122.   KEY  `users_roles_ibfk_2` (`role_id`),  
  123.   CONSTRAINT  `users_roles_ibfk_1`  FOREIGN   KEY  (`user_id`)  REFERENCES  `pub_users` (`id`),  
  124.   CONSTRAINT  `users_roles_ibfk_2`  FOREIGN   KEY  (`role_id`)  REFERENCES  `pub_roles` (`id`)  
  125. ) ENGINE=InnoDB AUTO_INCREMENT=303 DEFAULT  CHARSET=utf8;  
  126.   
  127. --   
  128. -- Dumping data for table `pub_users_roles`   
  129. --   
  130.   
  131. /*!40000 ALTER   TABLE  `pub_users_roles` DISABLE KEYS */;  
  132. INSERT   INTO  `pub_users_roles` (`id`,`user_id`,`role_id`,`ur_enabled`)  VALUES    
  133.  (300,100,200,1),  
  134.  (301,100,201,1),  
  135.  (302,101,201,1);  
  136. /*!40000 ALTER   TABLE  `pub_users_roles` ENABLE KEYS */;  

 2、自定义实现spring security的四个类

 

Java代码   收藏代码
  1. package  com.spring.security.service.impl;  
  2.   
  3. import  javax.annotation.Resource;  
  4.   
  5. import  org.springframework.security.core.userdetails.UserDetails;  
  6. import  org.springframework.security.core.userdetails.UsernameNotFoundException;  
  7. import  org.springframework.stereotype.Service;  
  8.   
  9. import  com.spring.security.dao.UserDao;  
  10. import  com.spring.security.domain.User;  
  11. import  com.spring.security.service.CustomUserDetailsService;  
  12.   
  13. @Service ( "customUserDetailsService" )  
  14. public   class  CustomUserDetailsServiceImpl  implements  CustomUserDetailsService {  
  15.       
  16.     @Resource   
  17.     private  UserDao userDao;  
  18.   
  19.     @Override   
  20.     public  UserDetails loadUserByUsername(String userName) throws  UsernameNotFoundException {  
  21.           
  22.         User user = userDao.findUserByName(userName);  
  23.           
  24.         if  (user ==  null ) {  
  25.             throw   new  UsernameNotFoundException( "用户名"  + userName +  "不存在" );  
  26.         }  
  27.   
  28.         // 因为User已经实现了UserDetails接口,所以直接返回user即可   
  29.         return  user;  
  30.     }  
  31. }  
 
Java代码   收藏代码
  1. package  com.spring.security.service.impl;  
  2.   
  3. import  java.util.Collection;  
  4. import  java.util.Iterator;  
  5.   
  6. import  org.springframework.security.access.AccessDeniedException;  
  7. import  org.springframework.security.access.ConfigAttribute;  
  8. import  org.springframework.security.access.SecurityConfig;  
  9. import  org.springframework.security.authentication.InsufficientAuthenticationException;  
  10. import  org.springframework.security.core.Authentication;  
  11. import  org.springframework.security.core.GrantedAuthority;  
  12. import  org.springframework.stereotype.Service;  
  13.   
  14. import  com.spring.security.service.CustomAccessDecisionManager;  
  15.   
  16. /**  
  17.  * AccessdecisionManager在Spring security中是很重要的。  
  18.  *   
  19.  * 在验证部分简略提过了,所有的Authentication实现需要保存在一个GrantedAuthority对象数组中。 这就是赋予给主体的权限。  
  20.  * GrantedAuthority对象通过AuthenticationManager 保存到  
  21.  * Authentication对象里,然后从AccessDecisionManager读出来,进行授权判断。  
  22.  *   
  23.  * Spring Security提供了一些拦截器,来控制对安全对象的访问权限,例如方法调用或web请求。  
  24.  * 一个是否允许执行调用的预调用决定,是由AccessDecisionManager实现的。 这个 AccessDecisionManager  
  25.  * 被AbstractSecurityInterceptor调用, 它用来作最终访问控制的决定。  
  26.  * 这个AccessDecisionManager接口包含三个方法:  
  27.  *   
  28.  * void decide(Authentication authentication, Object secureObject,  
  29.  * List<ConfigAttributeDefinition> config) throws AccessDeniedException; boolean  
  30.  * supports(ConfigAttribute attribute); boolean supports(Class clazz);  
  31.  *   
  32.  * 从第一个方法可以看出来,AccessDecisionManager使用方法参数传递所有信息,这好像在认证评估时进行决定。  
  33.  * 特别是,在真实的安全方法期望调用的时候,传递安全Object启用那些参数。 比如,让我们假设安全对象是一个MethodInvocation。  
  34.  * 很容易为任何Customer参数查询MethodInvocation,  
  35.  * 然后在AccessDecisionManager里实现一些有序的安全逻辑,来确认主体是否允许在那个客户上操作。  
  36.  * 如果访问被拒绝,实现将抛出一个AccessDeniedException异常。  
  37.  *   
  38.  * 这个 supports(ConfigAttribute) 方法在启动的时候被  
  39.  * AbstractSecurityInterceptor调用,来决定AccessDecisionManager  
  40.  * 是否可以执行传递ConfigAttribute。 supports(Class)方法被安全拦截器实现调用,  
  41.  * 包含安全拦截器将显示的AccessDecisionManager支持安全对象的类型。  
  42.  */   
  43.   
  44. @Service ( "customAccessDecisionManager" )  
  45. public   class  CustomAccessDecisionManagerImpl  implements  CustomAccessDecisionManager {  
  46.   
  47.     /* (non-Javadoc)  
  48.      * @see org.springframework.security.access.AccessDecisionManager#decide(org.springframework.security.core.Authentication, java.lang.Object, java.util.Collection)  
  49.      */   
  50.     public   void  decide(Authentication authentication, Object object,Collection<ConfigAttribute> configAttributes)  
  51.         throws  AccessDeniedException, InsufficientAuthenticationException {  
  52.   
  53.         if  (configAttributes ==  null ) {  
  54.             return ;  
  55.         }  
  56.   
  57.         Iterator<ConfigAttribute> ite = configAttributes.iterator();  
  58.   
  59.         while  (ite.hasNext()) {  
  60.   
  61.             ConfigAttribute ca = ite.next();  
  62.             String needRole = ((SecurityConfig) ca).getAttribute();  
  63.   
  64.             // ga 为用户所被赋予的权限。 needRole 为访问相应的资源应该具有的权限。   
  65.             for  (GrantedAuthority ga : authentication.getAuthorities()) {  
  66.                 if  (needRole.trim().equals(ga.getAuthority().trim())) {  
  67.                     return ;  
  68.                 }  
  69.             }  
  70.         }  
  71.   
  72.         throw   new  AccessDeniedException( "Acess Denied" );  
  73.     }  
  74.   
  75.     /* (non-Javadoc)  
  76.      * @see org.springframework.security.access.AccessDecisionManager#supports(org.springframework.security.access.ConfigAttribute)  
  77.      */   
  78.     public   boolean  supports(ConfigAttribute attribute) {  
  79.   
  80.         return   true ;  
  81.     }  
  82.   
  83.     /* (non-Javadoc)  
  84.      * @see org.springframework.security.access.AccessDecisionManager#supports(java.lang.Class)  
  85.      */   
  86.     public   boolean  supports(Class<?> clazz) {  
  87.   
  88.         return   true ;  
  89.     }  
  90. }  
 
Java代码   收藏代码
  1. package  com.spring.security.service.impl;  
  2.   
  3. import  java.io.IOException;  
  4.   
  5. import  javax.servlet.FilterChain;  
  6. import  javax.servlet.FilterConfig;  
  7. import  javax.servlet.ServletException;  
  8. import  javax.servlet.ServletRequest;  
  9. import  javax.servlet.ServletResponse;  
  10.   
  11. import  org.springframework.security.access.SecurityMetadataSource;  
  12. import  org.springframework.security.access.intercept.AbstractSecurityInterceptor;  
  13. import  org.springframework.security.access.intercept.InterceptorStatusToken;  
  14. import  org.springframework.security.web.FilterInvocation;  
  15. import  org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;  
  16. import  org.springframework.stereotype.Service;  
  17.   
  18. import  com.spring.security.service.CustomFilterSecurityInterceptor;  
  19.   
  20. /** */   
  21. /**  
  22.  * 该过滤器的主要作用就是通过spring著名的IoC生成securityMetadataSource。  
  23.  * securityMetadataSource相当于本包中自定义的MyInvocationSecurityMetadataSourceService。  
  24.  * 该MyInvocationSecurityMetadataSourceService的作用提从数据库提取权限和资源,装配到HashMap中,  
  25.  * 供Spring Security使用,用于权限校验。  
  26.  *   
  27.  */   
  28.   
  29. @Service ( "customFilterSecurityInterceptor" )  
  30. public   class  CustomFilterSecurityInterceptorImpl  extends  AbstractSecurityInterceptor  implements  CustomFilterSecurityInterceptor {  
  31.   
  32.     private  FilterInvocationSecurityMetadataSource securityMetadataSource;  
  33.       
  34.     public   void  setSecurityMetadataSource(  
  35.             FilterInvocationSecurityMetadataSource securityMetadataSource) {  
  36.         this .securityMetadataSource = securityMetadataSource;  
  37.     }  
  38.   
  39.   
  40.     public   void  doFilter(ServletRequest request, ServletResponse response,FilterChain chain)  throws  IOException, ServletException {  
  41.   
  42.         FilterInvocation fi = new  FilterInvocation(request, response, chain);  
  43.         invoke(fi);  
  44.     }  
  45.   
  46.     public  FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {  
  47.           
  48.         return   this .securityMetadataSource;  
  49.     }  
  50.   
  51.     public  Class<?  extends  Object> getSecureObjectClass() {  
  52.           
  53.         return  FilterInvocation. class ;  
  54.     }  
  55.   
  56.     public   void  invoke(FilterInvocation fi)  throws  IOException,ServletException {  
  57.   
  58.         InterceptorStatusToken token = super .beforeInvocation(fi);  
  59.   
  60.         try  {  
  61.             fi.getChain().doFilter(fi.getRequest(), fi.getResponse());  
  62.         } finally  {  
  63.             super .afterInvocation(token,  null );  
  64.         }  
  65.   
  66.     }  
  67.   
  68.     @Override   
  69.     public  SecurityMetadataSource obtainSecurityMetadataSource() {  
  70.         return   this .securityMetadataSource;  
  71.     }  
  72.       
  73.     public   void  destroy() {  
  74.           
  75.     }  
  76.   
  77.     public   void  init(FilterConfig filterconfig)  throws  ServletException {  
  78.   
  79.     }  
  80. }  
 
Java代码   收藏代码
  1. package  com.spring.security.service.impl;  
  2.   
  3. import  java.util.ArrayList;  
  4. import  java.util.Collection;  
  5. import  java.util.HashMap;  
  6. import  java.util.HashSet;  
  7. import  java.util.Iterator;  
  8. import  java.util.List;  
  9. import  java.util.Map;  
  10. import  java.util.Set;  
  11.   
  12. import  javax.annotation.PostConstruct;  
  13. import  javax.servlet.http.HttpServletRequest;  
  14.   
  15. import  org.springframework.security.access.ConfigAttribute;  
  16. import  org.springframework.security.access.SecurityConfig;  
  17. import  org.springframework.security.web.FilterInvocation;  
  18. import  org.springframework.security.web.util.AntPathRequestMatcher;  
  19. import  org.springframework.stereotype.Service;  
  20.   
  21. import  com.spring.security.dao.ResourceDao;  
  22. import  com.spring.security.domain.Resource;  
  23. import  com.spring.security.domain.Role;  
  24. import  com.spring.security.service.CustomInvocationSecurityMetadataSource;  
  25.   
  26. @Service ( "customInvocationSecurityMetadataSource" )  
  27. public   class  CustomInvocationSecurityMetadataSourceImpl  implements  CustomInvocationSecurityMetadataSource {  
  28.   
  29.     @javax .annotation.Resource  
  30.     private  ResourceDao resourceDao;  
  31.   
  32.     private  AntPathRequestMatcher pathMatcher;  
  33.   
  34.     private  HashMap<String, Collection<ConfigAttribute>> resourceMap =  null ;  
  35.   
  36.     /**  
  37.      * 自定义方法,这个类放入到Spring容器后,  
  38.      * 指定init为初始化方法,从数据库中读取资源  
  39.      *   
  40.      */   
  41.     @PostConstruct   
  42.     public   void  init(){  
  43.           
  44.         this .resourceMap =  new  HashMap<String, Collection<ConfigAttribute>>();  
  45.         for  (Resource item : resourceDao.getAllResource()) {  
  46.             resourceMap.put(item.getResource_string(), listToCollection(item.getRoles()));  
  47.         }  
  48.     }  
  49.   
  50.     @Override   
  51.     public  Collection<ConfigAttribute> getAllConfigAttributes() {  
  52.           
  53.         Set<ConfigAttribute> allAttributes = new  HashSet<ConfigAttribute>();  
  54.         for  (Map.Entry<String, Collection<ConfigAttribute>> entry : resourceMap.entrySet()) {  
  55.             allAttributes.addAll(entry.getValue());  
  56.         }  
  57.           
  58.         return  allAttributes;  
  59.     }  
  60.   
  61.     @Override   
  62.     public  Collection<ConfigAttribute> getAttributes(Object object) throws  IllegalArgumentException {  
  63.           
  64.         HttpServletRequest request = ((FilterInvocation) object).getRequest();  
  65.         System.out.println("requestUrl is "  + request.getRequestURI());  
  66.           
  67.         if  (resourceMap ==  null ) {  
  68.             this .loadAllResourcesAndAuthorities();  
  69.         }  
  70.         Iterator<String> it = resourceMap.keySet().iterator();  
  71.           
  72.         while  (it.hasNext()) {  
  73.             String resURL = it.next();  
  74.             pathMatcher = new  AntPathRequestMatcher(resURL);  
  75.             if  (pathMatcher.matches(request)) {  
  76.                 Collection<ConfigAttribute> returnCollection = resourceMap.get(resURL);  
  77.                   
  78.                 return  returnCollection;  
  79.             }  
  80.         }  
  81.           
  82.         return   null ;  
  83.     }  
  84.   
  85.     @Override   
  86.     public   boolean  supports(Class<?> arg0) {  
  87.         // TODO Auto-generated method stub   
  88.         return   true ;  
  89.     }  
  90.   
  91.       
  92.     /**  
  93.      * 自定义方法,将List<Role>集合转换为框架需要的Collection<ConfigAttribute>集合  
  94.      *   
  95.      * @param roles  
  96.      * @return  
  97.      */   
  98.     private  Collection<ConfigAttribute> listToCollection(List<Role> roles) {  
  99.           
  100.         List<ConfigAttribute> list = new  ArrayList<ConfigAttribute>();  
  101.           
  102.         for  (Role role : roles) {  
  103.             list.add(new  SecurityConfig(role.getRole_name()));  
  104.         }  
  105.           
  106.         return  list;  
  107.     }  
  108.       
  109.     /**  
  110.      * 加载所有资源与权限的关系  
  111.      */   
  112.     private   void  loadAllResourcesAndAuthorities() {  
  113.           
  114.         if  (resourceMap ==  null ) {  
  115.             resourceMap = new  HashMap<String, Collection<ConfigAttribute>>();  
  116.         }  
  117.           
  118.         List<Resource> resources = this .resourceDao.getAllResource();  
  119.         for  (Resource resource : resources) {  
  120.             resourceMap.put(resource.getResource_string(),listToCollection(resource.getRoles()));  
  121.         }  
  122.     }  
  123. }  
 

3、定义用户,角色,资源的类

 

Java代码   收藏代码
  1. package  com.spring.security.domain;  
  2.   
  3. import  java.io.Serializable;  
  4. import  java.util.ArrayList;  
  5. import  java.util.List;  
  6.   
  7. /**  
  8.  * Resources  
  9.  */   
  10.   
  11. public   class  Resource  implements  Serializable {  
  12.   
  13.     private   static   final   long  serialVersionUID = 1L;  
  14.       
  15.     private  Integer id;  
  16.     private  String resource_name;  
  17.     private  String resource_type;  
  18.     private  String resource_string;  
  19.     private  String resource_enabled;  
  20.     private  String resource_desc;  
  21.     private  List<Role> roles =  new  ArrayList<Role>();  
  22.   
  23.     public  Integer getId() {  
  24.         return  id;  
  25.     }  
  26.   
  27.     public   void  setId(Integer id) {  
  28.         this .id = id;  
  29.     }  
  30.   
  31.     public  String getResource_name() {  
  32.         return  resource_name;  
  33.     }  
  34.   
  35.     public   void  setResource_name(String resource_name) {  
  36.         this .resource_name = resource_name;  
  37.     }  
  38.   
  39.     public  String getResource_type() {  
  40.         return  resource_type;  
  41.     }  
  42.   
  43.     public   void  setResource_type(String resource_type) {  
  44.         this .resource_type = resource_type;  
  45.     }  
  46.   
  47.     public  String getResource_string() {  
  48.         return  resource_string;  
  49.     }  
  50.   
  51.     public   void  setResource_string(String resource_string) {  
  52.         this .resource_string = resource_string;  
  53.     }  
  54.   
  55.     public  String getResource_enabled() {  
  56.         return  resource_enabled;  
  57.     }  
  58.   
  59.     public   void  setResource_enabled(String resource_enabled) {  
  60.         this .resource_enabled = resource_enabled;  
  61.     }  
  62.   
  63.     public  String getResource_desc() {  
  64.         return  resource_desc;  
  65.     }  
  66.   
  67.     public   void  setResource_desc(String resource_desc) {  
  68.         this .resource_desc = resource_desc;  
  69.     }  
  70.   
  71.     public  List<Role> getRoles() {  
  72.         return  roles;  
  73.     }  
  74.   
  75.     public   void  setRoles(List<Role> roles) {  
  76.         this .roles = roles;  
  77.     }  
  78. }  
 
Java代码   收藏代码
  1. package  com.spring.security.domain;  
  2.   
  3. import  java.io.Serializable;  
  4.   
  5. /**  
  6.  * Roles.  
  7.  */   
  8.   
  9. public   class  Role  implements  Serializable {  
  10.   
  11.     private   static   final   long  serialVersionUID = 1L;  
  12.       
  13.     private  Integer id;  
  14.     private  String role_name;  
  15.     private  Integer role_enabled;  
  16.     private  String role_desc;  
  17.   
  18.     public  Role() {  
  19.     }  
  20.   
  21.     public  Integer getId() {  
  22.         return  id;  
  23.     }  
  24.   
  25.     public   void  setId(Integer id) {  
  26.         this .id = id;  
  27.     }  
  28.   
  29.     public  String getRole_name() {  
  30.         return  role_name;  
  31.     }  
  32.   
  33.     public   void  setRole_name(String role_name) {  
  34.         this .role_name = role_name;  
  35.     }  
  36.   
  37.     public  Integer getRole_enabled() {  
  38.         return  role_enabled;  
  39.     }  
  40.   
  41.     public   void  setRole_enabled(Integer role_enabled) {  
  42.         this .role_enabled = role_enabled;  
  43.     }  
  44.   
  45.     public  String getRole_desc() {  
  46.         return  role_desc;  
  47.     }  
  48.   
  49.     public   void  setRole_desc(String role_desc) {  
  50.         this .role_desc = role_desc;  
  51.     }  
  52. }  
 
Java代码   收藏代码
  1. package  com.spring.security.domain;  
  2.   
  3. import  java.io.Serializable;  
  4. import  java.util.ArrayList;  
  5. import  java.util.Collection;  
  6. import  java.util.List;  
  7.   
  8. import  org.springframework.security.core.GrantedAuthority;  
  9. import  org.springframework.security.core.authority.SimpleGrantedAuthority;  
  10. import  org.springframework.security.core.userdetails.UserDetails;  
  11.   
  12. public   class  User  implements  UserDetails, Serializable {  
  13.   
  14.     private   static   final   long  serialVersionUID = 1L;  
  15.       
  16.     private  Integer id;  
  17.     private  String user_account;  
  18.     private  Integer user_enabled;  
  19.     private  String user_password;  
  20.     private  String user_desc;  
  21.     private  List<Role> roles =  new  ArrayList<Role>();  
  22.   
  23.     public  User() {  
  24.     }  
  25.   
  26.     public  Integer getId() {  
  27.         return  id;  
  28.     }  
  29.   
  30.     public   void  setId(Integer id) {  
  31.         this .id = id;  
  32.     }  
  33.   
  34.     public  String getUser_account() {  
  35.         return  user_account;  
  36.     }  
  37.   
  38.     public   void  setUser_account(String user_account) {  
  39.         this .user_account = user_account;  
  40.     }  
  41.   
  42.     public  Integer getUser_enabled() {  
  43.         return  user_enabled;  
  44.     }  
  45.   
  46.     public   void  setUser_enabled(Integer user_enabled) {  
  47.         this .user_enabled = user_enabled;  
  48.     }  
  49.   
  50.     public  String getUser_password() {  
  51.         return  user_password;  
  52.     }  
  53.   
  54.     public   void  setUser_password(String user_password) {  
  55.         this .user_password = user_password;  
  56.     }  
  57.   
  58.     public  String getUser_desc() {  
  59.         return  user_desc;  
  60.     }  
  61.   
  62.     public   void  setUser_desc(String user_desc) {  
  63.         this .user_desc = user_desc;  
  64.     }  
  65.   
  66.     public  List<Role> getRoles() {  
  67.         return  roles;  
  68.     }  
  69.   
  70.     public   void  setRoles(List<Role> roles) {  
  71.         this .roles = roles;  
  72.     }  
  73.   
  74.     /*  
  75.      * 获取用户权限集合,权限使用GrantedAuthority接口表示,框架中有它的实现类  
  76.      * GrantedAuthorityImpl,只需要把角色的名称放入即可 (non-Javadoc)  
  77.      *   
  78.      * @see  
  79.      * org.springframework.security.core.userdetails.UserDetails#getAuthorities  
  80.      * ()  
  81.      */   
  82.     @Override   
  83.     public  Collection<?  extends  GrantedAuthority> getAuthorities() {  
  84.         List<GrantedAuthority> list = new  ArrayList<GrantedAuthority>();  
  85.         for  (Role role : roles) {  
  86.             list.add(new  SimpleGrantedAuthority(role.getRole_name()));  
  87.         }  
  88.   
  89.         return  list;  
  90.     }  
  91.   
  92.     /*  
  93.      * 获取用户名 (non-Javadoc)  
  94.      *   
  95.      * @see  
  96.      * org.springframework.security.core.userdetails.UserDetails#getUsername()  
  97.      */   
  98.     @Override   
  99.     public  String getUsername() {  
  100.         // TODO Auto-generated method stub   
  101.         return   this .user_account;  
  102.     }  
  103.   
  104.     /*  
  105.      * 用户密码 (non-Javadoc)  
  106.      *   
  107.      * @see  
  108.      * org.springframework.security.core.userdetails.UserDetails#getPassword()  
  109.      */   
  110.     @Override   
  111.     public  String getPassword() {  
  112.         // TODO Auto-generated method stub   
  113.         return   this .user_password;  
  114.     }  
  115.   
  116.     /*  
  117.      * 直接返回true,表示没有过期 (non-Javadoc)  
  118.      *   
  119.      * @see  
  120.      * org.springframework.security.core.userdetails.UserDetails#isAccountNonExpired  
  121.      * ()  
  122.      */   
  123.     @Override   
  124.     public   boolean  isAccountNonExpired() {  
  125.         // TODO Auto-generated method stub   
  126.         return   true ;  
  127.     }  
  128.   
  129.     /*  
  130.      * 直接返回true,表示没有锁定 (non-Javadoc)  
  131.      *   
  132.      * @see  
  133.      * org.springframework.security.core.userdetails.UserDetails#isAccountNonLocked  
  134.      * ()  
  135.      */   
  136.     @Override   
  137.     public   boolean  isAccountNonLocked() {  
  138.         // TODO Auto-generated method stub   
  139.         return   true ;  
  140.     }  
  141.   
  142.     @Override   
  143.     public   boolean  isCredentialsNonExpired() {  
  144.         // TODO Auto-generated method stub   
  145.         return   true ;  
  146.     }  
  147.   
  148.     /*  
  149.      * 是否禁用 (non-Javadoc)  
  150.      *   
  151.      * @see  
  152.      * org.springframework.security.core.userdetails.UserDetails#isEnabled()  
  153.      */   
  154.     @Override   
  155.     public   boolean  isEnabled() {  
  156.         // TODO Auto-generated method stub   
  157.         return   true ;  
  158.     }  
  159. }  

 4 用户,资源,角色DAo类的实现

Java代码   收藏代码
  1. package  com.spring.security.dao.impl;  
  2.   
  3. import  java.sql.ResultSet;  
  4. import  java.sql.SQLException;  
  5. import  java.util.List;  
  6.   
  7. import  org.springframework.jdbc.core.BeanPropertyRowMapper;  
  8. import  org.springframework.jdbc.core.RowMapper;  
  9. import  org.springframework.stereotype.Repository;  
  10.   
  11. import  com.spring.security.dao.UserDao;  
  12. import  com.spring.security.dao.support.SimpleDaoSupport;  
  13. import  com.spring.security.domain.Role;  
  14. import  com.spring.security.domain.User;  
  15.   
  16. @Repository ( "userDao" )  
  17. public   class  UserDaoImpl  extends  SimpleDaoSupport  implements  UserDao {  
  18.   
  19.     @Override   
  20.     public  User findUserByName(String userName) {  
  21.   
  22.         String sql = "SELECT id,user_account,user_enabled,user_password,user_desc FROM pub_users where user_account=?" ;  
  23.           
  24.         return   this .getSimpleJdbcTemplate().queryForObject(sql,  
  25.                 new  UserMapper(), userName);  
  26.     }  
  27.   
  28.     /**  
  29.      * 获取User对象的role列表  
  30.      *   
  31.      * @param userID  
  32.      * @return RoleList  
  33.      */   
  34.     public  List<Role> getRolesByUserID(String userName) {  
  35.   
  36.         String sql = "SELECT r.id,r.role_name,r.role_enabled,r.role_desc FROM pub_users u,pub_roles r,pub_users_roles ur "   
  37.                 + "WHERE u.id=ur.user_id AND r.id=ur.role_id AND u.user_account=?" ;  
  38.   
  39.         return   this .getSimpleJdbcTemplate().query(sql,  
  40.                 BeanPropertyRowMapper.newInstance(Role.class ), userName);  
  41.     }  
  42.   
  43.     /**  
  44.      * 定义UserMapper  
  45.      */   
  46.     protected   class  UserMapper  implements  RowMapper<User> {  
  47.   
  48.         public  User mapRow(ResultSet rs,  int  rowNum)  throws  SQLException {  
  49.             User user = new  User();  
  50.             user.setId(rs.getInt("id" ));  
  51.             user.setUser_account(rs.getString("user_account" ));  
  52.             user.setUser_password(rs.getString("user_password" ));  
  53.             user.setUser_enabled(rs.getInt("user_enabled" ));  
  54.             user.setUser_desc(rs.getString("user_desc" ));  
  55.   
  56.             // 调用上面的方法获取用户所有的权限   
  57.             user.setRoles(getRolesByUserID(rs.getString("user_account" )));  
  58.   
  59.             return  user;  
  60.         }  
  61.     }  
  62. }  
 
Java代码   收藏代码
  1. package  com.spring.security.dao.impl;  
  2.   
  3. import  java.sql.ResultSet;  
  4. import  java.sql.SQLException;  
  5. import  java.util.List;  
  6.   
  7. import  org.springframework.jdbc.core.RowMapper;  
  8. import  org.springframework.stereotype.Repository;  
  9.   
  10. import  com.spring.security.dao.ResourceDao;  
  11. import  com.spring.security.dao.support.SimpleDaoSupport;  
  12. import  com.spring.security.domain.Resource;  
  13. import  com.spring.security.domain.Role;  
  14.   
  15. @Repository ( "resourceDao" )  
  16. public   class  ResourceDaoImpl  extends  SimpleDaoSupport  implements  ResourceDao {  
  17.   
  18.     @Override   
  19.     public  List<Resource> getAllResource() {  
  20.   
  21.         List<Resource> list = null ;  
  22.         String sql = "SELECT * from pub_resources" ;  
  23.         list = this .getSimpleJdbcTemplate().query(sql,  new  RowMapper<Resource>() {  
  24.             public  Resource mapRow(ResultSet rs,  int  arg1)  throws  SQLException {  
  25.                 Resource resource = new  Resource();  
  26.                 resource.setId(rs.getInt("id" ));  
  27.                 resource.setResource_name(rs.getString("resource_name" ));  
  28.                 resource.setResource_type(rs.getString("resource_type" ));  
  29.                 resource.setResource_string(rs.getString("resource_string" ));  
  30.                 resource.setResource_enabled(rs.getString("resource_enabled" ));  
  31.                 resource.setResource_desc(rs.getString("resource_desc" ));  
  32.                 resource.setRoles(getRoleByResourceId(resource.getId()));  
  33.                   
  34.                 return  resource;  
  35.             }  
  36.         });  
  37.           
  38.         return  list;  
  39.     }  
  40.       
  41.     private  List<Role> getRoleByResourceId( int  id) {  
  42.           
  43.         String sql = "SELECT r.id,r.role_name,r.role_enabled,r.role_desc FROM pub_roles r,pub_roles_resources rr WHERE rr.role_id=r.id AND rr.resource_id=?" ;  
  44.         return   this .getSimpleJdbcTemplate().query(sql,  new  RowMapper<Role>() {  
  45.             public  Role mapRow(ResultSet rs,  int  arg1)  throws  SQLException {  
  46.                 Role role = new  Role();  
  47.                 role.setId(rs.getInt("id" ));  
  48.                 role.setRole_name(rs.getString("role_name" ));  
  49.                 role.setRole_enabled(rs.getInt("role_enabled" ));  
  50.                 role.setRole_desc(rs.getString("role_desc" ));  
  51.                   
  52.                 return  role;  
  53.             }  
  54.         }, new  Object[] { id });  
  55.     }  
  56. }  
 

5 spring security的配置如下:

Xml代码   收藏代码
  1. <? xml   version = "1.0"   encoding = "UTF-8" ?>   
  2. < beans:beans   xmlns = "http://www.springframework.org/schema/security"   
  3.     xmlns:beans = "http://www.springframework.org/schema/beans"   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"   
  4.     xsi:schemaLocation ="http://www.springframework.org/schema/beans   
  5.     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
  6.                         http://www.springframework.org/schema/security   
  7.                         http://www.springframework.org/schema/security/spring-security-3.1.xsd">   
  8.   
  9.     < global-method-security   pre-post-annotations = "enabled"   />   
  10.   
  11.     <!--对登录页面不进行拦截,在页面后面加*表示,该页面后面可能会带一些参数 -->   
  12.     < http   pattern = "/login.jsp*"   security = "none"   />   
  13.     < http   pattern = "/common/**"   security = "none"   />   
  14.     < http   pattern = "/js/**"   security = "none"   />   
  15.   
  16.     <!-- 保护应用程序配置一些列的权限问题,当没有权限403返回页面为403.jsp -->   
  17.     < http   auto-config = "true"   access-denied-page = "/common/403.jsp"   use-expressions = "true" >   
  18.         <!-- login-page: 指定登录页面,并指定默认的target访问地址index.jsp -->   
  19.         < form-login   login-page = "/login.jsp"   default-target-url = '/index.jsp'   always-use-default-target = 'true'   />   
  20.         <!-- 配置用户退出的默认返回页面 -->   
  21.         < logout   logout-success-url = "/login.jsp"   />   
  22.         <!-- 会话管理配置 ,设置最多登录一次,二次登录会让第一次登录失效,  
  23.          则设置error-if-maximum-exceeded为false,要求第一次有效设置为true -->   
  24.         < session-management   invalid-session-url = "/common/timeout.jsp" >   
  25.             < concurrency-control   max-sessions = "1"   error-if-maximum-exceeded = "false"   />   
  26.         </ session-management >   
  27.   
  28.         <!-- 将自己的过滤器加入到过滤器链中, 放在FILTER_SECURITY_INTERCEPTOR之前 -->   
  29.         < custom-filter   ref = "customFilterSecurityInterceptor"   before = "FILTER_SECURITY_INTERCEPTOR"   />   
  30.     </ http >   
  31.   
  32.     <!-- 配置自己的拦截器 -->   
  33.     < beans:bean   id = "customFilterSecurityInterceptor"   
  34.         class = "com.spring.security.service.impl.CustomFilterSecurityInterceptorImpl" >   
  35.         < beans:property   name = "authenticationManager"   ref = "autheticationManager" />   
  36.         < beans:property   name = "accessDecisionManager"   ref = "customAccessDecisionManager"   />   
  37.         <!-- resourceService在applicationContext.xml中定义 -->   
  38.         < beans:property   name = "securityMetadataSource"   ref = "customInvocationSecurityMetadataSource"   />   
  39.     </ beans:bean >   
  40.   
  41.     <!--配置认证管理器 -->   
  42.     < authentication-manager   alias = "autheticationManager" >   
  43.         <!-- 使用自定义UserDetailsService -->   
  44.         < authentication-provider   user-service-ref = "customUserDetailsService" >   
  45.             < password-encoder   hash = "md5" />   
  46.         </ authentication-provider >   
  47.     </ authentication-manager >   
  48.       
  49.     < beans:bean   id = "webPrivilegeEvaluator"   class = "org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator" >    
  50.         < beans:constructor-arg   ref = "customFilterSecurityInterceptor" />   
  51.     </ beans:bean >   
  52.       
  53.    <!-- Jcaptcha相关的配置 -->      
  54.     < beans:bean   id = "captchaService"    class = "com.octo.captcha.service.image.DefaultManageableImageCaptchaService" >      
  55.         < beans:property   name = "captchaEngine" >      
  56.             < beans:bean   class = "com.spring.security.jcaptcha.GMailEngine"   />      
  57.         </ beans:property >      
  58.         <!-- 默认生成的图片180秒过期 , 可另行设置 -->       
  59.         < beans:property   name = "minGuarantedStorageDelayInSeconds"   value = "180"   />      
  60.     </ beans:bean >   
  61.       
  62. </ beans:beans >   

 

Xml代码   收藏代码
  1. <? xml   version = "1.0"   encoding = "UTF-8" ?>   
  2. < web-app   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"   
  3.     xmlns = "http://java.sun.com/xml/ns/javaee"   xmlns:web = "http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"   
  4.     xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"   
  5.     id = "WebApp_ID"   version = "2.5" >   
  6.     < display-name > springSecurityIII </ display-name >   
  7.     < context-param >   
  8.         < param-name > log4jConfigLocation </ param-name >   
  9.         < param-value > classpath:log4j.xml </ param-value >   
  10.     </ context-param >   
  11.     < context-param >   
  12.         < param-name > log4jRefreshInterval </ param-name >   
  13.         < param-value > 60000 </ param-value >   
  14.     </ context-param >   
  15.     < context-param >   
  16.         < param-name > contextConfigLocation </ param-name >   
  17.         < param-value > classpath:applicationContext.xml </ param-value >   
  18.     </ context-param >   
  19.     < listener >   
  20.         < listener-class > org.springframework.web.util.Log4jConfigListener </ listener-class >   
  21.     </ listener >   
  22.     < listener >   
  23.         < listener-class > org.springframework.web.context.ContextLoaderListener </ listener-class >   
  24.     </ listener >   
  25.     < listener >   
  26.         < listener-class > org.springframework.web.util.IntrospectorCleanupListener </ listener-class >   
  27.     </ listener >   
  28.     < filter >   
  29.         < filter-name > CharacterEncodingFilter </ filter-name >   
  30.         < filter-class > org.springframework.web.filter.CharacterEncodingFilter </ filter-class >   
  31.         < init-param >   
  32.             < param-name > encoding </ param-name >   
  33.             < param-value > UTF-8 </ param-value >   
  34.         </ init-param >   
  35.         < init-param >   
  36.             < param-name > forceEncoding </ param-name >   
  37.             < param-value > true </ param-value >   
  38.         </ init-param >   
  39.     </ filter >   
  40.     < filter-mapping >   
  41.         < filter-name > CharacterEncodingFilter </ filter-name >   
  42.         < url-pattern > /* </ url-pattern >   
  43.     </ filter-mapping >   
  44.       
  45.     < session-config >   
  46.         < session-timeout > 30 </ session-timeout >   
  47.     </ session-config >   
  48.       
  49.     <!-- JCaptcha`s filter -->   
  50.     < filter >   
  51.         < filter-name > jcaptchaFilter </ filter-name >   
  52.         < filter-class > com.spring.security.jcaptcha.JCaptchaFilter </ filter-class >   
  53.         < init-param >   
  54.             < param-name > failureUrl </ param-name >   
  55.             < param-value > /login.jsp </ param-value >   
  56.         </ init-param >   
  57.     </ filter >   
  58.       
  59.     <!-- jcaptcha图片生成URL. -->   
  60.     < filter-mapping >   
  61.         < filter-name > jcaptchaFilter </ filter-name >   
  62.         < url-pattern > /jcaptcha.jpg </ url-pattern >   
  63.     </ filter-mapping >   
  64.       
  65.     <!-- jcaptcha登录表单处理URL. 必须放在springSecurityFilter的filter-mapping定义之前 -->   
  66.     < filter-mapping >   
  67.         < filter-name > jcaptchaFilter </ filter-name >   
  68.         < url-pattern > /j_spring_security_check </ url-pattern >   
  69.     </ filter-mapping >   
  70.       
  71.     < filter >   
  72.         < filter-name > springSecurityFilterChain </ filter-name >   
  73.         < filter-class > org.springframework.web.filter.DelegatingFilterProxy </ filter-class >   
  74.     </ filter >   
  75.     < filter-mapping >   
  76.         < filter-name > springSecurityFilterChain </ filter-name >   
  77.         < url-pattern > /* </ url-pattern >   
  78.     </ filter-mapping >   
  79.       
  80.     < listener >   
  81.         < listener-class > org.springframework.security.web.session.HttpSessionEventPublisher </ listener-class >   
  82.     </ listener >   
  83.   
  84.     < welcome-file-list >   
  85.         < welcome-file > index.jsp </ welcome-file >   
  86.     </ welcome-file-list >   
  87. </ web-app >   
 

 

 

6、其他页面保持不变,进行访问页面如下:

 


spring security3进级篇III_第1张图片
 
spring security3进级篇III_第2张图片
 admin用户点击admin页面


spring security3进级篇III_第3张图片
 切换user用户登入页面进入

 


spring security3进级篇III_第4张图片
 点击admin页面,用户访问被拒绝


spring security3进级篇III_第5张图片

总结: 这种方法虽然将用户、角色、资源存放到数据库中,但spring security 中<sec:authorize url> tag 的隐藏功能消失,这需要自己去定义类似标签去自行控制。

 

要想在真正在企业中做到很好的控制,其设计会更复杂,下面是基于RBAC设计的数据库

 


spring security3进级篇III_第6张图片

你可能感兴趣的:(spring,Security)