自定义Spring Security过滤器

来源:互联网 发布:js数组的sort 编辑:程序博客网 时间:2024/05/17 07:02

准备:

  1、Spring Security需要自定义一个继承至AbstractSecurityInterceptor的Filter,该抽象类包含了AccessDecisionManager(决策管理器)、AuthenticationManager(身份认证管理器)的setter, 可以通过Spring自动注入,另外,资源角色授权器需要单独自定义注入

  2、AccessDecisionManager(决策管理器)的实现需要实现AccessDecisionManager接口,在实现的decide(Authentication arg0, Object arg1,Collection<ConfigAttribute> arg2)方法中,需要将用户具有的角色权限Collection<GrantedAuthority> grantedAuthorities=arg0.getAuthorities();与访问该资源所需要的金额角色权限Collection<ConfigAttribute> arg2进行比较,若有一个角色匹配,则放行允许该用户访问此资源。

  3、AuthenticationManager(身份认证管理器)可以通过applicationContext-security.xml中<authentication-manager />标签实现。该标签需要引用一个实现了UserDetailService接口的类。该类的loadUserByUsername(String username)方法,通过传进来的用户名返回一个User对象,构造该User对象时需要传入GrantedAuthority的Collection,此时可以通过不同的用户名赋予不同的GrantedAuthority。

  4、资源角色授权器需要实现FilterInvocationSecurityMetadataSource接口。请求的资源所需要的角色权限在服务器启动时候就已经确定的,所以在该实现类的构造方法中需要确定每一种资源需要那些角色权限,通过一个Map<String, List<ConfigAttribute>>即可将所有资源所需要的List<ConfigAttribute>存储起来。该实现类中getAttributes(Object arg0)方法,可以通过请求的url返回对应的Collection<ConfigAttribute>,通过传进来的FilterInvocation可以得到RequestUrl,然后遍历Map<String, List<ConfigAttribute>>。

一、定义继承至AbstractSecurityInterceptor的CustomSecurityFilter。

View Code
复制代码
 1 package com.spring.security.demo; 2  3 import java.io.IOException; 4  5 import javax.servlet.Filter; 6 import javax.servlet.FilterChain; 7 import javax.servlet.FilterConfig; 8 import javax.servlet.ServletException; 9 import javax.servlet.ServletRequest;10 import javax.servlet.ServletResponse;11 12 import org.springframework.security.access.SecurityMetadataSource;13 import org.springframework.security.access.intercept.AbstractSecurityInterceptor;14 import org.springframework.security.access.intercept.InterceptorStatusToken;15 import org.springframework.security.web.FilterInvocation;16 import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;17 18 public class CustomSecurityFilter extends AbstractSecurityInterceptor implements19         Filter20 {21     private FilterInvocationSecurityMetadataSource securityMetadataSource;22 23     public FilterInvocationSecurityMetadataSource getSecurityMetadataSource()24     {25         return securityMetadataSource;26     }27 28     public void setSecurityMetadataSource(29             FilterInvocationSecurityMetadataSource securityMetadataSource)30     {31         this.securityMetadataSource = securityMetadataSource;32     }33 34     @Override35     public void destroy()36     {37         // TODO Auto-generated method stub38 39     }40 41     @Override42     public void doFilter(ServletRequest arg0, ServletResponse arg1,43             FilterChain arg2) throws IOException, ServletException44     {45         FilterInvocation fileInvocation = new FilterInvocation(arg0, arg1, arg2);46         InterceptorStatusToken interceptorStatusToken = this47                 .beforeInvocation(fileInvocation);48         fileInvocation.getChain().doFilter(arg0, arg1);49         this.afterInvocation(interceptorStatusToken, null);50     }51 52     @Override53     public void init(FilterConfig arg0) throws ServletException54     {55         // TODO Auto-generated method stub56 57     }58 59     @Override60     public Class<? extends Object> getSecureObjectClass()61     {62         return FilterInvocation.class;63     }64 65     @Override66     public SecurityMetadataSource obtainSecurityMetadataSource()67     {68         return this.securityMetadataSource;69     }70 71 }
复制代码

 

 

二、定义AccessDecisionManager(决策管理器)、AuthenticationManager(身份认证管理器)、实现了UserDetailService接口的CustomUserDetailService。

CustomAccessDecisionManager.java

View Code
复制代码
 1 package com.spring.security.demo.dependent.components; 2  3 import java.util.Collection; 4 import java.util.Iterator; 5  6 import org.springframework.security.access.AccessDecisionManager; 7 import org.springframework.security.access.AccessDeniedException; 8 import org.springframework.security.access.ConfigAttribute; 9 import org.springframework.security.access.SecurityConfig;10 import org.springframework.security.authentication.InsufficientAuthenticationException;11 import org.springframework.security.core.Authentication;12 import org.springframework.security.core.GrantedAuthority;13 14 public class CustomAccessDecisionManager implements AccessDecisionManager15 {16     /**17      * Authentication arg0 --->用户具有的角色权限 18      * Collection<ConfigAttribute> arg2 --->访问该资源所需的角色权限19      */20     @Override21     public void decide(Authentication arg0, Object arg1,22             Collection<ConfigAttribute> arg2) throws AccessDeniedException,23             InsufficientAuthenticationException24     {25         Iterator<ConfigAttribute> iter = arg2.iterator();26         while (iter.hasNext())27         {28             String accessResourceNeedRole = ((SecurityConfig) iter.next())29                     .getAttribute();30             for (GrantedAuthority grantedAuthority : arg0.getAuthorities())31             {32                 String userOwnRole = grantedAuthority.getAuthority();33                 if (accessResourceNeedRole.equals(userOwnRole))34                 {35                     return;36                 }37             }38         }39         throw new AccessDeniedException("访问被拒绝!");40     }41 42     @Override43     public boolean supports(ConfigAttribute arg0)44     {45         return true;46     }47 48     @Override49     public boolean supports(Class<?> arg0)50     {51         return true;52     }53 54 }
复制代码

CustomFilterInvocationSecurityMetadataSource.java

View Code
复制代码
 1 package com.spring.security.demo.dependent.components; 2  3 import java.util.ArrayList; 4 import java.util.Collection; 5 import java.util.HashMap; 6 import java.util.Iterator; 7 import java.util.List; 8 import java.util.Map; 9 10 import org.springframework.security.access.ConfigAttribute;11 import org.springframework.security.access.SecurityConfig;12 import org.springframework.security.web.FilterInvocation;13 import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;14 import org.springframework.security.web.util.AntUrlPathMatcher;15 import org.springframework.security.web.util.UrlMatcher;16 17 public class CustomFilterInvocationSecurityMetadataSource implements18         FilterInvocationSecurityMetadataSource19 {20     private Map<String, List<ConfigAttribute>> mp;21     private UrlMatcher urlMatcher;22 23     /**24      * 构造每一种资源所需要的角色权限25      */26     public CustomFilterInvocationSecurityMetadataSource()27     {28         super();29         this.mp = new HashMap<String, List<ConfigAttribute>>();30         this.urlMatcher = new AntUrlPathMatcher();31         List<ConfigAttribute> list = new ArrayList<ConfigAttribute>();32         ConfigAttribute cb = new SecurityConfig("Role_ADMIN"); // 构造一个权限(角色)33         ConfigAttribute cbUser = new SecurityConfig("Role_USER"); // 构造一个权限(角色)34         ConfigAttribute cbManager = new SecurityConfig("Role_MANAGER"); // 构造一个权限(角色)35         list.add(cb);36         list.add(cbUser);37         list.add(cbManager);38         39         mp.put("/Main.jsp", list);40         list.remove(2);41         mp.put("/Main2.jsp", list);42     }43 44     @Override45     public Collection<ConfigAttribute> getAllConfigAttributes()46     {47         return null;48     }49 50     /**51      * 获取访问某一个url所需的角色52      */53     @Override54     public Collection<ConfigAttribute> getAttributes(Object arg0)55             throws IllegalArgumentException56     {57         String requestUrl = ((FilterInvocation) arg0).getRequestUrl();58         Iterator<String> iter = this.mp.keySet().iterator();59         while (iter.hasNext())60         {61             String temp = iter.next();62             if (this.urlMatcher.pathMatchesUrl(requestUrl, temp))63             {64                 return mp.get(temp);65             }66         }67 68         return null;69     }70 71     @Override72     public boolean supports(Class<?> arg0)73     {74         return true;75     }76 77 }
复制代码

CustomUserDetailService.java

View Code
复制代码
 1 package com.spring.security.demo.dependent.components; 2  3 import java.util.ArrayList; 4 import java.util.List; 5  6 import org.springframework.dao.DataAccessException; 7 import org.springframework.security.core.GrantedAuthority; 8 import org.springframework.security.core.authority.GrantedAuthorityImpl; 9 import org.springframework.security.core.userdetails.User;10 import org.springframework.security.core.userdetails.UserDetails;11 import org.springframework.security.core.userdetails.UserDetailsService;12 import org.springframework.security.core.userdetails.UsernameNotFoundException;13 14 public class CustomUserDetailService implements UserDetailsService15 {16     /**17      * arg0 --->登录的用户名18      */19     @Override20     public UserDetails loadUserByUsername(String arg0)21             throws UsernameNotFoundException, DataAccessException22     {23         List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();24         GrantedAuthority grantedAuthority = null;25 26         if ("admin".equals(arg0))27         {28             grantedAuthority = new GrantedAuthorityImpl("Role_ADMIN");29         }30         else if ("manager".equals(arg0))31         {32             grantedAuthority = new GrantedAuthorityImpl("Role_MANAGER");33         }34         else35         {36             grantedAuthority = new GrantedAuthorityImpl("Role_USER");37         }38         grantedAuthorities.add(grantedAuthority);39 40         User user = new User(arg0, "123456", true, true, true, true,41                 grantedAuthorities);42 43         return user;44     }45 46 }
复制代码

 

 

三、完成applicationContext-security.xml以及web.xml的配置

applicationContext-security.xml

View Code
复制代码
 1 <beans:beans xmlns="http://www.springframework.org/schema/security" 2     xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 4                         http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd"> 5      6     <!-- 用户验证通过才能授权,若不通过会跳到authentication-failure-url(验证失败页面) 7           若用户验证通过,但没有default-target-url的访问权限,则会跳转至access-denied-page(授权失败页面) --> 8     <http access-denied-page="/AccessDenied.jsp"> 9         <intercept-url pattern="/Login.jsp" filters="none" />10         <logout logout-success-url="/Login.jsp" />11         <form-login login-page="/Login.jsp" default-target-url="/Main.jsp"12             authentication-failure-url="/Login.jsp" />13         <http-basic />14 15         <custom-filter ref="CustomSecurityFilter" before="FILTER_SECURITY_INTERCEPTOR" />16     </http>17 18     <beans:bean id="CustomSecurityFilter"19         class="com.spring.security.demo.CustomSecurityFilter">20 21         <!-- 注入决策管理器 -->22         <beans:property name="accessDecisionManager" ref="CC_AccessDecisionManager"></beans:property>23 24         <!-- 注入资源角色授权管理器 -->25         <beans:property name="securityMetadataSource" ref="CC_SecurityMetadataSource"></beans:property>26 27         <!-- 注入身份认证管理器 -->28         <beans:property name="authenticationManager" ref="CC_AuthenticationManager"></beans:property>29 30     </beans:bean>31 32     <beans:bean id="CC_SecurityMetadataSource"33         class="com.spring.security.demo.dependent.components.CustomFilterInvocationSecurityMetadataSource"></beans:bean>34 35     <beans:bean id="CC_AccessDecisionManager"36         class="com.spring.security.demo.dependent.components.CustomAccessDecisionManager"></beans:bean>37 38     <authentication-manager alias="CC_AuthenticationManager">39         <authentication-provider user-service-ref="AidUserDetailService"></authentication-provider>40     </authentication-manager>41 42     <beans:bean id="AidUserDetailService"43         class="com.spring.security.demo.dependent.components.CustomUserDetailService"></beans:bean>44 </beans:beans>                      
复制代码

web.xml

View Code
复制代码
 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_3_0.xsd" 5     version="3.0"> 6     <listener> 7         <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 8     </listener> 9 10     <context-param>11         <param-name>contextConfigLocation</param-name>12         <param-value>/WEB-INF/applicationContext*.xml</param-value>13     </context-param>14 15     <filter>16         <filter-name>springSecurityFilterChain</filter-name>17         <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>18     </filter>19 20     <filter-mapping>21         <filter-name>springSecurityFilterChain</filter-name>22         <url-pattern>/*</url-pattern>23     </filter-mapping>24 25     <display-name></display-name>26     <welcome-file-list>27         <welcome-file>index.jsp</welcome-file>28     </welcome-file-list>29 </web-app>
复制代码

 

 

四、完成前台测试页面

View Code
复制代码
 1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 <% 3 String path = request.getContextPath(); 4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; 5 %> 6  7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 8 <html> 9 <head>10 <base href="<%=basePath%>">11 12 <title>用户登录</title>13 14 <meta http-equiv="pragma" content="no-cache">15 <meta http-equiv="cache-control" content="no-cache">16 <meta http-equiv="expires" content="0">17 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">18 <meta http-equiv="description" content="This is my page">19 <!--20     <link rel="stylesheet" type="text/css" href="styles.css">21     -->22 23 </head>24 25 <body>26     <div>27         用户名:admin (admin拥有Role_ADMIN角色,其他任意用户拥有Role_USER角色)28         密码:12345629     </div>30     <hr />31     <form action="j_spring_security_check" method="POST"> 32         用户名:<input type="text" name="j_username" /><br />33         密码:<input type="password" name="j_password"><br />34         <input type="submit" value="登录">35     </form>36 </body>37 </html>
复制代码
0 0
原创粉丝点击