Spring Security3详细配置

Spring Security3详细配置

表名:RESOURCE 解释:资源表
备注: 资源表

RESOURCE(资源表)

是否主键

字段名

字段描述

数据类型

长度

可空

约束

缺省值

备注

ID

id

INT(11)

11

TYPE

类型(URL,METHOD)

VARCHAR(50)

50

VALUE

URL

VARCHAR(50)

50

MODEL_NAME

模块名

VARCHAR(50)

50

PARENT_ID

父模块ID

VARCHAR(50)

50

 


表名:ROLE 解释:角色表
备注: 角色表

ROLE(角色表)

是否主键

字段名

字段描述

数据类型

长度

可空

约束

缺省值

备注

ID

id

INT(11)

11

NAME

角色名

VARCHAR(50)

50

DESCRIPTION

角色描述

VARCHAR(50)

50

 


表名:ROLE_RESOURCE 解释:角色资源表
备注: 角色资源表

ROLE_RESOURCE(角色资源表)

是否主键

字段名

字段描述

数据类型

长度

可空

约束

缺省值

备注

ROLE_ID

角色ID

VARCHAR(50)

50

RESOURCE_ID

资源ID

VARCHAR(50)

50

 


表名:USER 解释:用户表
备注: 用户表

USER(用户表)

是否主键

字段名

字段描述

数据类型

长度

可空

约束

缺省值

备注

NAME

用户名

VARCHAR(50)

50

PASSWORD

密码

VARCHAR(50)

50

DISABLED

是否有效

CHAR(1)

1

EMAIL

邮箱

VARCHAR(100)

100

 


表名:USER_ROLE 解释:用户角色表
备注: 用户角色表

USER_ROLE(用户角色表)

是否主键

字段名

字段描述

数据类型

长度

可空

约束

缺省值

备注

USER_ID

用户ID

VARCHAR(50)

50

ROLE_ID

角色ID

VARCHAR(50)

50

相关的jar包可到spring官网下载,我使用的是spring security 3.1.3

首先web.xml配置

  1. <context-param>  
  2. <param-name>contextConfigLocation</param-name>  
  3. <param-value>  
  4. classpath:/config/*.xml   
  5. </param-value>  
  6. </context-param>  
  7. <!-- spring监听 -->  
  8. <listener>  
  9. <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
  10. </listener>  
  11. <!-- Spring Security会话控制 -->  
  12. <listener>  
  13. <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>  
  14. </listener>  
  15. <!-- Spring security Filter -->  
  16. <filter>  
  17. <filter-name>springSecurityFilterChain</filter-name>  
  18. <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
  19. </filter>  
  20. <filter-mapping>  
  21. <filter-name>springSecurityFilterChain</filter-name>  
  22. <url-pattern>/*</url-pattern>  
  23. </filter-mapping>  


这里主要做了三件事,

1、加载Spring;

2、加载Spring Security;

3、添加Spring Security Session监听器(用于控制登录)

Spring Secirty如下:

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans:beans xmlns="http://www.springframework.org/schema/security"  
  3. xmlns:beans="http://www.springframework.org/schema/beans"  
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
  6. http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">  
  7. <debug/>  
  8. <global-method-security  pre-post-annotations="enabled" />  
  9. <!-- 此目录下不需要过滤 -->  
  10. <http pattern="/js/**" security="none"/>  
  11. <http pattern="/resources/**" security="none"/>  
  12. <http pattern="/css/**" security="none"/>  
  13. <http pattern="/dwr/**" security="none"/>  
  14. <http pattern="/images/**" security="none"/>  
  15. <http pattern="/login.jsp" security="none"/>  
  16. <http use-expressions="true">  
  17. <!-- 非匿名用户就允许访问 -->  
  18. <intercept-url pattern="/index.jsp" access="isAuthenticated()"/>  
  19. <form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?error=true"  always-use-default-target="true" default-target-url="/index.jsp" />  
  20. <logout logout-success-url="/login.jsp"/>  
  21. <!-- 没有权限访问的页面 -->  
  22. <access-denied-handler error-page="/403.jsp"/>  
  23. <session-management></session-management>  
  24. <remember-me/>  
  25. <custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR"/>  
  26. </http>  
  27. <!-- 指定提示信息 -->  
  28. <beans:bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">  
  29. <beans:property name="basename" value="classpath:spring-security"></beans:property>  
  30. </beans:bean>  
  31. <authentication-manager alias="myAuthenticationManager">  
  32. <authentication-provider ref="authenticationProvider">  
  33. </authentication-provider>  
  34. </authentication-manager>  
  35. <beans:bean id="authenticationProvider"   
  36. class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">  
  37. <beans:property name="userDetailsService" ref="userdetailService" />  
  38. <!--显示用户错误信息-->  
  39. <beans:property name="hideUserNotFoundExceptions" value="false" />  
  40. <beans:property  name="passwordEncoder" ref="md5password"></beans:property >  
  41. </beans:bean>  
  42. <!-- 密码加密策略 -->  
  43. <beans:bean name="md5password" class="org.springframework.security.authentication.encoding.Md5PasswordEncoder"></beans:bean>  
  44. <beans:bean name="userdetailService" class="com.yindejin.system.MyAuthenticationManager">  
  45. <beans:property name="systemService" ref="systemService"></beans:property>  
  46. </beans:bean>  
  47. <beans:bean name="myFilter" class="com.yindejin.system.MySecurityFilter">  
  48. <!-- 用户拥有的权限 -->    
  49. <beans:property name="authenticationManager" ref="myAuthenticationManager" />    
  50. <!-- 用户是否拥有所请求资源的权限 -->    
  51. <beans:property name="accessDecisionManager" ref="myAccessDecisionManager" />    
  52. <!-- 资源与权限对应关系 -->    
  53. <beans:property name="securityMetadataSource" ref="mySecurityMetadataSource" />  
  54. </beans:bean>  
  55. <beans:bean id="myAccessDecisionManager" class="com.yindejin.system.MyAccessDecisionManager"></beans:bean>    
  56. <beans:bean id="mySecurityMetadataSource" class="com.yindejin.system.MySecurityMetadataSource">    
  57. <beans:constructor-arg name="systemService" ref="systemService"></beans:constructor-arg>    
  58. </beans:bean>    
  59. </beans:beans>  

<custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR"/>

这里的FILTER_SECURITY_INTERCEPTOR是Spring Security过滤器链中默认的Filter,

他的主要功能是

1、校验用户名、密码;

2、初始化时一次性加载所有的资源角色信息

3、检查用户访问权限

我们自定义的Filter必须在它之前,由于我们自己的过滤器和默认过滤器功能是一样的,所以就替换掉了原来的过滤器。

接下来是myFilter几个关键类


 


MySecurityFilter

  1. package com.yindejin.system;  
  2. import java.io.IOException;  
  3. import javax.servlet.Filter;  
  4. import javax.servlet.FilterChain;  
  5. import javax.servlet.FilterConfig;  
  6. import javax.servlet.ServletException;  
  7. import javax.servlet.ServletRequest;  
  8. import javax.servlet.ServletResponse;  
  9. import org.springframework.security.access.SecurityMetadataSource;  
  10. import org.springframework.security.access.intercept.AbstractSecurityInterceptor;  
  11. import org.springframework.security.access.intercept.InterceptorStatusToken;  
  12. import org.springframework.security.web.FilterInvocation;  
  13. import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;  
  14. public class MySecurityFilter extends AbstractSecurityInterceptor implements Filter {  
  15. //与applicationContext-security.xml里的myFilter的属性securityMetadataSource对应,  
  16. //其他的两个组件,已经在AbstractSecurityInterceptor定义  
  17. private FilterInvocationSecurityMetadataSource securityMetadataSource;  
  18. @Override  
  19. public SecurityMetadataSource obtainSecurityMetadataSource() {  
  20. return this.securityMetadataSource;  
  21. }  
  22. public void doFilter(ServletRequest request, ServletResponse response,  
  23. FilterChain chain) throws IOException, ServletException {  
  24. FilterInvocation fi = new FilterInvocation(request, response, chain);  
  25. invoke(fi);  
  26. }  
  27. private void invoke(FilterInvocation fi) throws IOException, ServletException {  
  28. System.out.println("用户发送请求! ");  
  29. InterceptorStatusToken token = null;  
  30. token = super.beforeInvocation(fi);  
  31. try {  
  32. fi.getChain().doFilter(fi.getRequest(), fi.getResponse());  
  33. } finally {  
  34. super.afterInvocation(token, null);  
  35. }  
  36. }  
  37. public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {  
  38. return securityMetadataSource;  
  39. }  
  40. public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource securityMetadataSource) {  
  41. this.securityMetadataSource = securityMetadataSource;  
  42. }  
  43. public void init(FilterConfig arg0) throws ServletException {  
  44. // TODO Auto-generated method stub  
  45. }  
  46. public void destroy() {  
  47. // TODO Auto-generated method stub  
  48. }  
  49. @Override  
  50. public Class<? extends Object> getSecureObjectClass() {  
  51. //下面的MyAccessDecisionManager的supports方面必须放回true,否则会提醒类型错误  
  52. return FilterInvocation.class;  
  53. }}  


 

MySecurityMetadataSource

  1. package com.yindejin.system;  
  2. import java.util.ArrayList;  
  3. import java.util.Collection;  
  4. import java.util.HashMap;  
  5. import java.util.LinkedHashMap;  
  6. import java.util.List;  
  7. import java.util.Map;  
  8. import java.util.Set;  
  9. import javax.servlet.http.HttpServletRequest;  
  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.AntPathRequestMatcher;  
  15. import org.springframework.security.web.util.RequestMatcher;  
  16. import com.yindejin.system.service.ISystemService;  
  17. import com.yindejin.vo.Resource;  
  18. import com.yindejin.vo.Role;  
  19. import com.yindejin.vo.User;  
  20. //1 加载资源与权限的对应关系  
  21. public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource {  
  22. //由spring调用  
  23. public MySecurityMetadataSource(ISystemService systemService) {  
  24. this.systemService = systemService;  
  25. }  
  26. private ISystemService systemService;  
  27. public ISystemService getSystemService() {  
  28. return systemService;  
  29. }  
  30. public void setSystemService(ISystemService systemService) {  
  31. this.systemService = systemService;  
  32. }  
  33. private static LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> resourceMap = null;  
  34. public Collection<ConfigAttribute> getAllConfigAttributes() {  
  35. // TODO Auto-generated method stub  
  36. return null;  
  37. }  
  38. public boolean supports(Class<?> clazz) {  
  39. // TODO Auto-generated method stub  
  40. return true;  
  41. }  
  42. //加载所有资源与权限的关系  
  43. private Map<String, String> getResource() {  
  44. Map<String, String> resourceMap = new HashMap<String, String>();  
  45. List<User> users = systemService.getAllUser();  
  46. for(User user:users){     
  47. for(Role role : user.getUserRoles()) {  
  48. Set<Resource> resources = role.getRoleResources();  
  49. for(Resource resource : resources) {  
  50. String url = resource.getValue();  
  51. if(!resourceMap.containsKey(url)) {  
  52. resourceMap.put(url, role.getName());  
  53. }else{  
  54. String roleName = resourceMap.get(url);  
  55. resourceMap.put(url, roleName+","+role.getName());  
  56. }  
  57. }  
  58. }  
  59. }  
  60. return resourceMap;  
  61. }  
  62. private void loadResourceDefine(){  
  63. resourceMap = new LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>>();  
  64. Map<String, String> resource = getResource();  
  65. for(Map.Entry<String, String> entry:resource.entrySet()){  
  66. Collection<ConfigAttribute> configAttributes = new ArrayList<ConfigAttribute>();  
  67. configAttributes.add(new SecurityConfig(entry.getValue()));  
  68. resourceMap.put(new AntPathRequestMatcher(entry.getKey()), configAttributes);  
  69. }  
  70. }  
  71. //返回所请求资源所需要的权限  
  72. public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {  
  73. HttpServletRequest request = ((FilterInvocation) object).getRequest();  
  74. if(null==resourceMap){  
  75. System.out.println("请求地址 " + ((FilterInvocation) object).getRequestUrl());  
  76. loadResourceDefine();  
  77. System.out.println("我需要的认证:"+resourceMap.toString());  
  78. }  
  79. for (Map.Entry<RequestMatcher, Collection<ConfigAttribute>> entry : resourceMap.entrySet()) {  
  80. if (entry.getKey().matches(request)) {  
  81. return entry.getValue();  
  82. }  
  83. }  
  84. return null;  
  85. }  
  86. }  


MyAccessDecisionManager

  1. package com.yindejin.system;  
  2. import java.util.Collection;  
  3. import java.util.Iterator;  
  4. import org.springframework.security.access.AccessDecisionManager;  
  5. import org.springframework.security.access.AccessDeniedException;  
  6. import org.springframework.security.access.ConfigAttribute;  
  7. import org.springframework.security.authentication.InsufficientAuthenticationException;  
  8. import org.springframework.security.core.Authentication;  
  9. import org.springframework.security.core.GrantedAuthority;  
  10. //3  
  11. public class MyAccessDecisionManager implements AccessDecisionManager {  
  12. public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {  
  13. if(configAttributes == null) {  
  14. return;  
  15. }  
  16. //所请求的资源拥有的权限(一个资源对多个权限)  
  17. Iterator<ConfigAttribute> iterator = configAttributes.iterator();  
  18. while(iterator.hasNext()) {  
  19. ConfigAttribute configAttribute = iterator.next();  
  20. //访问所请求资源所需要的权限  
  21. String needPermission = configAttribute.getAttribute();  
  22. System.out.println("needPermission is " + needPermission);  
  23. //用户所拥有的权限authentication  
  24. for(GrantedAuthority ga : authentication.getAuthorities()) {  
  25. if(needPermission.contains((ga.getAuthority()))) {  
  26. return;  
  27. }  
  28. }  
  29. }  
  30. //没有权限让我们去捕捉  
  31. throw new AccessDeniedException(" 没有权限访问!");  
  32. }  
  33. public boolean supports(ConfigAttribute attribute) {  
  34. // TODO Auto-generated method stub  
  35. return true;  
  36. }  
  37. public boolean supports(Class<?> clazz) {  
  38. // TODO Auto-generated method stub  
  39. return true;  
  40. }  
  41. }  


 

MyAuthenticationManager

  1. package com.yindejin.system;  
  2. import org.springframework.security.core.userdetails.UserDetails;  
  3. import org.springframework.security.core.userdetails.UserDetailsService;  
  4. import org.springframework.security.core.userdetails.UsernameNotFoundException;  
  5. import com.yindejin.system.service.ISystemService;  
  6. import com.yindejin.util.StringUtils;  
  7. import com.yindejin.vo.User;  
  8. public class MyAuthenticationManager implements UserDetailsService {  
  9. private ISystemService systemService;  
  10. public void setSystemService(ISystemService systemService) {  
  11. this.systemService = systemService;  
  12. }  
  13. @Override  
  14. public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {  
  15. if(!StringUtils.isEmpty(userName)){  
  16. throw new UsernameNotFoundException("用户名不能为空!");  
  17. }  
  18. User user = systemService.loginByUserName(userName);  
  19. if (user == null) {  
  20. throw new UsernameNotFoundException("用户名或密码错误!");  
  21. }  
  22. return user;  
  23. }  
  24. }  

User

  1. package com.yindejin.vo;  
  2. import java.util.ArrayList;  
  3. import java.util.Collection;  
  4. import java.util.HashMap;  
  5. import java.util.HashSet;  
  6. import java.util.List;  
  7. import java.util.Map;  
  8. import java.util.Set;  
  9. import javax.persistence.Transient;  
  10. import org.springframework.security.core.GrantedAuthority;  
  11. import org.springframework.security.core.authority.GrantedAuthorityImpl;  
  12. import org.springframework.security.core.userdetails.UserDetails;  
  13. /** 
  14. * User entity. @author MyEclipse Persistence Tools 
  15. */  
  16. public class User implements UserDetails {  
  17. // Fields  
  18. private Integer id;  
  19. private String name;  
  20. private String password = "123456";  
  21. private Integer disabled = 0;  
  22. private String email;  
  23. public String getEmail() {  
  24. return email;  
  25. }  
  26. public void setEmail(String email) {  
  27. this.email = email;  
  28. }  
  29. private Set<Role> userRoles = new HashSet<Role>();  
  30. @Transient  
  31. private Map<String, List<Resource>> roleResources;  
  32. // Constructors  
  33. public Integer getId() {  
  34. return id;  
  35. }  
  36. public void setId(Integer id) {  
  37. this.id = id;  
  38. }  
  39. public String getName() {  
  40. return name;  
  41. }  
  42. public void setName(String name) {  
  43. this.name = name;  
  44. }  
  45. public String getPassword() {  
  46. return password;  
  47. }  
  48. public void setPassword(String password) {  
  49. this.password = password;  
  50. }  
  51. public Integer getDisabled() {  
  52. return disabled;  
  53. }  
  54. public void setDisabled(Integer disabled) {  
  55. this.disabled = disabled;  
  56. }  
  57. public Set<Role> getUserRoles() {  
  58. return userRoles;  
  59. }  
  60. public void setUserRoles(Set<Role> userRoles) {  
  61. this.userRoles = userRoles;  
  62. }  
  63. /** default constructor */  
  64. public User() {  
  65. }  
  66. public String getUsername() {  
  67. return name;  
  68. }  
  69. public boolean isAccountNonExpired() {  
  70. return true;  
  71. }  
  72. public boolean isAccountNonLocked() {  
  73. return true;  
  74. }  
  75. public boolean isCredentialsNonExpired() {  
  76. return true;  
  77. }  
  78. public boolean isEnabled() {  
  79. return this.disabled==0?true:false;  
  80. }  
  81. /** 
  82. * @return the roleResources 
  83. */  
  84. public Map<String, List<Resource>> getRoleResources() {  
  85. // init roleResources for the first time  
  86. if(this.roleResources == null) {              
  87. this.roleResources = new HashMap<String, List<Resource>>();  
  88. for(Role role : this.userRoles) {  
  89. String roleName = role.getName();  
  90. Set<Resource> resources = role.getRoleResources();  
  91. for(Resource resource : resources) {  
  92. String key = roleName + "_" + resource.getType();  
  93. if(!this.roleResources.containsKey(key)) {  
  94. this.roleResources.put(key, new ArrayList<Resource>());  
  95. }  
  96. this.roleResources.get(key).add(resource);                    
  97. }  
  98. }  
  99. }  
  100. return this.roleResources;  
  101. }  
  102. @SuppressWarnings("deprecation")  
  103. @Override  
  104. public Collection<GrantedAuthority> getAuthorities() {  
  105. Set<GrantedAuthority> authSet = new HashSet<GrantedAuthority>();  
  106. for(Role role : getUserRoles()){  
  107. authSet.add(new GrantedAuthorityImpl(role.getName()));  
  108. }  
  109. return authSet;  
  110. }  
  111. }  


 

原文地址:https://www.cnblogs.com/fan-yuan/p/6249064.html