SpringBoot使用AOP實現(xiàn)統(tǒng)一角色權(quán)限校驗
一、引入AOP starter
在tg-book-common中引入依賴:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
對于spring boot的starter,我在之前的文章中已經(jīng)反復(fù)說明過多次,不做贅述!
本項目中已經(jīng)使用中的starter如下:
- spring-boot-starter-web
- spring-boot-starter-logging
- mybatis-spring-boot-starter
- pagehelper-spring-boot-starter
二、創(chuàng)建切面@Aspect + 定義切點@Pointcut
@Aspect
注解方式,它的概念像@Aspect、@Pointcut、@Before、@After、@Around等注解都是來自于 AspectJ,但是功能的實現(xiàn)是純 Spring AOP 自己實現(xiàn)的,主要有兩大核心
:
- 定義[切入點]:使用 @Pointcut 切點表達式,你可以理解成類似于正則表達式的強大東東。(例如本文的@annotation方式)
- 定義[切入時機] 和 [增強處理邏輯]:五種通知Advice注解 對[切入點]執(zhí)行增強處理, 包括:@Before、@After、@AfterRunning、@AfterThrowing、@Around
以下使用@Aspect 定義一個切面類,使用@Pointcut定義一個切點,切點表達式使用@annotation方式,也就是注解的方式。
// @Aspect和@Component定義一個切面類,@Slf4j是之前講過的日志注解 @Component @Aspect @Slf4j public class RoleAspect { // 核心一:定義切點(使用@annotation方式) @Pointcut(value = "@annotation( org.tg.book.common.annotation.Role)") public void pointCut() {} }
三、封裝校驗@Role角色權(quán)限的方法
本文的AOP是上文攔截器Interceptor的另一種實現(xiàn)方式,所以請將上文的AuthInterceptor中的如下代碼注釋:
然后把這段代碼拿過來,封裝成一個方法,放到RoleAspect
中如下:
/** * 將@Role與登錄用戶的角色對比,如果是管理員返回true **/ private boolean checkAdminRole(Role role) { // 校驗角色 if (role != null) { // 走到這,說明方法上加了@Role boolean isAdmin = false; AuthContextInfo authInfo = AuthContextInfo.getAuthInfo(); for (int roleId : role.roleIds()) { if (authInfo.getRoleId().equals(roleId)) { isAdmin = true; break; } } if (!isAdmin) { log.info("[403]無權(quán)限, authInfo={}", authInfo); return false; } } return true; }
方法邏輯很簡單:將@Role與登錄用戶的角色對比,如果是管理員返回true,否則返回false
四、AOP兩種實現(xiàn)方式
4.1 前置通知@Before方式
因為角色權(quán)限校驗代碼,發(fā)生于【業(yè)務(wù)方法代碼】之前,所以可以使用前置通知@Before方式,代碼如下:
@Before("pointCut()") public void before(JoinPoint joinPoint) throws NoSuchMethodException { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Class<?> clazz = joinPoint.getTarget().getClass(); Method method = clazz.getMethod(signature.getName(), signature.getParameterTypes()); Role role = method.getAnnotation(Role.class); boolean isAdminRole = checkAdminRole(role); if (!isAdminRole) { throw new RuntimeException("無權(quán)限"); } }
核心邏輯是獲得@Role注解,然后進行校驗,如果非管理員,則
拋出異常
。這里實現(xiàn)的比較簡單,當(dāng)后面我們實現(xiàn)了【全局異常處理】以后,這里就可以換成自定義的異常類,交給【全局異常處理】統(tǒng)一處理!
4.2 環(huán)繞通知@Around方式
如果不拋出異常的話,如何處理?
可以使用@Around方式,環(huán)繞通知@Around可以控制在【業(yè)務(wù)方法代碼】之前校驗,并且可以返回結(jié)果
,所以我們就不需要拋出異常了!
@Around("pointCut()") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Class<?> clazz = joinPoint.getTarget().getClass(); Method method = clazz.getMethod(signature.getName(), signature.getParameterTypes()); Role role = method.getAnnotation(Role.class); boolean isAdminRole = checkAdminRole(role); if (!isAdminRole) { return TgResult.fail("403", "無權(quán)限"); } return joinPoint.proceed(); }
獲取Role 之前的代碼都是一模一樣的,區(qū)別就是這里沒有拋出異常,而是返回統(tǒng)一結(jié)果TgResult,這也正是封裝統(tǒng)一返回結(jié)果的好處之一?。。?/p>
特別注意: before和around是兩種實現(xiàn)方式,所以不必在意從joinPoint得到role的重復(fù)代碼,因為最終只會寫一份代碼,對于before和around我更建議使用around的方式!
以上就是SpringBoot使用AOP實現(xiàn)統(tǒng)一角色權(quán)限校驗的詳細內(nèi)容,更多關(guān)于SpringBoot AOP統(tǒng)一角色權(quán)限校驗的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot如何實現(xiàn)starter原理詳解
這篇文章主要介紹了SpringBoot如何實現(xiàn)starter原理詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-06-06Java面試重點中的重點之Elasticsearch核心原理
ElasticSearch是一個基于Lucene的搜索引擎,是用Java語言開發(fā)的,能夠達到實時搜索,穩(wěn)定,可靠,快速,安裝使用方便,作為Apache許可條款下的開放源碼發(fā)布,是一種流行的企業(yè)級搜索引擎,是最受歡迎的企業(yè)搜索引擎2022-01-01elasticsearch索引創(chuàng)建create?index集群matedata更新
這篇文章主要介紹了elasticsearch索引創(chuàng)建create?index及集群matedata更新,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-04-04IntelliJ IDEA Java項目手動添加依賴 jar 包的方法(圖解)
這篇文章主要介紹了IntelliJ IDEA Java項目手動添加依賴 jar 包,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-04-04零基礎(chǔ)如何系統(tǒng)的學(xué)習(xí)Java
這篇文章主要介紹了零基礎(chǔ)如何系統(tǒng)的學(xué)習(xí)Java,很多朋友糾結(jié)這個問題,教材書不知道從何學(xué)起,今天小編給大家分享一篇教程幫助到家梳理這方面的知識2020-07-07