SpringBoot中使用自定义注解和拦截器实现简单的权限控制
前言
众所周知,作为系统的最后一道防线,对于一些重要操作(crud等),后端默认接收的所有的请求都是“不可信”的,除了确认用户登录状态之外,还要对接收的数据进行一系列的合法性校验等等,即使已经在前端页面对用户输入信息做了一定的限制。因为请求可以伪造,也可能被拦截篡改,即使在正常情况下,用户也可能因为误操作或者恶意行为发送不合法的请求。
如果多角色系统的接口不做权限校验的话,那无疑是在“裸奔”,任何一个普通的登录用户都能调用所有的接口。
Q:什么是权限控制?
A:让特定的用户只能访问特定的资源。
在实际项目中,如果权限控制需要复杂的逻辑或者需要非常细致的权限划分,可能需要借助专门的权限框架,主流的权限框架有
Spring Security https://spring.io/projects/spring-security
Spring Security 是一个功能强大、高度可定制的身份验证和访问控制框架。它是确保基于 Spring 的应用程序安全的事实标准。
Spring Security 是一个专注于为 Java 应用程序提供身份验证和授权的框架。与所有 Spring 项目一样,Spring Security 的真正威力在于它可以轻松扩展以满足自定义需求Apache Shiro https://shiro.apache.org/
Apache Shiro™ 是一个功能强大且易于使用的 Java 安全框架,可执行身份验证、授权、加密和会话管理。利用 Shiro 易于理解的 API,您可以快速、轻松地保护任何应用程序的安全–从最小的移动应用程序到最大的网络和企业应用程序。
虽然上述的框架功能十分完备,但是对于只有两三个角色的系统来说,杀鸡焉用宰牛刀啊,通过使用SpringBoot框架提供的自定义注解和拦截器功能,可以轻松地实现对不同用户角色的访问权限控制。
本文用例说明:
系统有三种角色,管理员、教师、学生。
在数据库用户表中,用户类型字段以tinyint存储,3代表管理员,2代表教师,1代表学生。
功能需求:有些接口只能管理员访问,有些接口可以让管理员和老师访问,有些接口只能学生访问。
定义权限常量
在项目下新建constant包,并新建接口用于定义角色权限常量
1 | public interface UserConstant { |
定义Access注解
新建annotation包,在包下新建一个Access注解,用于权限控制
1 | import java.lang.annotation.*; |
新建权限拦截器
1 | /** |
注册拦截器
将权限拦截器添加到登录拦截器后面,拦截器将会在请求处理过程中按照它们被添加的顺序依次执行。
1 |
|
在controller方法上加注解
在需要进行权限校验的接口方法上使用@Access
,在注解数组中填入之前定义的常量即可,例如下面的例子表示只有学生用户和管理员用户才可以访问接口。如果没有标记权限注解,或者注解中数组为空,则不会验证该接口请求的权限。
1 |
|
以上实现了一种在注解中枚举角色的权限控制方法,可以实现简单而灵活的权限控制,保护我们的应用程序免受未经授权的访问。这样使用数组定义注解,好处是自定义程度高,可以指定哪(几)个角色,从而更加精细的控制访问权限,缺点是用户角色较多时,注解添加会比较麻烦。
如果权限划分是分层级的话(例如:超级无敌管理员>超级管理员>普通管理员,高权限用户可以向下访问低权限用户的所有接口,低权限用户不能向上访问),可以将注解里的roles改成整形,并修改权限拦截器,将判定条件修改成比较权限值的大小,只要用户的权限的数值高于接口权限就放行。