准备:
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 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
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 AccessDecisionManager
15 {
16 /**
17 * Authentication arg0 --->用户具有的角色权限
18 * Collection<ConfigAttribute> arg2 --->访问该资源所需的角色权限
19 */
20 @Override
21 public void decide(Authentication arg0, Object arg1,
22 Collection<ConfigAttribute> arg2) throws AccessDeniedException,
23 InsufficientAuthenticationException
24 {
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 @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
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 implements
18 FilterInvocationSecurityMetadataSource
19 {
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 @Override
45 public Collection<ConfigAttribute> getAllConfigAttributes()
46 {
47 return null;
48 }
49
50 /**
51 * 获取访问某一个url所需的角色
52 */
53 @Override
54 public Collection<ConfigAttribute> getAttributes(Object arg0)
55 throws IllegalArgumentException
56 {
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 @Override
72 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 UserDetailsService
15 {
16 /**
17 * arg0 --->登录的用户名
18 */
19 @Override
20 public UserDetails loadUserByUsername(String arg0)
21 throws UsernameNotFoundException, DataAccessException
22 {
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 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
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 密码: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>