在阅读本文之前可以先看看springsecurity的基本执行流程,下面我展示一些核心配置文件,后面给出完整的整合代码到git上面,有兴趣的小伙伴可以下载进行研究

  使用maven工程构建项目,首先需要引入最核心的依赖,

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-security</artifactId>
  4. </dependency>

由于这里我们整合的项目进行了前后端分离,所以我们首先需要自定义登录成功和失败,登出成功的自定义处理类

其实就是实现不同的handler即可:1.首先我们来看登录成功的处理类

  1. /**
  2. * 处理登录验证成功的类
  3. * @author zhoukebo
  4. * @date 2018/9/4
  5. */
  6. @Component
  7. public class FuryAuthSuccessHandler implements AuthenticationSuccessHandler {
  8. /**Json转化工具*/
  9. @Autowired
  10. private ObjectMapper objectMapper;
  11.  
  12. @Override
  13. public void onAuthenticationSuccess(HttpServletRequest request,HttpServletResponse response, Authentication authentication) throws IOException{
  14. SysUser userDetails = (SysUser)authentication.getPrincipal();
  15. System.out.println("管理员 " + userDetails.getUsername() + " 登录");
  16. Map<String,String> map=new HashMap<>(2);
  17. map.put("code", "200");
  18. map.put("msg", "登录成功");
  19. response.setContentType("application/json;charset=UTF-8");
  20. response.getWriter().write(objectMapper.writeValueAsString(map));
  21. }
  22.  
  23. }

2.登录验证失败的类

  1. /**
  2. * 处理登录验证失败的类
  3. * @author zhoukebo
  4. * @date 2018/9/4
  5. */
  6. @Component
  7. public class FuryAuthFailureHandler implements AuthenticationFailureHandler {
  8.  
  9. @Autowired
  10. private ObjectMapper objectMapper;
  11.  
  12. @Override
  13. public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
  14. System.out.println("登录验证失败");
  15. Map<String,String> map=new HashMap<>(2);
  16. map.put("code", "10001");
  17. map.put("msg", exception.getMessage());
  18. response.setContentType("application/json;charset=UTF-8");
  19. response.getWriter().write(objectMapper.writeValueAsString(map));
  20. }
  21. }

3.自定义处理注销成功的类

  1. /**
  2. * 处理注销成功
  3. * @author zhoukebo
  4. * @date 2018/9/4
  5. */
  6. @Component
  7. public class MyLogoutSuccessHandler implements LogoutSuccessHandler {
  8.  
  9. /**Json转化工具*/
  10. @Autowired
  11. private ObjectMapper objectMapper;
  12.  
  13. @Override
  14. public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException{
  15. Map<String,String> map=new HashMap<>(2);
  16. map.put("code", "200");
  17. map.put("msg", "登出成功");
  18. response.setContentType("application/json;charset=UTF-8");
  19. response.getWriter().write(objectMapper.writeValueAsString(map));
  20. }
  21. }

4.自定义没有权限的处理类

  1. /**
  2. * 处理没有权限的类
  3. * @author zhoukebo
  4. * @date 2018/9/5
  5. */
  6. @Component
  7. public class RestAuthAccessDeniedHandler implements AccessDeniedHandler {
  8.  
  9. @Autowired
  10. private ObjectMapper objectMapper;
  11.  
  12. @Override
  13. public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException {
  14. Map<String,String> map=new HashMap<>(2);
  15. map.put("code", "403");
  16. map.put("msg", e.getMessage());
  17. response.setContentType("application/json;charset=UTF-8");
  18. response.getWriter().write(objectMapper.writeValueAsString(map));
  19. }
  20. }

然后对springsecurity进行详细的配置需要继承WebSecurityConfigurerAdapter类,下面是配置文件的详情

  1. /**
  2. * spring Security配置安全控制中心
  3. *
  4. * @author zhoukb
  5. */
  6. @Configuration
  7. @EnableWebSecurity
  8. @EnableGlobalMethodSecurity(prePostEnabled = true)
  9. public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  10. /**
  11. * 依赖注入自定义的登录成功处理器
  12. */
  13. @Autowired
  14. private FuryAuthSuccessHandler furyAuthSuccessHandler;
  15. /**
  16. * 依赖注入自定义的登录失败处理器
  17. */
  18. @Autowired
  19. private FuryAuthFailureHandler furyAuthFailureHandler;
  20. /**
  21. * 依赖注入自定义的注销成功的处理器
  22. */
  23. @Autowired
  24. private MyLogoutSuccessHandler myLogoutSuccessHandler;
  25.  
  26. /**
  27. * 注册没有权限的处理器
  28. */
  29. @Autowired
  30. private RestAuthAccessDeniedHandler restAuthAccessDeniedHandler;
  31.  
  32. /***注入自定义的CustomPermissionEvaluator*/
  33. @Bean
  34. public DefaultWebSecurityExpressionHandler webSecurityExpressionHandler() {
  35. DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler();
  36. handler.setPermissionEvaluator(new CustomPermissionEvaluator());
  37. return handler;
  38. }
  39.  
  40. /***注入我们自己的登录逻辑验证器AuthenticationProvider*/
  41. @Autowired
  42. private AuthenticationProvider authenticationProvider;
  43.  
  44. @Override
  45. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  46. //这里可启用我们自己的登陆验证逻辑
  47. auth.authenticationProvider(authenticationProvider);
  48. }
  49.  
  50. /**
  51. * 配置spring security的控制逻辑
  52. */
  53. @Override
  54. protected void configure(HttpSecurity http) throws Exception {
  55. http.authorizeRequests()
  56. //"/login"不进行权限验证
  57. .antMatchers("/login").permitAll()
  58. .antMatchers("/favicon.ico").permitAll()
  59. .anyRequest().authenticated() //其他的需要登陆后才能访问
  60. .and()
  61. .formLogin()
  62. //loginProcessingUrl用于指定前后端分离的时候调用后台登录接口的名称
  63. .loginProcessingUrl("/login")
  64. //配置登录成功的自定义处理类
  65. .successHandler(furyAuthSuccessHandler)
  66. //配置登录失败的自定义处理类
  67. .failureHandler(furyAuthFailureHandler)
  68. .and()
  69. //loginProcessingUrl用于指定前后端分离的时候调用后台注销接口的名称
  70. .logout().logoutUrl("/logout")
  71. .logoutSuccessHandler(myLogoutSuccessHandler)
  72. .and()
  73. //配置没有权限的自定义处理类
  74. .exceptionHandling().accessDeniedHandler(restAuthAccessDeniedHandler)
  75. .and()
  76. .cors()//新加入
  77. .and()
  78. .csrf().disable();// 取消跨站请求伪造防护
  79. }
  80. }

上面我们配置了自定义的登录逻辑的验证MyAuthenticationProvider,和自定义的权限验证CustomPermissionEvaluator代码如下

  1. /**
  2. * 实现自己的AuthenticationProvider类,用来自定义用户校验机制
  3. * @author zhoukebo
  4. * @date 2018/9/5
  5. */
  6. @Component
  7. public class MyAuthenticationProvider implements AuthenticationProvider {
  8.  
  9. @Autowired
  10. private CustomerDetailService customerDetailService;
  11.  
  12. @Override
  13. public Authentication authenticate(Authentication authentication) throws AuthenticationException {
  14. // 获取表单输入中返回的用户名;
  15. String userName = (String) authentication.getPrincipal();
  16. // 获取表单中输入的密码;
  17. String password = (String) authentication.getCredentials();
  18. // 这里调用我们的自己写的获取用户的方法;
  19. UserDetails userInfo = customerDetailService.loadUserByUsername(userName);
  20. if (userInfo == null) {
  21. throw new BadCredentialsException("用户名不存在");
  22. }
  23.  
  24. // 这里我们还要判断密码是否正确,这里我们的密码使用BCryptPasswordEncoder进行加密的
  25. if (!new BCryptPasswordEncoder().matches(password, userInfo.getPassword())) {
  26. throw new BadCredentialsException("密码不正确");
  27. }
  28. // 这里还可以加一些其他信息的判断,比如用户账号已停用等判断。
  29.  
  30. Collection<? extends GrantedAuthority> authorities = userInfo.getAuthorities();
  31. // 构建返回的用户登录成功的token
  32. return new UsernamePasswordAuthenticationToken(userInfo, password, authorities);
  33. }
  34.  
  35. @Override
  36. public boolean supports(Class<?> authentication) {
  37. // 这里直接改成retrun true;表示是支持这个执行
  38. return true;
  39. }
  40. }
  1. /**
  2. * 我们需要自定义对hasPermission()方法的处理,
  3. * 就需要自定义PermissionEvaluator,创建类CustomPermissionEvaluator,实现PermissionEvaluator接口。
  4. * @author zhoukebo
  5. * @date 2018/9/5
  6. */
  7. @Component
  8. public class CustomPermissionEvaluator implements PermissionEvaluator {
  9. /**
  10. * 自定义验证方法
  11. * @param authentication 登录的时候存储的用户信息
  12. * @param targetDomainObject @PreAuthorize("hasPermission('/hello/**','r')") 中hasPermission的第一个参数
  13. * @param permission @PreAuthorize("hasPermission('/hello/**','r')") 中hasPermission的第二个参数
  14. * @return
  15. */
  16. @Override
  17. public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
  18. // 获得loadUserByUsername()方法的结果
  19. SysUser user = (SysUser)authentication.getPrincipal();
  20. // 获得loadUserByUsername()中注入的权限
  21. Collection<? extends GrantedAuthority> authorities = user.getAuthorities();
  22. // 遍历用户权限进行判定
  23. for(GrantedAuthority authority : authorities) {
  24. UrlGrantedAuthority urlGrantedAuthority = (UrlGrantedAuthority) authority;
  25. String permissionUrl = urlGrantedAuthority.getPermissionUrl();
  26. // 如果访问的Url和权限用户符合的话,返回true
  27. if(targetDomainObject.equals(permissionUrl)) {
  28. return true;
  29. }
  30. }
  31. return false;
  32. }
  33.  
  34. @Override
  35. public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
  36. return false;
  37. }
  38. }

注意:上面的自定义权限要生效还需要在WebSecurityConfig上面加上注解@EnableGlobalMethodSecurity(prePostEnabled = true)

完成登录逻辑还需要我们实现UserDetailsService接口,以便系统能够根据用户名去获取用户的信息,里面还可加上自己的逻辑

  1. /**
  2. * 需要自定义UserDetailsService实现spring security的UserDetailsService接口
  3. * @author zhoukebo
  4. * @date 2018/9/4
  5. */
  6. @Service
  7. public class CustomerDetailService implements UserDetailsService {
  8.  
  9. @Autowired
  10. SysUserRepository userRepository;
  11.  
  12. @Override
  13. public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
  14. SysUser user = userRepository.findByUsername(username);
  15. if (user == null) {
  16. throw new UsernameNotFoundException("用户名不存在");
  17. }
  18. List<SysRole> roles = user.getRoles();
  19.  
  20. //将所有的角色对应的资源权限全部放入user对应的grantedAuthority集合中
  21. for (SysRole role : roles) {
  22. List<SysResource> resources = role.getResources();
  23. List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
  24. for (SysResource resource : resources) {
  25. if (resource != null && resource.getResourceName()!=null) {
  26. GrantedAuthority grantedAuthority = new UrlGrantedAuthority(resource.getMethodPath(),resource.getResourceName());
  27. grantedAuthorities.add(grantedAuthority);
  28. }
  29. }
  30. user.setGrantedAuthority(grantedAuthorities);
  31. }
  32.  
  33. System.out.println("s:" + username);
  34. return user;
  35. }
  36. }

以上就完成了springboot和springsecurity的整合工作,demo中包含两种自定义权限验证,有兴趣的小伙伴可以自行在github上面下载下来研究,不懂得可以交流,代码有什么不妥的地方也望大家互相指教

github示例代码

springboot2.0整合springsecurity前后端分离进行自定义权限控制的更多相关文章

  1. SpringBoot2.0.3 + SpringSecurity5.0.6 + vue 前后端分离认证授权

    新项目引入安全控制 项目中新近添加了Spring Security安全组件,前期没怎么用过,加之新版本少有参考,踩坑四天,终完成初步解决方案.其实很简单,Spring Security5相比之前版本少 ...

  2. SpringBoot2.0整合SpringSecurity实现WEB JWT认证

    相信很多做技术的朋友都做过前后端分离项目,项目分离后认证就靠JWT,费话不多说,直接上干活(写的不好还请多多见谅,大牛请绕行) 直接上代码,项目为Maven项目,结构如图: 包分类如下: com.ap ...

  3. Spring Boot Security JWT 整合实现前后端分离认证示例

    前面两章节我们介绍了 Spring Boot Security 快速入门 和 Spring Boot JWT 快速入门,本章节使用 JWT 和 Spring Boot Security 构件一个前后端 ...

  4. Vue+Django2.0 restframework打造前后端分离的生鲜电商项目(2)

    1.restful api介绍 1.前后端分离的优缺点 1.为什么要用前后端分离 1.pc.app.pad多端适应 2.SPA(单页面应用)开发模式开始流行 3.前后端分离职责不清 4.开发效率问题, ...

  5. Spring Boot + Vue 前后端分离开发,权限管理的一点思路

    在传统的前后端不分的开发中,权限管理主要通过过滤器或者拦截器来进行(权限管理框架本身也是通过过滤器来实现功能),如果用户不具备某一个角色或者某一个权限,则无法访问某一个页面. 但是在前后端分离中,页面 ...

  6. SpringBoot+Shiro+JWT前后端分离实现用户权限和接口权限控制

    1. 引入需要的依赖 我使用的是原生jwt的依赖包,在maven仓库中有好多衍生的jwt依赖包,可自己在maven仓库中选择,实现大同小异. <dependency> <groupI ...

  7. SpringBoot2.0 整合 SpringSecurity 框架,实现用户权限安全管理

    本文源码:GitHub·点这里 || GitEE·点这里 一.Security简介 1.基础概念 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方 ...

  8. springboot整合ueditor 前后端分离

    1.下载ueditor,百度搜索ueditor,下载 前端用的是Jsp版,导入文件如下 由于要修改部分源码,所以后端用的源码版,导入文件如下 2.配置路径,用来找到json文件 配置前端ueditor ...

  9. Vue+Django2.0 restframework打造前后端分离的生鲜电商项目(3)

    1.drf前期准备 1.django-rest-framework官方文档 https://www.django-rest-framework.org/ #直接百度找到的djangorestframe ...

随机推荐

  1. Android网络(3):HttpClient作client,Tomcat Servlet作server的交互演示样例

    前面相继介绍了Android网络编程里的Socket传输图片.HttpURLConnection,今天看HttpClient. 第一部分:JavaEE版的Eclipse配置Tomcat [备注:开发后 ...

  2. Unity Shader后处理-搜索灰度效果

    如U3D中Hierarchy面板下的搜索效果: 讲解分析: 1.这种PostEffect效果其实就是指Unity shader的后处理,即游戏中实现屏幕特效的常见方法.顾名思义屏幕后处理就是指在渲染完 ...

  3. SB般的“WE战队”输掉了比赛

    事实再一次证明,对于LOL这种游戏,国服选手是根本就不能有一点期待的, 国服环境太好了,赢了可以吹,输了不能骂,自信心极度膨胀,估计WE俱乐部都没有个心理咨询师, 下岗了还可以再卖卖脸,卖卖饼, 国服 ...

  4. No package docker-io available

    新手centos6.8安装docker时从遇到No package docker-io available开始的各种不小心的坑... 新安装了CentOS6.8,准备安装docker,执行命令 yum ...

  5. Java List 快速搜索对象

    比如现在有一个需求现在有一个List 里面装Student 对象 我们想找出这个List 对象里面student name=小明的对象 我想很多同学会像以前的我一样变量List 然后去比较 但是这样处 ...

  6. Unity 中调用Android的JAVA代码

    首先我们要创建一个android项目 因为项目需要使用Unity提供的接口,所以需要将接口classes.jar引入至当前工程但中.接口包的所在地,打开Finder->应用程序->Unit ...

  7. Android SDK 环境变量配置

    ANDROID_HOME = D:\Package\android-sdk-windows 在path 中加入 %ANDROID_HOME%\tools 和 %ANDROID_HOME%\platfo ...

  8. electron-vue构建桌面应用

    一.项目搭建 electron-vue是vue-cli和electron结合的项目,比单独使用vue构建起的electron项目要方便很多. 1.初始化项目并运行 vue init simulated ...

  9. 使用Docker创建数据容器

    使用Docker创建数据容器 翻译自: Data-only container madness 1.什么是数据容器? 数据容器就是本身只创建一个volume供其他容器共享,创建完后即退出,不执行任何任 ...

  10. Spark 调优之ShuffleManager、Shuffle

    Shuffle 概述 影响Spark性能的大BOSS就是shuffle,因为该环节包含了大量的磁盘IO.序列化.网络数据传输等操作. 因此,如果要让作业的性能更上一层楼,就有必要对 shuffle 过 ...