zoukankan      html  css  js  c++  java
  • spring security总结 太有用了!!

    转至: http://www.cnblogs.com/yl2755/archive/2012/04/19/2456823.html
    谢谢作者!!!

    首先导入spring security所需要的jar包 
    spring-security-core-2.0.5.RELEASE.jar 
    spring-security-core-tiger-2.0.5.RELEASE.jar 
    一.配置过滤器 
    在web.xml中定义如下过滤器 
       
            springSecurityFilterChai
            org.springframework.web.filter.DelegatingFilterProxy 
         
         
            springSecurityFilterChai
             
    CREATE TABLE `t_account` ( 
      `id` int(11) NOT NULL, 
      `username` varchar(255) default NULL, 
      `password` varchar(255) default NULL, 
      `enabled` int default NULL,  
      PRIMARY KEY  (`id`) 
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
         
        CREATE TABLE `t_role` ( 
      `id` int(11) NOT NULL, 
      `name` varchar(255) default NULL,  
      `descn` varchar(255) default NULL,  
      PRIMARY KEY  (`id`) 
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

     
    CREATE TABLE `t_account_role` ( 
      `a_id` int(11) NOT NULL, 
      `r_id` int(11) NOT NULL, 
      PRIMARY KEY  (`a_id`,`r_id`), 
      KEY `FK1C2BC9332D31C656` (`r_id`), 
      KEY `FK1C2BC93371CCC630` (`a_id`), 
      CONSTRAINT `FK1C2BC93384B0A30E` FOREIGN KEY (`a_id`) REFERENCES `t_account` (`id`), 
      CONSTRAINT `FK1C2BC9332D31C656` FOREIGN KEY (`r_id`) REFERENCES `t_role` (`id`) 
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

     
    insert into t_account values(1,'zhangsan','123',1); 
    insert into t_account values(2,'lisi','321',1); 

    insert into t_role values(1,'系统管理员','ROLE_ADMIN'); 
    insert into t_role values(2,'普通用户','ROLE_USER'); 

    insert into t_account_role values(1,2); 
        insert into t_account_role values(2,1); 
        
    当用户登录时,spring security首先判断用户是否可以登录。用户登录后spring security获得该用户的 
    所有权限以判断用户是否可以访问资源。 

    spring配置文件中定义 
     
           
            users-by-username-query="select username,password,enabled from t_account where username=?" 
            authorities-by-username-query="select r.descn from t_account_role ar join 
             t_account a on ar.a_id=a.id join t_role r on ar.r_id=r.id where a.username=?"/> 
         
        
        users-by-username-query:根据用户名查找用户 
        authorities-by-username-query:根据用户名查找这个用户所有的角色名,将用户访问的URL地址和 
        查询结果与标签进行匹配。 
        匹配成功就允许访问,否则就返回到提示页面。 

        
        在标签中添加登录页面等信息 
         
           
             
            CREATE TABLE `t_account` ( 
      `id` int(11) NOT NULL, 
      `username` varchar(255) default NULL, 
      `password` varchar(255) default NULL, 
      `enabled` int default NULL,  
      PRIMARY KEY  (`id`) 
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
         
        CREATE TABLE `t_role` ( 
      `id` int(11) NOT NULL, 
      `name` varchar(255) default NULL,  
      `descn` varchar(255) default NULL,  
      PRIMARY KEY  (`id`) 
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

     
    CREATE TABLE `t_account_role` ( 
      `a_id` int(11) NOT NULL, 
      `r_id` int(11) NOT NULL, 
      PRIMARY KEY  (`a_id`,`r_id`), 
      KEY `FK1C2BC9332D31C656` (`r_id`), 
      KEY `FK1C2BC93371CCC630` (`a_id`), 
      CONSTRAINT `FK1C2BC93384B0A30E` FOREIGN KEY (`a_id`) REFERENCES `t_account` (`id`), 
      CONSTRAINT `FK1C2BC9332D31C656` FOREIGN KEY (`r_id`) REFERENCES `t_role` (`id`) 
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
     
    CREATE TABLE `t_module` ( 
      `id` int(11) NOT NULL, 
      `name` varchar(255) default NULL, 
      `address` varchar(255) default NULL, 
      PRIMARY KEY  (`id`) 
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

     
    CREATE TABLE `t_module_role` ( 
      `m_id` int(11) NOT NULL, 
      `r_id` int(11) NOT NULL, 
      PRIMARY KEY  (`m_id`,`r_id`), 
      KEY `FKA713071E2D31C656` (`r_id`), 
      KEY `FKA713071ED78C9071` (`m_id`), 
      CONSTRAINT `FKA713071ED78C9071` FOREIGN KEY (`m_id`) REFERENCES `t_module` (`id`), 
      CONSTRAINT `FKA713071E2D31C656` FOREIGN KEY (`r_id`) REFERENCES `t_role` (`id`) 
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

     
    insert into t_account values(1,'zhangsan','123',1); 
    insert into t_account values(2,'lisi','321',1); 

    insert into t_role values(1,'系统管理员','ROLE_ADMIN'); 
    insert into t_role values(2,'普通用户','ROLE_USER'); 

    insert into t_account_role values(1,2); 
        insert into t_account_role values(2,1); 
        
        insert into t_module values(1,'部门管理','/dept.jsp'); 
        insert into t_module values(2,'人员管理','/emp.jsp'); 
        
        insert into `t_module_role` values(1,1); 
        insert into `t_module_role` values(1,2); 
        insert into `t_module_role` values(2,1); 
        
    1.在自定义的过滤器中获取资源的URL地址和角色名以取代spring配置文件中原有的 
        过滤器代码: 
    import java.sql.ResultSet; 
    import java.sql.SQLException; 

    import java.util.LinkedHashMap; 
    import java.util.List; 
    import java.util.Map; 

    import javax.sql.DataSource; 

    import org.springframework.beans.factory.FactoryBean; 

    import org.springframework.jdbc.core.support.JdbcDaoSupport; 
    import org.springframework.jdbc.object.MappingSqlQuery; 

    import org.springframework.security.ConfigAttributeDefinition; 
    import org.springframework.security.ConfigAttributeEditor; 
    import org.springframework.security.intercept.web.DefaultFilterInvocationDefinitionSource; 
    import org.springframework.security.intercept.web.FilterInvocationDefinitionSource; 
    import org.springframework.security.intercept.web.RequestKey; 
    import org.springframework.security.util.AntUrlPathMatcher; 
    import org.springframework.security.util.UrlMatcher; 


    public class JdbcFilterInvocationDefinitionSourceFactoryBean 
        extends JdbcDaoSupport implements FactoryBean { 
        private String resourceQuery; 

        public boolean isSingleton() { 
            return true; 
       

        public Class getObjectType() { 
            return FilterInvocationDefinitionSource.class; 
       

        public Object getObject() { 
            return new DefaultFilterInvocationDefinitionSource(this 
                .getUrlMatcher(), this.buildRequestMap()); 
       

        protected Map findResources() { 
            ResourceMapping resourceMapping = new ResourceMapping(getDataSource(), 
                    resourceQuery); 

            Map resourceMap = new LinkedHashMap(); 

            for (Resource resource : (List) resourceMapping.execute()) { 
                String url = resource.getUrl(); 
                String role = resource.getRole(); 

                if (resourceMap.containsKey(url)) { 
                    String value = resourceMap.get(url); 
                    resourceMap.put(url, value + "," + role); 
                } else { 
                    resourceMap.put(url, role); 
               
           

            return resourceMap; 
       

        protected LinkedHashMap buildRequestMap() { 
            LinkedHashMap requestMap = null; 
            requestMap = new LinkedHashMap(); 

            ConfigAttributeEditor editor = new ConfigAttributeEditor(); 

            Map resourceMap = this.findResources(); 

            for (Map.Entry entry : resourceMap.entrySet()) { 
                RequestKey key = new RequestKey(entry.getKey(), null); 
                editor.setAsText(entry.getValue()); 
                requestMap.put(key, 
                    (ConfigAttributeDefinition) editor.getValue()); 
           

            return requestMap; 
       

        protected UrlMatcher getUrlMatcher() { 
            return new AntUrlPathMatcher(); 
       

        public void setResourceQuery(String resourceQuery) { 
            this.resourceQuery = resourceQuery; 
       

        private class Resource { 
            private String url; 
            private String role; 

            public Resource(String url, String role) { 
                this.url = url; 
                this.role = role; 
           

            public String getUrl() { 
                return url; 
           

            public String getRole() { 
                return role; 
           
       

        private class ResourceMapping extends MappingSqlQuery { 
            protected ResourceMapping(DataSource dataSource, 
                String resourceQuery) { 
                super(dataSource, resourceQuery); 
                compile(); 
           

            protected Object mapRow(ResultSet rs, int rownum) 
                throws SQLException { 
                String url = rs.getString(1); 
                String role = rs.getString(2); 
                Resource resource = new Resource(url, role); 
                
                return resource; 
           
       


    将自定义的过滤器放入到原有的spring security过滤器链中(在spring配置文件中配置) 
    定义自定义过滤器(sql语句用于查询资源的URL地址 如:/index.jsp 和角色名 如ROLE_USER) 

            class="com.lovo.JdbcFilterInvocationDefinitionSourceFactoryBean"> 
             
                        select m.address,r.descn 
    from t_module_role mr 
    join t_module m on mr.m_id=m.id 
    join t_role r on mr.r_id=r.id; 
            "/> 
         
      将自定义过滤器放入过滤器链中 
     
            class="org.springframework.security.intercept.web.FilterSecurityInterceptor" > 
             
             
         
        注意:FilterSecurityInterceptor过滤器会向request中写入一个标记,用于标记是否已经控制了当前请求,以避免对同一请求多次处理,导致第2个FilterSecurityInterceptor不会再次执行。 
        在中不需要再定义,如下: 
         
           
                        authentication-failure-url="/error.jsp" 
                        default-target-url="/index.jsp" /> 
                        
         
        自定义的过滤器就从配置文件中读取sql,查询结果就是角色和资源,用户登录时就在session中保存了用户的角色。 
        注意:intercept-url的先后顺序,spring security使用第一个能匹配的intercept-url标签进行权限控制。 
        现在intercept-url来源于数据库,所以在sql查询时注意角色和资源的顺序。 
        建议在角色和资源的中间表中添加1个字段用于标识顺序,(按从严到宽的顺序) 
        表结构修改如下: 
         
    CREATE TABLE `t_module_role` ( 
      `m_id` int(11) NOT NULL, 
      `r_id` int(11) NOT NULL, 
      `priority` int(11) default NULL,  
      PRIMARY KEY  (`m_id`,`r_id`), 
      KEY `FKA713071E2D31C656` (`r_id`), 
      KEY `FKA713071ED78C9071` (`m_id`), 
      CONSTRAINT `FKA713071ED78C9071` FOREIGN KEY (`m_id`) REFERENCES `t_module` (`id`), 
      CONSTRAINT `FKA713071E2D31C656` FOREIGN KEY (`r_id`) REFERENCES `t_role` (`id`) 
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

    数据如下: 
    insert into t_account values(1,'zhangsan','123',1); 
    insert into t_account values(2,'lisi','321',1); 

    insert into t_role values(1,'系统管理员','ROLE_ADMIN'); 
    insert into t_role values(2,'普通用户','ROLE_USER'); 

    insert into t_account_role values(1,2); 
        insert into t_account_role values(2,1); 
        
        insert into t_module values(1,'部门管理','/dept.jsp'); 
        insert into t_module values(2,'人员管理','/emp.jsp'); 
        
        insert into `t_module_role` values(1,1,3); 
        insert into `t_module_role` values(1,2,2); 
        insert into `t_module_role` values(2,1,1); 
        
        自定义过滤器修改如下: 
       
            class="com.lovo.JdbcFilterInvocationDefinitionSourceFactoryBean"> 
             
                        select m.address,r.descn 
    from t_module_role mr 
    join t_module m on mr.m_id=m.id 
    join t_role r on mr.r_id=r.id 
    order by mr.priority 
            "/> 
         
        
        如果持久层使用的是hibernate,那么只需要给自定义过滤器注入1个hibernateTemplate. 
        在自定义过滤器中就不需要再使用mapRow的方式。而是直接获取url和角色名即可。 
        例如: 
        public class ModuleFilter implements FactoryBean { 
    private String resourceQuery; 

        public boolean isSingleton() { 
            return true; 
       

        public Class getObjectType() { 
            return FilterInvocationDefinitionSource.class; 
       

        public Object getObject() { 
            return new DefaultFilterInvocationDefinitionSource(this 
                .getUrlMatcher(), this.buildRequestMap()); 
       

        protected Map findResources() { 
            ResourceMapping resourceMapping = new ResourceMapping(); 

            Map resourceMap = new LinkedHashMap(); 

            for (Resource resource : (List) resourceMapping.execute()) { 
                String url = resource.getUrl(); 
                String role = resource.getRole(); 

                if (resourceMap.containsKey(url)) { 
                    String value = resourceMap.get(url); 
                    resourceMap.put(url, value + "," + role); 
                } else { 
                    resourceMap.put(url, role); 
               
           

            return resourceMap; 
       

        protected LinkedHashMap buildRequestMap() { 
            LinkedHashMap requestMap = null; 
            requestMap = new LinkedHashMap(); 

            ConfigAttributeEditor editor = new ConfigAttributeEditor(); 

            Map resourceMap = this.findResources(); 

            for (Map.Entry entry : resourceMap.entrySet()) { 
                RequestKey key = new RequestKey(entry.getKey(), null); 
                editor.setAsText(entry.getValue()); 
                requestMap.put(key, 
                    (ConfigAttributeDefinition) editor.getValue()); 
           

            return requestMap; 
       

        protected UrlMatcher getUrlMatcher() { 
            return new AntUrlPathMatcher(); 
       

        public void setResourceQuery(String resourceQuery) { 
            this.resourceQuery = resourceQuery; 
       

        private class Resource { 
            private String url; 
            private String role; 

            public Resource(String url, String role) { 
                this.url = url; 
                this.role = role; 
           

            public String getUrl() { 
                return url; 
           

            public String getRole() { 
                return role; 
           
       

        private class ResourceMapping{ 
            public List execute(){ 
            List rlist = new ArrayList(); 
            List list = hibernateTemplate.find(resourceQuery); 
            for(int i=0;i
            Role role = list.get(i); 
            Set set = role.getModuleSet(); 
            Iterator it = set.iterator(); 
            while(it.hasNext()){ 
            Module m = it.next(); 
            Resource re = new Resource(m.getUrl(),role.getDescn()); 
            rlist.add(re); 
           
           
    return rlist; 
           
       

        public void setHibernateTemplate(HibernateTemplate hibernateTemplate) { 
    this.hibernateTemplate = hibernateTemplate; 


    private HibernateTemplate hibernateTemplate; 

    而从灵活性的角度考虑,把hql写在配置文件中 
     
            
             value="from com.lovo.po.Role order by ind"> 
              
              
              
         
        
        问题:系统只会在初始化的时候从数据库中加载信息。无法识别数据库中信息的改变。 
        解决:每个jsp页面上重新内存 
        代码:每个jsp页面include如下代码: 

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    media Queries实现一个响应式的菜单
    跨域资源共享(CORS)在ASP.NET Web API中是如何实现的?
    Media Formatters媒体格式化器
    Winform系列
    node-webkit入门
    WCF 自承载
    HttpClient的使用-爬虫学习1
    为什么程序员的工作效率跟他们的工资不成比例(转)
    大师们都是怎么撑场面的(转)
    马云关于企业发展的一些看法
  • 原文地址:https://www.cnblogs.com/ubuntuvim/p/4796542.html
Copyright © 2011-2022 走看看