⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 blog.csdn.net/weixin_44102992/article/details/107335702 「Colins~」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

前言

提到权限管理这块肯定很多人第一想到的就是Springboot Security或者是Shiro安全框架,但本文介绍的并不是这两种,不是因为他们不好用,实在是自己太懒了,我觉得一个拦截器加上其他的一些处理就能满足项目的需求,我又何必去多用一个框架呢,这篇文章也不是去对比谁好谁坏,各位自行抉择。

我将权限管理分为三块:

  1. 资源权限:将url当做资源,可以给每个账号动态划分Url权限,访问不同的URl;
  2. 操作权限:将所有URL分为增、删、改、查4种操作权限,给用户分配对应的操作权限,如某个用户只有查操作权限那么他就无法做其他的操作;
  3. 角色权限:系统有多个角色,每个角色的权限都不同,如一个管理后台有着账号管理模块、商品模块等,为超级管理员的角色就可以看到所有模块并操作,而为售后的角色就只能看到商品模块,即使他知道账号管理模块下的URL也无权限操作。然后为用户设置角色就有对应的权限;

资源权限

1.静态资源准备

这里方便演示就不直接操作数据库了,对应的权限建表关系也很简单,这里直接建立静态的用户对应的URL关系。

public class Constant {
/**
* 权限管理
*/
public static Map<Integer,String[]> permission=new HashMap<>();
static {
String[] frist={"/url1","/url2","/url3","/url4","/url5","/url6","/url7"};//用户1所拥有的URL权限
String[] second={"/url1","/url2","/url3","/url4","/url5"};//用户2所拥有的URL权限
String[] third={"/url1","/url2","/url3"};//用户3所拥有的URL权限
permission.put(1,frist);
permission.put(2,second);
permission.put(3,third);

}
}

2.自定义一个异常,便于拦截抛出

public class APIException extends RuntimeException {
private static final long serialVersionUID = 1L;
private String msg;
public APIException(String msg) {
super(msg);
this.msg = msg;
}

}

3.全局异常处理

便于异常后返回统一规范的结果,正常应该是正常返回自定义Vo,但这里目标是为了演示结果,再加上各位应该都有自己的Vo类,所以这里就不用了

@RestControllerAdvice
public class WebExceptionControl {

@ExceptionHandler(APIException.class)
public String APIExceptionHandler(APIException e) {
return e.getMessage();
}
}

4.controller层

很简单创建对应的URL就好

5.拦截器创建

一般是要先验证token,后根据token取到用户对应信息,这里没有登录所以就直接在token里传对应用户的key值了

/**
* 权限管理URL拦截器
*/
public class URLInterceptor implements HandlerInterceptor {

// 预处理回调方法,在接口调用之前使用 true代表放行 false代表不放行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String token = httpServletRequest.getHeader("token");
String requestURL = httpServletRequest.getRequestURI();
//1.根据token判断用户是否登录
if (token==null){ //正常情况下这里还需判断与redis中的token是否匹配
// 如果没有token或者token不匹配, 直接抛出异常 提示未登录
throw new APIException("当前用户未登录");
}
//2.登录成功后 根据用户token中的信息获取到用户对应的URL权限集合
String[] strings = Constant.permission.get(Integer.valueOf(token));
boolean hasPermission = false;
//3.再根据用户对应的URL集合去与当前请求的URL对比 有匹配的则放行 反之则抛出异常
for (int i =0;i<strings.length;i++) {
if (strings[i].equals(requestURL)){
hasPermission = true;
break;
}
}
if (hasPermission){
return true;
}else {
throw new APIException("当前用户没有访问路径" + requestURL + "的权限");
}
}
}

6.将拦截器注入应用

@Configuration
public class WebMvcConfg implements WebMvcConfigurer {

@Override
public void addInterceptors(InterceptorRegistry registry) {
//权限拦截器
registry.addInterceptor(urlInterceptor()).addPathPatterns("/**");
}
@Bean
public URLInterceptor urlInterceptor(){
return new URLInterceptor();
}
}

7.验证查看结果

分别在token中传入用户1-3的key,访问不同url就可以看到效果,如下

操作权限

1.和上面一样使用静态资源

public class Constant {
/**
* 权限管理
*/
public static Map<Integer,String[]> permission=new HashMap<>();
static {
String[] frist={"insert","delete","select","update"};//用户1所拥有的操作权限
String[] second={"insert","select","update"};//用户2所拥有的URL权限
String[] third={"select"};//用户3所拥有的URL权限
permission.put(1,frist);
permission.put(2,second);
permission.put(3,third);

}
}

2.自定义注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UrlAnnotation {
/**
* 操作类型(type):添加,删除,修改,插入
*
*/
String type();
}

3.controller层

打上自定义的注解,代表对应方法是什么操作

4.修改一下之前的拦截器

添加对注解上面的操作类型的获取,并用type类型去对比判断

5.验证结果

其他都不变

角色权限

这里其实和上面的操作大同小异,我这里简单演示一下,以两个模块为例

1.静态对应关系

public class Constant {
/**
* 权限管理
*/
public static Map<Integer,String[]> permission=new HashMap<>();
static {
String[] frist={"test","test1"};//用户1所拥有的模块权限 这里的test是模块URL入口 例如:test模块下所有URL都是/test/**
String[] second={"test"};//用户2所拥有的模块权限
permission.put(1,frist); //这里的1其实是用户对应ID为1的角色
permission.put(2,second);//这个2同理

}

2.修改controller

模拟两个模块

3.修改一下拦截器

4.结果测试

总结

其实用自定义的拦截器去做权限,不管是什么类型其实都大同小异,根据需求灵活的去处理才是最重要的,上面的静态权限变通一下,建立角色表、用户表、路径表以及对应关系,就很容易做出URL的动态权限配置了,灵活运用自定义注解搭配可以做到更细致。

文章目录
  1. 1. 前言
  2. 2. 资源权限
    1. 2.1. 1.静态资源准备
    2. 2.2. 2.自定义一个异常,便于拦截抛出
    3. 2.3. 3.全局异常处理
    4. 2.4. 4.controller层
    5. 2.5. 5.拦截器创建
    6. 2.6. 6.将拦截器注入应用
    7. 2.7. 7.验证查看结果
  3. 3. 操作权限
    1. 3.1. 1.和上面一样使用静态资源
    2. 3.2. 2.自定义注解
    3. 3.3. 3.controller层
    4. 3.4. 4.修改一下之前的拦截器
    5. 3.5. 5.验证结果
  4. 4. 角色权限
    1. 4.1. 1.静态对应关系
    2. 4.2. 2.修改controller
    3. 4.3. 3.修改一下拦截器
    4. 4.4. 4.结果测试
  5. 5. 总结