准备:
1、Spring Security需要自定义一个继承至AbstractSecurityInterceptor的Filter,该抽象类包含了AccessDecisionManager(决策管理器)、AuthenticationManager(身份认证管理器)的setter, 可以通过Spring自动注入,另外,资源角色授权器需要单独自定义注入
2、AccessDecisionManager(决策管理器)的实现需要实现AccessDecisionManager接口,在实现的decide(Authentication arg0, Object arg1,Collection
3、AuthenticationManager(身份认证管理器)可以通过applicationContext-security.xml中
4、资源角色授权器需要实现FilterInvocationSecurityMetadataSource接口。请求的资源所需要的角色权限在服务器启动时候就已经确定的,所以在该实现类的构造方法中需要确定每一种资源需要那些角色权限,通过一个Map
一、定义继承至AbstractSecurityInterceptor的CustomSecurityFilter。
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 implements 19 Filter 20 { 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 @Override 35 public void destroy() 36 { 37 // TODO Auto-generated method stub 38 39 } 40 41 @Override 42 public void doFilter(ServletRequest arg0, ServletResponse arg1, 43 FilterChain arg2) throws IOException, ServletException 44 { 45 FilterInvocation fileInvocation = new FilterInvocation(arg0, arg1, arg2); 46 InterceptorStatusToken interceptorStatusToken = this 47 .beforeInvocation(fileInvocation); 48 fileInvocation.getChain().doFilter(arg0, arg1); 49 this.afterInvocation(interceptorStatusToken, null); 50 } 51 52 @Override 53 public void init(FilterConfig arg0) throws ServletException 54 { 55 // TODO Auto-generated method stub 56 57 } 58 59 @Override 60 public Class extends Object> getSecureObjectClass() 61 { 62 return FilterInvocation.class; 63 } 64 65 @Override 66 public SecurityMetadataSource obtainSecurityMetadataSource() 67 { 68 return this.securityMetadataSource; 69 } 70 71 }
二、定义AccessDecisionManager(决策管理器)、AuthenticationManager(身份认证管理器)、实现了UserDetailService接口的CustomUserDetailService。
CustomAccessDecisionManager.java
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 AccessDecisionManager 15 { 16 /** 17 * Authentication arg0 --->用户具有的角色权限 18 * Collectionarg2 --->访问该资源所需的角色权限 19 */ 20 @Override 21 public void decide(Authentication arg0, Object arg1, 22 Collectionarg2) throws AccessDeniedException, 23 InsufficientAuthenticationException 24 { 25 Iterator 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 @Override 43 public boolean supports(ConfigAttribute arg0) 44 { 45 return true; 46 } 47 48 @Override 49 public boolean supports(Class> arg0) 50 { 51 return true; 52 } 53 54 }
CustomFilterInvocationSecurityMetadataSource.java
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 implements 18 FilterInvocationSecurityMetadataSource 19 { 20 private Map> mp; 21 private UrlMatcher urlMatcher; 22 23 /** 24 * 构造每一种资源所需要的角色权限 25 */ 26 public CustomFilterInvocationSecurityMetadataSource() 27 { 28 super(); 29 this.mp = new HashMap >(); 30 this.urlMatcher = new AntUrlPathMatcher(); 31 List list = new ArrayList (); 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 @Override 45 public Collection getAllConfigAttributes() 46 { 47 return null; 48 } 49 50 /** 51 * 获取访问某一个url所需的角色 52 */ 53 @Override 54 public Collection getAttributes(Object arg0) 55 throws IllegalArgumentException 56 { 57 String requestUrl = ((FilterInvocation) arg0).getRequestUrl(); 58 Iterator 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 @Override 72 public boolean supports(Class> arg0) 73 { 74 return true; 75 } 76 77 }
CustomUserDetailService.java
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 UserDetailsService 15 { 16 /** 17 * arg0 --->登录的用户名 18 */ 19 @Override 20 public UserDetails loadUserByUsername(String arg0) 21 throws UsernameNotFoundException, DataAccessException 22 { 23 ListgrantedAuthorities = new ArrayList (); 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 else 35 { 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
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 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
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.ContextLoaderListenerlistener-class> 8 listener> 9 10 <context-param> 11 <param-name>contextConfigLocationparam-name> 12 <param-value>/WEB-INF/applicationContext*.xmlparam-value> 13 context-param> 14 15 <filter> 16 <filter-name>springSecurityFilterChainfilter-name> 17 <filter-class>org.springframework.web.filter.DelegatingFilterProxyfilter-class> 18 filter> 19 20 <filter-mapping> 21 <filter-name>springSecurityFilterChainfilter-name> 22 <url-pattern>/*url-pattern> 23 filter-mapping> 24 25 <display-name>display-name> 26 <welcome-file-list> 27 <welcome-file>index.jspwelcome-file> 28 welcome-file-list> 29 web-app>
四、完成前台测试页面
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 22 23 head> 24 25 <body> 26 <div> 27 用户名:admin (admin拥有Role_ADMIN角色,其他任意用户拥有Role_USER角色) 28 密码:123456 29 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>