当前后端分离时,权限问题的处理也和我们传统的处理方式有一点差异.笔者前几天刚好在负责一个项目的权限管理模块,现在权限管理模块已经做完了,我想通过 5-6 篇文章,来介绍一下项目中遇到的问题以及我的解决方案,希望这个系列能够给小伙伴一些帮助.本系列文章并不是手把手的教程,主要介绍了核心思路并讲解了核心代码,完整的代码小伙伴们可以在 GitHub 上 star 并 clone 下来研究.另外,原本计划把项目跑起来放到网上供小伙伴们查看,但是之前买服务器为了省钱,内存只有 512M,两个应用跑不起来 (已经有一个 V 部落开源项目 在运行),因此小伙伴们只能将就看一下下面的截图了,GitHub 上有部署教程,部署到本地也可以查看完整效果.
项目地址: https://github.com/lenve/vhr
上篇文章我们已经把整个环境搭建成功了,并且配置好了资源和角色的动态分配,本文我们主要来聊聊异常处理和密码加密.
本文是本系列的第三篇,建议先阅读前面的文章有助于更好的理解本文:
1. SpringBoot+vue 前后端分离,使用 SpringSecurity 完美处理权限问题 (一)
2. SpringBoot+Vue 前后端分离,使用 SpringSecurity 完美处理权限问题 (二)
密码加盐
密码要加盐处理,这是常识.各个权限处理框架对此都有不同程度的支持,Shiro,SpringSecurity 都有自家的解决方案,SpringSecurity 中有一个升级版的消息摘要:
BCryptPasswordEncoder
使用 BCryptPasswordEncoder,即使相同的明文,生成的新的加密字符串都是不一样的,这样可以避免像在 Shiro 中那样我们自己配置密码的盐,SpringSecurity 中使用 BCryptPasswordEncoder 的具体流程如下:
注册处理
在用户注册时,我们需要对密码进行处理,处理方式如下:
通过 BCryptPasswordEncoder 中的 encode 方法对密码进行处理.
public int hrReg(String username, String password) {
//如果用户名存在,返回错误
if (hrMapper.loadUserByUsername(username) != null) {
return - 1;
}
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
String encode = encoder.encode(password);
return hrMapper.hrReg(username, encode);
}
当用户注册成功之后,存在数据库中的密码就像下面这样:
登录处理
密码加密处理之后,登录时候也要对密码进行处理,修改 webSecurityConfig 类的 configure(AuthenticationManagerBuilder auth) 方法,改为下面这样即可:
异常统一处理
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(hrService).passwordEncoder(new BCryptPasswordEncoder());
}
如果不是前后端分离,一般出了异常都很容易处理,直接跳转到相关的错误页面即可,现在前后端分离,出了异常,就不能再跳转到错误页面了,但是我们可以返回 JSON 呀!我们可以对服务端可能发生的异常进行统一处理.
举个栗子:
当管理员想要删除某一个角色的时候,如果该角色下尚有关联的用户或者资源,此时由于数据库中外键的约束会导致删除失败(我的业务逻辑就是如此,这里小伙伴不要和我扯 cascade(*^_^*)),当删除失败时,会抛出一个 DataIntegrityViolationException 异常,我将这种异常捕获后统一处理.
处理方式如下:
自定义异常处理类
自定义异常处理类 CustomExceptionResolver,如下:
在这里接收到系统抛出的各种异常,判断异常的类型,根据不同的类型,返回不同的提示,当然,我这里只有一种情况.
public class CustomExceptionResolver implements HandlerExceptionResolver {@Override public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse response, Object o, Exception e) {
ModelAndView mv = new ModelAndView(new MappingJackson2JsonView());
Map < String,
String > map = new HashMap < >();
map.put("status", "error");
if (e instanceof DataIntegrityViolationException) {
map.put("msg", "该角色尚有关联的资源或用户,删除失败!");
}
mv.addAllObjects(map);
return mv;
}
}
将 CustomExceptionResolver 注册为一个 Bean
将 CustomExceptionResolver 注册为 Bean 就比较简单了,可以直接在类上添加 @Component 注解,也可以通过 Java 进行配置,如下:
两种方式任选一.
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Bean
public CustomExceptionResolver customExceptionResolver() {
return new CustomExceptionResolver();
}
}
来源: http://blog.csdn.net/u012702547/article/details/79037297