spring security 配置文件小结(逐步深化到url级别)

Java代码 复制代码 收藏代码
  1. 一 、方式一:用户名密码都在配置文件中。   
  2. <?xml version="1.0" encoding="UTF-8"?>   
  3. <beans:beans xmlns="http://www.springframework.org/schema/security"  
  4.     xmlns:beans="http://www.springframework.org/schema/beans"  
  5.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  6.     xsi:schemaLocation="http://www.springframework.org/schema/beans   
  7.     http://www.springframework.org/schema/beans/spring-beans-2.0.xsd   
  8.     http://www.springframework.org/schema/security   
  9.     http://www.springframework.org/schema/security/spring-security-2.0.4.xsd">   
  10.   
  11.     <http auto-config='true'>   
  12.         <intercept-url pattern="/admin.jsp" access="ROLE_ADMIN" />   
  13.         <intercept-url pattern="/**" access="ROLE_USER" />   
  14.     </http>   
  15.   
  16.     <authentication-provider>   
  17.         <user-service>   
  18.             <user name="admin" password="admin" authorities="ROLE_USER, ROLE_ADMIN" />   
  19.             <user name="user" password="user" authorities="ROLE_USER" />   
  20.         </user-service>   
  21.     </authentication-provider>   
  22.   
  23. </beans:beans>   
  24.   
  25.   
  26. 二、方式二:运用spring security 提供的默认表结构,authentication部分修改如下:   
  27.     <authentication-provider>   
  28.         <jdbc-user-service data-source-ref="dataSource"/>   
  29.     </authentication-provider>   
  30.   
  31.     <beans:bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">   
  32.         <beans:property name="driverClassName" value="org.hsqldb.jdbcDriver"/>   
  33.         <beans:property name="url" value="jdbc:hsqldb:res:/hsqldb/test"/>   
  34.         <beans:property name="username" value="sa"/>   
  35.         <beans:property name="password" value=""/>   
  36.     </beans:bean>   
  37.        
  38.        
  39. 三、方式三:运用原先本地的数据库,authentication修改如下:   
  40.     <authentication-provider>   
  41.         <jdbc-user-service data-source-ref="dataSource"  
  42.             users-by-username-query="select username,password,status as enabled   
  43.                                          from user   
  44.                                         where username=?"   
  45.             authorities-by-username-query="select u.username,r.name as authority   
  46.                                              from user u   
  47.                                              join user_role ur   
  48.                                                on u.id=ur.user_id   
  49.                                              join role r   
  50.                                                on r.id=ur.role_id   
  51.                                             where u.username=?"/>   
  52.     </authentication-provider>   
  53.                
  54.  注:   
  55.  users-by-username-query为根据用户名查找用户,系统通过传入的用户名查询当前用户的登录名,密码和是否被禁用这一状态。   
  56.  authorities-by-username-query为根据用户名查找权限,系统通过传入的用户名查询当前用户已被授予的所有权限。   
  57.     
  58. 四、方式四;在方式三的基础上,修改登录页面   
  59. 在xml中的http标签中添加一个form-login标签。   
  60.   
  61. <http auto-config='true'>   
  62.     <intercept-url pattern="/login.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY" />[1]   
  63.     <intercept-url pattern="/admin.jsp" access="ROLE_ADMIN" />   
  64.     <intercept-url pattern="/**" access="ROLE_USER" />   
  65.     <form-login login-page="/login.jsp"[2]   
  66.                 authentication-failure-url="/login.jsp?error=true"[3]   
  67.                 default-target-url="/" />[4]   
  68. </http>   
  69.            
  70.     
  71. 1、让没登陆的用户也可以访问login.jsp。[1]   
  72.   
  73. 这是因为配置文件中的“/**”配置,要求用户访问任意一个系统资源时,必须拥有ROLE_USER角色,/login.jsp也不例外,如果我们不为/login.jsp单独配置访问权限,会造成用户连登陆的权限都没有,这是不正确的。   
  74.     
  75.  2、login-page表示用户登陆时显示我们自定义的login.jsp。[2]   
  76.   
  77. 这时我们访问系统显示的登陆页面将是我们上面创建的login.jsp。   
  78.     
  79.  3、authentication-failure-url表示用户登陆失败时,跳转到哪个页面。[3]   
  80.   
  81. 当用户输入的登录名和密码不正确时,系统将再次跳转到/login.jsp,并添加一个error=true参数作为登陆失败的标示。   
  82.     
  83.     
  84.  4default-target-url表示登陆成功时,跳转到哪个页面。[4]   
  85.     
  86.  五、方式五:使用数据配置角色可以访问的资源(控制到URL级别)(可以参见工程005)   
  87. <!--从配置文件上可以看到,Spring Security所需的数据应该是一系列URL网址和访问这些网址所需的权限:   
  88.   
  89. <intercept-url pattern="/login.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY" />   
  90. <intercept-url pattern="/admin.jsp" access="ROLE_ADMIN" />   
  91. <intercept-url pattern="/**" access="ROLE_USER" />   
  92.                
  93. SpringSecurity所做的就是在系统初始化时,将以上XML中的信息转换为特定的数据格式,而框架中其他组件可以利用这些特定格式的数据,用于控制之后的验证操作。现在这些资源信息都保存在数据库中了,从数据库中取出数据,然后让它等同于从xml文件中取出,需要做以下几步。   
  94. -->   
  95.  1、实现一个符合该功能的类,主要参看该类中1-5步骤,了解即可。   
  96.  <!--   
  97.   
  98. public class JdbcFilterInvocationDefinitionSourceFactoryBean   
  99.     extends JdbcDaoSupport implements FactoryBean {   
  100.     private String resourceQuery;   
  101.   
  102.     public boolean isSingleton() {   
  103.         return true;   
  104.     }   
  105.   
  106.     public Class getObjectType() {   
  107.         return FilterInvocationDefinitionSource.class;   
  108.     }   
  109.     //4、 使用urlMatcher和requestMap创建DefaultFilterInvocationDefinitionSource。   
  110.     public Object getObject() {   
  111.         return new DefaultFilterInvocationDefinitionSource(this  
  112.             .getUrlMatcher(), this.buildRequestMap());   
  113.     }   
  114.     //2、这样我们可以执行它的execute()方法获得所有资源信息。并把它封装到map中。   
  115.     
  116.     protected Map<String, String> findResources() {   
  117.         ResourceMapping resourceMapping = new ResourceMapping(getDataSource(),   
  118.                 resourceQuery);   
  119.   
  120.         Map<String, String> resourceMap = new LinkedHashMap<String, String>();   
  121.   
  122.         for (Resource resource : (List<Resource>) resourceMapping.execute()) {   
  123.             String url = resource.getUrl();   
  124.             String role = resource.getRole();   
  125.   
  126.             if (resourceMap.containsKey(url)) {   
  127.                 String value = resourceMap.get(url);   
  128.                 resourceMap.put(url, value + "," + role);   
  129.             } else {   
  130.                 resourceMap.put(url, role);   
  131.             }   
  132.         }   
  133.   
  134.         return resourceMap;   
  135.     }   
  136.        
  137.        
  138. /*    <intercept-url pattern="/login.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY" />   
  139.     <intercept-url pattern="/admin.jsp" access="ROLE_ADMIN" />   
  140.     <intercept-url pattern="/**" access="ROLE_USER" />*/   
  141.   
  142.     //3、使用获得的资源信息组装requestMap。再把第二步封装到map中的方法进一步加工,使它等价于“如spring从上面模式的配置文件中读取一样”   
  143.     protected LinkedHashMap<RequestKey, ConfigAttributeDefinition> buildRequestMap() {   
  144.         LinkedHashMap<RequestKey, ConfigAttributeDefinition> requestMap = null;   
  145.         requestMap = new LinkedHashMap<RequestKey, ConfigAttributeDefinition>();   
  146.   
  147.         ConfigAttributeEditor editor = new ConfigAttributeEditor();   
  148.   
  149.         Map<String, String> resourceMap = this.findResources();   
  150.   
  151.         for (Map.Entry<String, String> entry : resourceMap.entrySet()) {   
  152.             RequestKey key = new RequestKey(entry.getKey(), null);   
  153.             editor.setAsText(entry.getValue());   
  154.             requestMap.put(key,   
  155.                 (ConfigAttributeDefinition) editor.getValue());   
  156.         }   
  157.   
  158.         return requestMap;   
  159.     }   
  160.   
  161.     protected UrlMatcher getUrlMatcher() {   
  162.         return new AntUrlPathMatcher();   
  163.     }   
  164.   
  165.     public void setResourceQuery(String resourceQuery) {   
  166.         this.resourceQuery = resourceQuery;   
  167.     }   
  168.   
  169.     private class Resource {   
  170.         private String url;   
  171.         private String role;   
  172.   
  173.         public Resource(String url, String role) {   
  174.             this.url = url;   
  175.             this.role = role;   
  176.         }   
  177.   
  178.         public String getUrl() {   
  179.             return url;   
  180.         }   
  181.   
  182.         public String getRole() {   
  183.             return role;   
  184.         }   
  185.     }   
  186.     //1、我们通过定义一个MappingSqlQuery实现数据库操作。   
  187.     private class ResourceMapping extends MappingSqlQuery {   
  188.         protected ResourceMapping(DataSource dataSource,   
  189.             String resourceQuery) {   
  190.             super(dataSource, resourceQuery);   
  191.             compile();   
  192.         }   
  193.   
  194.         protected Object mapRow(ResultSet rs, int rownum)   
  195.             throws SQLException {   
  196.             String url = rs.getString(1);   
  197.             String role = rs.getString(2);   
  198.             Resource resource = new Resource(url, role);   
  199.   
  200.             return resource;   
  201.         }   
  202.     }   
  203. }   
  204.   
  205.  -->   
  206.  2、替换原有功能的切入点   
  207.  在spring中配置我们编写的代码。   
  208.   
  209. <beans:bean id="filterInvocationDefinitionSource"  
  210.     class="com.family168.springsecuritybook.ch005.JdbcFilterInvocationDefinitionSourceFactoryBean">   
  211.     <beans:property name="dataSource" ref="dataSource"/>   
  212.     <beans:property name="resourceQuery" value="   
  213.         select re.res_string,r.name   
  214.           from role r   
  215.           join resc_role rr   
  216.             on r.id=rr.role_id   
  217.           join resc re   
  218.             on re.id=rr.resc_id   
  219.       order by priority   
  220.     "/>   
  221. </beans:bean>   
  222.                
  223. 下一步使用这个filterInvocationDefinitionSource创建filterSecurityInterceptor,并使用它替换系统原来创建的那个过滤器。   
  224.   
  225. <beans:bean id="filterSecurityInterceptor"  
  226.     class="org.springframework.security.intercept.web.FilterSecurityInterceptor" autowire="byType">   
  227.     <custom-filter before="FILTER_SECURITY_INTERCEPTOR" />   
  228.     <beans:property name="objectDefinitionSource" ref="filterInvocationDefinitionSource" />   
  229. </beans:bean>   
  230.                
  231. 注意这个custom-filter标签,它表示将filterSecurityInterceptor放在框架原来的FILTER_SECURITY_INTERCEPTOR过滤器之前,这样我们的过滤器会先于原来的过滤器执行,因为它的功能与老过滤器完全一样,所以这就等于把原来的过滤器替换掉了。   
  232.     
  233.  3、完整的配置文件如下所示:   
  234.   
  235. <?xml version="1.0" encoding="UTF-8"?>   
  236. <beans:beans xmlns="http://www.springframework.org/schema/security"  
  237.     xmlns:beans="http://www.springframework.org/schema/beans"  
  238.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  239.     xsi:schemaLocation="http://www.springframework.org/schema/beans   
  240.     http://www.springframework.org/schema/beans/spring-beans-2.0.xsd   
  241.     http://www.springframework.org/schema/security   
  242.     http://www.springframework.org/schema/security/spring-security-2.0.4.xsd">   
  243.   
  244.     <http auto-config="true"/>   
  245.   
  246.     <authentication-provider>   
  247.         <jdbc-user-service data-source-ref="dataSource"  
  248.             users-by-username-query="select username,password,status as enabled   
  249.                                        from user   
  250.                                       where username=?"   
  251.             authorities-by-username-query="select u.username,r.name as authority   
  252.                                              from user u   
  253.                                              join user_role ur   
  254.                                                on u.id=ur.user_id   
  255.                                              join role r   
  256.                                                on r.id=ur.role_id   
  257.                                             where u.username=?"/>   
  258.     </authentication-provider>   
  259.   
  260.     <beans:bean id="filterSecurityInterceptor"  
  261.         class="org.springframework.security.intercept.web.FilterSecurityInterceptor" autowire="byType">   
  262.         <custom-filter before="FILTER_SECURITY_INTERCEPTOR" />   
  263.         <beans:property name="objectDefinitionSource" ref="filterInvocationDefinitionSource" />   
  264.     </beans:bean>   
  265.   
  266.     <beans:bean id="filterInvocationDefinitionSource"  
  267.         class="com.family168.springsecuritybook.ch05.JdbcFilterInvocationDefinitionSourceFactoryBean">   
  268.         <beans:property name="dataSource" ref="dataSource"/>   
  269.         <beans:property name="resourceQuery" value="   
  270.             select re.res_string,r.name   
  271.               from role r   
  272.               join resc_role rr   
  273.                 on r.id=rr.role_id   
  274.               join resc re   
  275.                 on re.id=rr.resc_id   
  276.           order by priority   
  277.         "/>   
  278.     </beans:bean>   
  279.   
  280.     <beans:bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">   
  281.         <beans:property name="driverClassName" value="org.hsqldb.jdbcDriver"/>   
  282.         <beans:property name="url" value="jdbc:hsqldb:res:/hsqldb/test"/>   
  283.         <beans:property name="username" value="sa"/>   
  284.         <beans:property name="password" value=""/>   
  285.     </beans:bean>   
  286. </beans:beans>   
  287.   
  288.   
  289.  4、允许动态增加某个用户权限。   
  290.  目前存在的问题是,系统会在初始化时一次将所有资源加载到内存中,即使在数据库中修改了资源信息,系统也不会再次去从数据库中读取资源信息。这就造成了每次修改完数据库后,都需要重启系统才能时资源配置生效。   
  291.   
  292. 解决方案是,如果数据库中的资源出现的变化,需要刷新内存中已加载的资源信息时,使用下面代码:   
  293.   
  294. <%@page import="org.springframework.context.ApplicationContext"%>   
  295. <%@page import="org.springframework.web.context.support.WebApplicationContextUtils"%>   
  296. <%@page import="org.springframework.beans.factory.FactoryBean"%>   
  297. <%@page import="org.springframework.security.intercept.web.FilterSecurityInterceptor"%>   
  298. <%@page import="org.springframework.security.intercept.web.FilterInvocationDefinitionSource"%>   
  299. <%   
  300.     ApplicationContext ctx =  WebApplicationContextUtils.getWebApplicationContext(application);   
  301.     FactoryBean factoryBean = (FactoryBean) ctx.getBean("&filterInvocationDefinitionSource");   
  302.     FilterInvocationDefinitionSource fids = (FilterInvocationDefinitionSource) factoryBean.getObject();   
  303.     FilterSecurityInterceptor filter = (FilterSecurityInterceptor) ctx.getBean("filterSecurityInterceptor");   
  304.     filter.setObjectDefinitionSource(fids);   
  305. %>   
  306. <jsp:forward page="/"/>

posted on 2011-09-06 14:22 sichuanxiaohuo 阅读(3526) 评论(0)  编辑  收藏 所属分类: spring


只有注册用户登录后才能发表评论。


网站导航:
 
<2025年7月>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

导航

统计

留言簿

文章分类

文章档案

link

搜索

最新评论