SpringBoot中运用自界说注解和拦截器实现简略的权限操控
本文首发在我的个人站点:追逐日落,欢迎大家前去参观~
前言
众所周知,作为体系的最终一道防地,关于一些重要操作(crud等),后端默认接收的一切的恳求都是“不可信”的,除了确认用户登录状况之外,还要对接收的数据进行一系列的合法性校验等等,即便已经在前端页面对用户输入信息做了必定的约束。因为恳求能够假造,也或许被拦截篡改,即便在正常情况下,用户也或许因为误操作或许歹意行为发送不合法的恳求。
假如多人物体系的接口不做权限校验的话,那无疑是在“裸奔”,任何一个一般的登录用户都能调用一切的接口。
Q:什么是权限操控?
A:让特定的用户只能拜访特定的资源。
在实际项目中,假如权限操控需求杂乱的逻辑或许需求非常详尽的权限区分,或许需求凭借专门的权限结构,干流的权限结构有
-
Spring Security spring.io/projects/sp…
Spring Security 是一个功用强大、高度可定制的身份验证和拜访操控结构。它是确保基于 Spring 的应用程序安全的事实标准。 Spring Security 是一个专注于为 Java 应用程序提供身份验证和授权的结构。与一切 Spring 项目一样,Spring Security 的真实威力在于它能够轻松扩展以满足自界说需求
-
Apache Shiro shiro.apache.org/
Apache Shiro™ 是一个功用强大且易于运用的 Java 安全结构,可执行身份验证、授权、加密和会话管理。利用 Shiro 易于理解的 API,您能够快速、轻松地维护任何应用程序的安全–从最小的移动应用程序到最大的网络和企业应用程序。
尽管上述的结构功用非常齐备,但是关于只要两三个人物的体系来说,杀鸡焉用宰牛刀啊,经过运用SpringBoot结构提供的自界说注解和拦截器功用,能够轻松地实现对不同用户人物的拜访权限操控。
本文用例阐明:
体系有三种人物,管理员、教师、学生。
在数据库用户表中,用户类型字段以tinyint存储,3代表管理员,2代表教师,1代表学生。
功用需求:有些接口只能管理员拜访,有些接口能够让管理员和老师拜访,有些接口只能学生拜访。
界说权限常量
在项目下新建constant包,并新建接口用于界说人物权限常量
public interface UserConstant {
int USER_TYPE_ADMIN = 3; // 管理员
int USER_TYPE_TEACHER = 2; // 教师
int USER_TYPE_STUDENT = 1; // 学生
int USER_TYPE_LOGIN = 0; // 登录未认证身份用户
}
界说Access注解
新建annotation包,在包下新建一个Access注解,用于权限操控
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Access {
int[] roles() default {};
}
新建权限拦截器
/**
* 权限拦截器
*/
@Component
public class AccessInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if (!(handler instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
Access access = method.getAnnotation(Access.class);
//假如role是空的,阐明不需求权限,直接放行
if (access.roles().length == 0) {
log.info("access " + method.getName() + "role是空的");
return true;
}
//假如是指定人物(们)才能拜访的权限
//获取登录用户信息的办法
User user = ......<补全>.......;
//假如用户类型在权限数组中,阐明权限足够
if (Arrays.asList(access.roles()).contains(user.getType())) {
return true;
} else {
response.setStatus(403);
return false;
}
}
}
注册拦截器
将权限拦截器增加到登录拦截器后边,拦截器将会在恳求处理过程中依照它们被增加的次序顺次执行。
@Configuration
public class RequestInterceptor implements WebMvcConfigurer {
@Resource
private AccessInterceptor accessInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 登录拦截器
// registry.addInterceptor(loginInterceptor);
registry.addInterceptor(accessInterceptor);
}
}
在controller办法上加注解
在需求进行权限校验的接口办法上运用@Access
,在注解数组中填入之前界说的常量即可,例如下面的例子表示只要学生用户和管理员用户才能够拜访接口。假如没有符号权限注解,或许注解中数组为空,则不会验证该接口恳求的权限。
@GetMapping("/hello")
@Access(roles = {UserConstant.USER_TYPE_STUDENT,UserConstant.USER_TYPE_ADMIN})
public BaseResponse<List<Activity>> hello(){
//一致回来结果类,回来一致格局的响应
return ResultUtil.success(activityService.list());
}
以上实现了一种在注解中枚举人物的权限操控办法,能够实现简略而灵敏的权限操控,维护我们的应用程序免受未经授权的拜访。这样运用数组界说注解,优点是自界说程度高,能够指定哪(几)个人物,然后更加精细的操控拜访权限,缺点是用户人物较多时,注解增加会比较费事。
假如权限区分是分层级的话(例如:超级无敌管理员>超级管理员>一般管理员,高权限用户能够向下拜访低权限用户的一切接口,低权限用户不能向上拜访),能够将注解里的roles改成整形,并修正权限拦截器,将判定条件修正成比较权限值的巨细,只要用户的权限的数值高于接口权限就放行。