Spring Boot 集成spring security4

Posted 星朝

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Boot 集成spring security4相关的知识,希望对你有一定的参考价值。


项目GitHub地址 :

https://github.com/FrameReserve/TrainingBoot


Spring Boot (三)集成spring security,标记地址:

https://github.com/FrameReserve/TrainingBoot/releases/tag/0.0.3



pom.xml

只列举 Spring Security配置,完整配置请查看Git项目地址

  1. <properties>  
  2.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
  3.         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>  
  4.         <java.version>1.8</java.version>  
  5.         <!--  依赖版本  -->  
  6.         <mybatis.version>3.4.1</mybatis.version>  
  7.         <mybatis.spring.version>1.3.0</mybatis.spring.version>  
  8.           
  9.         <spring-security.version>4.1.0.RELEASE</spring-security.version>  
  10.     </properties>  
  11.   
  12.   
  13.   
  14. <!-- spring security -->  
  15.         <dependency>  
  16.             <groupId>org.springframework.security</groupId>  
  17.             <artifactId>spring-security-web</artifactId>  
  18.             <version>${spring-security.version}</version>  
  19.         </dependency>  
  20.         <dependency>  
  21.             <groupId>org.springframework.security</groupId>  
  22.             <artifactId>spring-security-config</artifactId>  
  23.             <version>${spring-security.version}</version>  
  24.         </dependency>  
  25.         <dependency>  
  26.             <groupId>org.springframework.security</groupId>  
  27.             <artifactId>spring-security-taglibs</artifactId>  
  28.             <version>${spring-security.version}</version>  
  29.         </dependency>  


Spring Security 配置类:

src/main/java/com/training/core/security/WebSecurityConfig.java

  1. package com.training.core.security;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import javax.annotation.Resource;  
  7.   
  8. import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;  
  9. import org.springframework.context.annotation.Bean;  
  10. import org.springframework.context.annotation.Configuration;  
  11. import org.springframework.security.access.AccessDecisionManager;  
  12. import org.springframework.security.access.AccessDecisionVoter;  
  13. import org.springframework.security.access.vote.AuthenticatedVoter;  
  14. import org.springframework.security.access.vote.RoleVoter;  
  15. import org.springframework.security.authentication.AuthenticationManager;  
  16. import org.springframework.security.authentication.event.LoggerListener;  
  17. import org.springframework.security.config.annotation.ObjectPostProcessor;  
  18. import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;  
  19. import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;  
  20. import org.springframework.security.config.annotation.web.builders.HttpSecurity;  
  21. import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;  
  22. import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;  
  23. import org.springframework.security.core.userdetails.UserDetailsService;  
  24. import org.springframework.security.web.access.AccessDeniedHandler;  
  25. import org.springframework.security.web.access.AccessDeniedHandlerImpl;  
  26. import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;  
  27. import org.springframework.security.web.access.expression.WebExpressionVoter;  
  28. import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;  
  29. import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;  
  30. import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;  
  31. import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;  
  32. import org.springframework.security.web.util.matcher.AntPathRequestMatcher;  
  33.   
  34. import com.training.sysmanager.service.AclResourcesService;  
  35. import com.training.sysmanager.service.impl.AclResourcesServiceImpl;  
  36.   
  37. /** 
  38.  * Created by Athos on 2016-10-16. 
  39.  */  
  40. @Configuration  
  41. @EnableWebSecurity  
  42. @EnableGlobalMethodSecurity(prePostEnabled = true)  
  43. public class WebSecurityConfig extends WebSecurityConfigurerAdapter {  
  44.   
  45.     @Resource  
  46.     private UserDetailsService userDetailsService;  
  47.   
  48.     @Resource  
  49.     private MySecurityMetadataSource mySecurityMetadataSource;  
  50.   
  51.     @Override  
  52.     protected void configure(HttpSecurity http) throws Exception {  
  53.   
  54.         http.addFilterAfter(MyUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);  
  55.         // 开启默认登录页面  
  56.         http.authorizeRequests().anyRequest().authenticated().withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {  
  57.             public <O extends FilterSecurityInterceptor> O postProcess(O fsi) {  
  58.                 fsi.setSecurityMetadataSource(mySecurityMetadataSource);  
  59.                 fsi.setAccessDecisionManager(accessDecisionManager());  
  60.                 fsi.setAuthenticationManager(authenticationManagerBean());  
  61.                 return fsi;  
  62.             }  
  63.         }).and().exceptionHandling().authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login.html")).and().logout().logoutSuccessUrl("/index.html").permitAll();  
  64.         // 自定义accessDecisionManager访问控制器,并开启表达式语言  
  65.         http.exceptionHandling().accessDeniedHandler(accessDeniedHandler()).and().authorizeRequests().anyRequest().authenticated().expressionHandler(webSecurityExpressionHandler());  
  66.   
  67.         // 自定义登录页面  
  68.         http.csrf().disable();  
  69.   
  70.         // 自定义注销  
  71.         // http.logout().logoutUrl("/logout").logoutSuccessUrl("/login")  
  72.         // .invalidateHttpSession(true);  
  73.   
  74.         // session管理  
  75.         http.sessionManagement().maximumSessions(1);  
  76.   
  77.         // RemeberMe  
  78.         // http.rememberMe().key("webmvc#FD637E6D9C0F1A5A67082AF56CE32485");  
  79.   
  80.     }  
  81.   
  82.     @Override  
  83.     protected void configure(AuthenticationManagerBuilder auth) throws Exception {  
  84.         // 自定义UserDetailsService  
  85.         auth.userDetailsService(userDetailsService);  
  86.     }  
  87.   
  88.     @Bean  
  89.     UsernamePasswordAuthenticationFilter MyUsernamePasswordAuthenticationFilter() {  
  90.         UsernamePasswordAuthenticationFilter myUsernamePasswordAuthenticationFilter = new UsernamePasswordAuthenticationFilter();  
  91.         myUsernamePasswordAuthenticationFilter.setPostOnly(true);  
  92.         myUsernamePasswordAuthenticationFilter.setAuthenticationManager(authenticationManagerBean());  
  93.         myUsernamePasswordAuthenticationFilter.setUsernameParameter("name_key");  
  94.         myUsernamePasswordAuthenticationFilter.setPasswordParameter("pwd_key");  
  95.         myUsernamePasswordAuthenticationFilter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/login""POST"));  
  96.         myUsernamePasswordAuthenticationFilter.setAuthenticationFailureHandler(simpleUrlAuthenticationFailureHandler());  
  97.         return myUsernamePasswordAuthenticationFilter;  
  98.     }  
  99.   
  100.     @Bean  
  101.     AccessDeniedHandler accessDeniedHandler() {  
  102.         AccessDeniedHandlerImpl accessDeniedHandler = new AccessDeniedHandlerImpl();  
  103.         accessDeniedHandler.setErrorPage("/securityException/accessDenied");  
  104.         return accessDeniedHandler;  
  105.     }  
  106.   
  107.     @Bean  
  108.     public LoggerListener loggerListener() {  
  109.         System.out.println("org.springframework.security.authentication.event.LoggerListener");  
  110.         return new LoggerListener();  
  111.     }  
  112.   
  113.     @Bean  
  114.     public org.springframework.security.access.event.LoggerListener eventLoggerListener() {  
  115.         System.out.println("org.springframework.security.access.event.LoggerListener");  
  116.         return new org.springframework.security.access.event.LoggerListener();  
  117.     }  
  118.   
  119.     /* 
  120.      *  
  121.      * 这里可以增加自定义的投票器 
  122.      */  
  123.     @Bean(name = "accessDecisionManager")  
  124.     public AccessDecisionManager accessDecisionManager() {  
  125.         List<AccessDecisionVoter<? extends Object>> decisionVoters = new ArrayList();  
  126.         decisionVoters.add(new RoleVoter());  
  127.         decisionVoters.add(new AuthenticatedVoter());  
  128.         decisionVoters.add(webExpressionVoter());// 启用表达式投票器  
  129.         MyAccessDecisionManager accessDecisionManager = new MyAccessDecisionManager(decisionVoters);  
  130.         return accessDecisionManager;  
  131.     }  
  132.   
  133.     @Bean(name = "authenticationManager")  
  134.     @Override  
  135.     public AuthenticationManager authenticationManagerBean() {  
  136.         AuthenticationManager authenticationManager = null;  
  137.         try {  
  138.             authenticationManager = super.authenticationManagerBean();  
  139.         } catch (Exception e) {  
  140.             e.printStackTrace();  
  141.         }  
  142.         return authenticationManager;  
  143.     }  
  144.   
  145.     @Bean(name = "failureHandler")  
  146.     public SimpleUrlAuthenticationFailureHandler simpleUrlAuthenticationFailureHandler() {  
  147.         return new SimpleUrlAuthenticationFailureHandler("/getLoginError");  
  148.     }  
  149.   
  150.     @Bean(name = "aclResourcesService")  
  151.     @ConditionalOnMissingBean  
  152.     public AclResourcesService aclResourcesService() {  
  153.         return new AclResourcesServiceImpl();  
  154.     }  
  155.   
  156.     /* 
  157.      * 表达式控制器 
  158.      */  
  159.     @Bean(name = "expressionHandler")  
  160.     public DefaultWebSecurityExpressionHandler webSecurityExpressionHandler() {  
  161.         DefaultWebSecurityExpressionHandler webSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler();  
  162.         return webSecurityExpressionHandler;  
  163.     }  
  164.   
  165.     /* 
  166.      * 表达式投票器 
  167.      */  
  168.     @Bean(name = "expressionVoter")  
  169.     public WebExpressionVoter webExpressionVoter() {  
  170.         WebExpressionVoter webExpressionVoter = new WebExpressionVoter();  
  171.         webExpressionVoter.setExpressionHandler(webSecurityExpressionHandler());  
  172.         return webExpressionVoter;  
  173.     }  
  174.   
  175. }  


自定义 UserDetailsService 用户、角色、资源获取类:

src/main/java/com/training/core/security/UserDetailsServiceImpl.java

  1. package com.training.core.security;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import javax.annotation.Resource;  
  7.   
  8. import org.springframework.security.core.GrantedAuthority;  
  9. import org.springframework.security.core.authority.SimpleGrantedAuthority;  
  10. import org.springframework.security.core.userdetails.User;  
  11. import org.springframework.security.core.userdetails.UserDetails;  
  12. import org.springframework.security.core.userdetails.UserDetailsService;  
  13. import org.springframework.security.core.userdetails.UsernameNotFoundException;  
  14. import org.springframework.stereotype.Service;  
  15.   
  16. import com.training.sysmanager.entity.AclResources;  
  17. import com.training.sysmanager.entity.AclUser;  
  18. import com.training.sysmanager.service.AclResourcesService;  
  19. import com.training.sysmanager.service.AclRoleResourcesService;  
  20. import com.training.sysmanager.service.AclUserService;  
  21.   
  22. /** 
  23.  * Created by Athos on 2016-10-16. 
  24.  */  
  25. @Service("userDetailsService")  
  26. public class UserDetailsServiceImpl  implements UserDetailsService {  
  27.       
  28.     @Resource  
  29.     private AclUserService aclUserService;  
  30.     @Resource  
  31.     private AclRoleResourcesService aclRoleResourcesService;  
  32.     @Resource  
  33.     private AclResourcesService aclResourcesService;  
  34.   
  35.     /* (non-Javadoc) 
  36.      * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String) 
  37.      */  
  38.     @Override  
  39.     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {  
  40.         List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();  
  41.         AclUser aclUser = aclUserService.findAclUserByName(username);  
  42.         String resourceIds = aclRoleResourcesService.selectResourceIdsByRoleIds(aclUser.getRoleIds());  
  43.         List<AclResources> aclResourcesList = aclResourcesService.selectAclResourcesByResourceIds(resourceIds);  
  44.         for (AclResources aclResources : aclResourcesList) {  
  45.             auths.add(new SimpleGrantedAuthority(aclResources.getAuthority().toUpperCase()));  
  46.         }  
  47. //        auths.addAll(aclResourcesList.stream().map(resources -> new SimpleGrantedAuthority(resources.getAuthority().toUpperCase())).collect(Collectors.toList()));  
  48.         return new User(aclUser.getUserName().toLowerCase(),aclUser.getUserPwd().toLowerCase(),true,true,true,true,auths);  
  49.     }  
  50. }  


自定义securityMetadataSource:

src/main/java/com/training/core/security/MySecurityMetadataSource.java

  1. package com.training.core.security;  
  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 javax.servlet.http.HttpServletRequest;  
  11.   
  12. import org.springframework.security.access.ConfigAttribute;  
  13. import org.springframework.security.access.SecurityConfig;  
  14. import org.springframework.security.web.FilterInvocation;  
  15. import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;  
  16. import org.springframework.security.web.util.matcher.AntPathRequestMatcher;  
  17. import org.springframework.security.web.util.matcher.RequestMatcher;  
  18. import org.springframework.stereotype.Component;  
  19.   
  20. import com.training.sysmanager.entity.AclResources;  
  21. import com.training.sysmanager.service.AclResourcesService;  
  22.   
  23. /** 
  24.  * Created by Athos on 2016-10-16. 
  25.  */  
  26. @Component("mySecurityMetadataSource")  
  27. public class MySecurityMetadataSource  implements FilterInvocationSecurityMetadataSource {  
  28.   
  29.     private static Map<String,Collection<ConfigAttribute>> aclResourceMap = null;  
  30.     private AclResourcesService aclResourcesService;  
  31.   
  32.     /** 
  33.      * 构造方法 
  34.      */  
  35.     //1  
  36.     public MySecurityMetadataSource(AclResourcesService aclResourcesService){  
  37.         this.aclResourcesService=aclResourcesService;  
  38.         loadResourceDefine();  
  39.     }  
  40.   
  41.     @Override  
  42.     public Collection<ConfigAttribute> getAttributes(Object object)throws IllegalArgumentException{  
  43.         HttpServletRequest request=((FilterInvocation)object).getRequest();  
  44.         Iterator<String> ite = aclResourceMap.keySet().iterator();  
  45.         while (ite.hasNext()){  
  46.             String resURL = ite.next();  
  47.             RequestMatcher requestMatcher = new AntPathRequestMatcher(resURL);  
  48.             if(requestMatcher.matches(request)){  
  49.                 return aclResourceMap.get(resURL);  
  50.             }  
  51.         }  
  52.         return null;  
  53.     }  
  54.     //4  
  55.     @Override  
  56.     public Collection<ConfigAttribute> getAllConfigAttributes() {  
  57.         System.out.println("metadata : getAllConfigAttributes");  
  58.         return null;  
  59.     }  
  60.     //3  
  61.     @Override  
  62.     public boolean supports(Class<?> clazz) {  
  63.         System.out.println("metadata : supports");  
  64.         return true;  
  65.     }  
  66.   
  67.   
  68.     private void loadResourceDefine(){  
  69.         /** 
  70.          * 因为只有权限控制的资源才需要被拦截验证,所以只加载有权限控制的资源 
  71.          */  
  72.         List<AclResources> aclResourceses = aclResourcesService.selectAclResourcesTypeOfRequest();  
  73.         aclResourceMap = new HashMap<>();  
  74.         for (AclResources aclResources:aclResourceses){  
  75.             ConfigAttribute ca = new SecurityConfig(aclResources.getAuthority().toUpperCase());  
  76.             String url = aclResources.getUrl();  
  77.             if(aclResourceMap.containsKey(url)){  
  78.                 Collection<ConfigAttribute> value = aclResourceMap.get(url);  
  79.                 value.add(ca);  
  80.                 aclResourceMap.put(url,value);  
  81.   
  82.             }else {  
  83.                 Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();  
  84.                 atts.add(ca);  
  85.                 aclResourceMap.put(url,atts);  
  86.             }  
  87.         }  
  88.     }  
  89. }  


自定义AbstractAccessDecisionManager权限决策类,

src/main/java/com/training/core/security/MyAccessDecisionManager.java

  1. package com.training.core.security;  
  2.   
  3. import org.springframework.security.access.AccessDecisionVoter;  
  4. import org.springframework.security.access.AccessDeniedException;  
  5. import org.springframework.security.access.ConfigAttribute;  
  6. import org.springframework.security.access.vote.AbstractAccessDecisionManager;  
  7. import org.springframework.security.authentication.InsufficientAuthenticationException;  
  8. import org.springframework.security.core.Authentication;  
  9. import org.springframework.security.core.GrantedAuthority;  
  10.   
  11. import java.util.Collection;  
  12. import java.util.Iterator;  
  13. import java.util.List;  
  14.   
  15. /** 
  16.  * Created by Athos on 2016-10-16. 
  17.  */  
  18.   
  19. public class MyAccessDecisionManager  extends AbstractAccessDecisionManager {  
  20.     protected MyAccessDecisionManager(List<AccessDecisionVoter<? extends Object>> decisionVoters) {  
  21.         super(decisionVoters);  
  22.     }  
  23.   
  24.     @Override  
  25.     public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {  
  26.         if(configAttributes==null){  
  27.             return;  
  28.         }  
  29.         Iterator<ConfigAttribute> ite = configAttributes.iterator();  
  30.         while(ite.hasNext()){  
  31.             ConfigAttribute ca = ite.next();  
  32.             String needRole = (ca).getAttribute();  
  33.             for (GrantedAuthority ga : authentication.getAuthorities()){  
  34.                 if (needRole.equals(ga.getAuthority())){  
  35.                     return;  
  36.                 }  
  37.             }  
  38.         }  
  39.         throw new AccessDeniedException("没有权限,拒绝访问!");  
  40.     }  
  41.     @Override  
  42.     public boolean supports(ConfigAttribute attribute) {  
  43.         return false;  
  44.     }  
  45.   
  46.     /** 
  47.      * Iterates through all <code>AccessDecisionVoter</code>s and ensures each can support 
  48.      * the presented class. 
  49.      * <p> 
  50.      * If one or more voters cannot support the presented class, <code>false</code> is 
  51.      * returned. 
  52.      * 
  53.      * @param clazz the type of secured object being presented 
  54.      * @return true if this type is supported 
  55.      */  
  56.     @Override  
  57.     public boolean supports(Class<?> clazz) {  
  58.         return true;  
  59.     }  
  60. }  


用户、角色、资源(菜单)略。

详情请看GIT完成工程。

https://github.com/FrameReserve/TrainingBoot





















以上是关于Spring Boot 集成spring security4的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 第七章 Spring Boot 集成 Dubbo

忽略 Spring Boot 中特定 Url 的承载令牌验证

Spring Boot(十八):使用Spring Boot集成FastDFS

Spring Boot集成Spring Cache 和 Redis

Spring Boot集成Mybatis及通用Mapper

Spring Boot学习笔记——Spring Boot与Redis的集成