SPRING註解形式實現許可權控制
今天看了一下黑馬程式設計師的視訊,上面講到一個使用spring AOP + 自定義註解的方式來實現許可權控制的一個小例子,個人覺得還是可以借鑑,整理出來與大家分享。
需求:service層有一些方法,這些方法需要不同的許可權才能訪問。
實現方案:自定義一個PrivilegeInfo的註解,使用這個註解為service層中的方法進行許可權配置,在aop中根據PrivilegeInfo註解的值,判斷使用者是否擁有訪問目標方法的許可權,有則訪問目標方法,沒有則給出提示。
關鍵技術:自定義註解及註解解析,spring aop
最終實現後的目錄結構:
具體步驟:
下面我們來具體實現這個需求。
首先來實現這個自定義註解,為了簡單起見,我們演示的這個註解,只是給了一個許可權名的屬性。
package privilege.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 許可權註解
* @author Minhellic
*
*/
@Target(ElementType.METHOD)//這個註解是應用在方法上
@Retention(RetentionPolicy.RUNTIME)
public @interface PrivilegeInfo {
/**
* 許可權的名稱
* @return
*/
String value() default "";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
為這個自定義的註解,寫一個解析器,主要是用於返回目標方法上的註解PrivilegeInfo設定的value值
package privilege.annotation;
import java.lang.reflect.Method;
/**
* 許可權註解解析器
* 這個解析器的主要功能,是解析目標方法上如果有PrivilegeInfo註解,那麼解析出這個註解中的value值(許可權的值)
* @author Minhellic
*
*/
public class PrivilegeAnnotationParse {
/**
* 解析註解
* @param targetClass 目標類的class形式
* @param methodName 在客戶端呼叫哪個方法,methodName就代表哪個方法
* @return
* @throws Exception
*/
public static String parse(Class targetClass, String methodName) throws Exception {
String methodAccess = "";
/*
* 為簡單起見,這裡考慮該方法沒有引數
*/
Method method = targetClass.getMethod(methodName);
//判斷方法上是否有Privilege註解
if (method.isAnnotationPresent(PrivilegeInfo.class)) {
//得到方法上的註解
PrivilegeInfo privilegeInfo = method.getAnnotation(PrivilegeInfo.class);
methodAccess = privilegeInfo.value();
}
return methodAccess;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
自定義的註解和解析器有了,我們把對應的Service層寫出來,並在需要使用這個註解配置許可權的方法上,新增上這個註解。我們知道Service層是由介面和實現類組成,這是規範,雖然對我們這次的演示沒有什麼作用,但我們還是遵守一下:
介面原始碼:
package privilege.service;
/**
* 使用者業務介面
* @author Minhellic
*
*/
public interface FirmService {
/**
* 在需要許可權的目標方法上,使用PrivilegeInfo註解,配置許可權為save
*/
public void save();
/**
* 在需要許可權的目標方法上,使用PrivilegeInfo註解,配置許可權為update
*/
public void update();
/**
* 不需要許可權的目標方法上,則不新增PrivilegeInfo註解
* 在切面中,預設使用者擁有許可權
*/
public void get();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
實現類原始碼:
package privilege.service.impl;
import privilege.annotation.PrivilegeInfo;
import privilege.service.FirmService;
/**
* 使用者業務實現
* @author Minhellic
*
*/
public class FirmServiceImpl implements FirmService {
/**
* 在需要許可權的目標方法上,使用PrivilegeInfo註解,配置許可權
*/
@Override
@PrivilegeInfo("save")
public void save() {
System.out.println("FirmServiceImpl.save()");
}
/**
* 在需要許可權的目標方法上,使用PrivilegeInfo註解,配置許可權
*/
@Override
@PrivilegeInfo("update")
public void update() {
System.out.println("FirmServiceImpl.update()");
}
/**
* 不需要許可權的目標方法上,則不新增PrivilegeInfo註解
* 在切面中,預設使用者擁有許可權
*/
@Override
public void get() {
System.out.println("FirmServiceImpl.get()");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
為了更好地管理許可權,我們專門建立一個許可權類,當然,為了簡單,這裡還是隻封裝了許可權的名稱
package privilege.userprivilege;
/**
* 封裝使用者許可權
* 為簡單,只封裝了許可權的名稱
* @author Minhellic
*
*/
public class FirmPrivilege {
/**
* 使用者許可權的名稱
*/
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public FirmPrivilege(String value) {
this.value = value;
}
public FirmPrivilege() {
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
現在Service層和註解都已經有了,就需要寫切面的程式碼了。
在切面中,我們使用環繞通知,在呼叫目標方法之前,我們先用目標方法上的PrivilegeInfo註解配置的許可權,與使用者擁有的許可權進行匹配,如果匹配成功,則認為使用者擁有這個目標方法的許可權,則呼叫目標方法,否則,給出提示資訊,不呼叫目標方法。
這裡之所以不使用前置通知的方式來匹配許可權,就是因為前置通知雖然也可以檢查,但是無論檢查是否通過,目標方法都會被呼叫,起不到根據許可權來控制目標方法呼叫的目的。
package privilege.aspect;
import java.util.List;
import org.aspectj.lang.ProceedingJoinPoint;
import privilege.annotation.PrivilegeAnnotationParse;
import privilege.userprivilege.FirmPrivilege;
/**
* 許可權檢查切面
* 根據使用者原有的許可權,與目標方法的許可權配置進行匹配,
* 如果目標方法需要的許可權在使用者原有的許可權以內,則呼叫目標方法
* 如果不匹配,則不呼叫目標方法
* @author Minhellic
*
*/
public class PrivilegeAspect {
/**
* 使用者本身的許可權
*/
private List<FirmPrivilege> privileges;
public List<FirmPrivilege> getPrivileges() {
return privileges;
}
public void setPrivileges(List<FirmPrivilege> privileges) {
this.privileges = privileges;
}
/**
* aop中的環繞通知
* 在這個方法中檢查使用者的許可權和目標方法的需要的許可權是否匹配
* 如果匹配則呼叫目標方法,不匹配則不呼叫
* @param joinPoint 連線點
* @throws Throwable
*/
public void isAccessMethod(ProceedingJoinPoint joinPoint) throws Throwable {
/**
* 1.獲取訪問目標方法應該具備的許可權
* 為解析目標方法的PrivilegeInfo註解,根據我們定義的解析器,需要得到:目標類的class形式 方法的名稱
*/
Class targetClass = joinPoint.getTarget().getClass();
String methodName = joinPoint.getSignature().getName();
//得到該方法的訪問許可權
String methodAccess = PrivilegeAnnotationParse.parse(targetClass, methodName);
/*
* 2.遍歷使用者的許可權,看是否擁有目標方法對應的許可權
*/
boolean isAccessed = false;
for (FirmPrivilege firmPrivilege : privileges) {
/*
* 如果目標方法沒有使用PrivilegeInfo註解,則解析出來的許可權字串就為空字串
* 則預設使用者擁有這個許可權
*/
if ("".equals(methodAccess)) {
isAccessed = true;
break;
}
/*
* 使用者原有許可權列表中有的許可權與目標方法上PrivilegeInfo註解配置的許可權進行匹配
*/
if (firmPrivilege.getValue() != null &&
firmPrivilege.getValue().equalsIgnoreCase(methodAccess)) {
isAccessed = true;
break;
}
}
/*
* 3.如果使用者擁有許可權,則呼叫目標方法 ,如果沒有,則不呼叫目標方法,只給出提示
*/
if (isAccessed) {
joinPoint.proceed();//呼叫目標方法
} else {
System.out.println("你沒有許可權");
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
最後,配置好spring的配置檔案,要使用spring aop,配置檔案中,必須包含有aop的名稱空間,並引入相應的xsd
配置檔案的原始碼為:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<bean id="firmService" class="privilege.service.impl.FirmServiceImpl"></bean>
<bean id="privilegeAspect" class="privilege.aspect.PrivilegeAspect"></bean>
<!-- 配置切面 -->
<aop:config>
<!--
切入點表示式,確認目標類
privilege.service.impl包中的所有類中的所有方法
-->
<aop:pointcut expression="execution(* privilege.service.impl.*.*(..))" id="perform"/>
<!-- ref指向的物件就是切面 -->
<aop:aspect ref="privilegeAspect">
<!-- 環繞通知 -->
<aop:around method="isAccessMethod" pointcut-ref="perform"/>
</aop:aspect>
</aop:config>
</beans>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
所有的工作都已做好,我們來測試一下:
package privilege.test;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import privilege.aspect.PrivilegeAspect;
import privilege.service.FirmService;
import privilege.userprivilege.FirmPrivilege;
/**
* aop+註解許可權控制測試類
*
* @author Minhellic
*
*/
public class PrivilegeTest {
/**
* 客戶端直接呼叫這個Service的方法,而不需要關心許可權問題
*/
private FirmService firmService;
/**
* 在初始化方法中,初始化firmService
* 同時為使用者賦上原始許可權,這個在專案中,會使用別的方式實現,這裡只是模擬,就不搞那麼複雜了
*/
@Before
public void init() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
firmService = (FirmService) context.getBean("firmService");
/*
* 給使用者新增預設許可權
*/
PrivilegeAspect privilegeAspect = (PrivilegeAspect) context.getBean("privilegeAspect");
List<FirmPrivilege> privileges = new ArrayList<FirmPrivilege>();
//privileges.add(new FirmPrivilege("save"));
privileges.add(new FirmPrivilege("update"));
privilegeAspect.setPrivileges(privileges);
}
/**
* 客戶端直接呼叫Service中的方法,而不需要關心許可權問題,會有切面去做
*/
@Test
public void test() {
firmService.save();
firmService.update();
firmService.get();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
執行test方法,根據控制檯的輸出結果,就可以看到許可權控制是起到了作用,因為使用者初始許可權中的save許可權被註釋掉,則使用者不會擁有save許可權,呼叫save方法時,提示沒有許可權。
從上面的測試方法可以看出,使用了aop之後,我們只需要關心主要業務,而不需要再分心去管理許可權問題。
這篇部落格,雖是我本人整理,但所有的思路及實現方式,都來源於黑馬程式設計師的視訊,算是半原創吧。如寫得很爛,歡迎大神
相關推薦
SPRING註解形式實現許可權控制
今天看了一下黑馬程式設計師的視訊,上面講到一個使用spring AOP + 自定義註解的方式來實現許可權控制的一個小例子,個人覺得還是可以借鑑,整理出來與大家分享。 需求:service層有一些方法,這些方法需要不同的許可權才能訪問。 實現方案:自定義一個Privilege
Spring AOP自定義註解實現許可權控制
1.建立註解類,controller控制層使用該註解進行許可權控制使用 import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.R
spring boot註解實現許可權控制
1、自定義註解 Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface RoleCheck { String[] roles() default
Spring Boot 整合 Shiro實現許可權控制,親測可用,附帶sql
前提: 本文主要講解Spring Boot 與 Shiro的整合 與許可權控制的實現方式(主要以程式碼實現功能為主),主要用到的技術Spring Boot+Shiro+Jpa(通過Maven構建),並不會涉及到Shiro框架的原始碼分析 如果有想要學習Shiro框架的小夥伴可以去http://shiro.
在Spring Boot中使用Spring Security實現許可權控制
Spring Boot框架我們前面已經介紹了很多了,相信看了前面的部落格的小夥伴對Spring Boot應該有一個大致的瞭解了吧,如果有小夥伴對Spring Boot尚不熟悉,可以先移步這裡從SpringMVC到Spring Boot,老司機請略過。OK,那我們
SpringBoot中使用Spring Security實現許可權控制
Spring Security,這是一個專門針對基於Spring的專案的安全框架,它主要是利用了AOP來實現的。以前在Spring框架中使用Spring Security需要我們進行大量的XML配置,但是,Spring Boot針對Spring Security
【Spring MVC】教程——使用攔截器實現許可權控制
之前一直都在用mvc的攔截器許可權控制,後來上網也研究了一些這方面的知識,下面就直接分享下我對mvc的攔截器的理解,通過專案來分析吧。。。 1、首先準備對應的架包 2、看看專案的架構 3、基本的web.xml檔案 ? 1 2 3 4 5 6 7 8 9 10 11
基於Spring框架應用的許可權控制系統的研究和實現
摘 要: Spring框架是一個優秀的多層J2EE系統框架,Spring本身沒有提供對系統的安全性支援。Acegi是基於Spring IOC 和 AOP機制實現的一個安全框架。本文探討了Acegi安全框架中各部件之間的互動,並通過擴充套件Acegi資料庫設計來實現基於Spring框架的應用的安全控制方法。
註解形式實現SpringBoot結合RabbitMq
匯入相關依賴 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId&
註解形式實現,Redis分散式鎖
Redis工具類參考我的博文:https://blog.csdn.net/weixin_38399962/article/details/82753763 一個註解就可以實現分散式鎖?這麼神奇麼? 首先定義註解: /** * Description:分散式Redis鎖 * User:
springboot使用Spring Security+OAuth2做許可權控制
文章來源:http://lxgandlz.cn/404.html 前面有一篇文章Spring+Spring Security+OAuth2實現REST API許可權控制,講了Spring+Spring Security+OAuth2來實現REST API許可權
javaEE shiro框架,許可權控制。基於Spring框架的shiro許可權控制
許可權控制的方式: 方式一:通過過濾器或Struts2的攔截器實現許可權控制 方式二:為Struts2的Action加入註解(標識),然後為Action建立代理物件;代理物件進行許可權校驗,校驗通過後通過反射呼叫目標方法。 shiro框架可以進行認證、授權、會話管理、加
Spring整合Shiro做許可權控制模組詳細案例分析
1.引入Shiro的Maven依賴 <!-- Spring 整合Shiro需要的依賴 --> <dependency> <groupId>org.apache.shiro</groupId> <artifac
Shiro——實現許可權控制demo思路(包含自定義標籤hasAnyPermission)
在很多系統中需要使用許可權控制,來控制不同角色的人訪問不同的資源。表達能力不好,不喜勿噴! 環境:eclipse4.5.2+oracle11g+hibernate4+spring4+shiro+jboss 原始碼(工程)+ 資料表sql(包含初始化資料)+hibernat
Taurus.MVC 2.2.3.4 :WebAPI 實現許可權控制認證(及功能增強說明)
前言: 前兩天,當我還在老家收拾行旅,準備回廣州,為IT連的創業再戰365天時, 有網友扣上問:Taurus.MVC中如何實現認證和許可權控制,最好能做個小例子。 我一不小心回了句:等回廣州我再寫篇文章...... 然後,今天就來補文章了〜〜〜〜 Taurus.MVC Nuget 更新: 寫文之前
第7篇:ui-router登入檢查實現許可權控制
做專案時用到了前端登入檢查實現使用者許可權控制,在angularJS外掛中用到了ui-router,可以利用本地儲存實現對登入狀態的監聽,實現如下: 1)登入成功,將登入資訊寫入本地儲存: $.ajax({ type: 'POST',
springboot整合shiro 實現許可權控制
shiro apache shiro 是一個輕量級的身份驗證與授權框架,與spring security 相比較,簡單易用,靈活性高,springboot本身是提供了對security的支援,畢竟是自家的東西。springboot暫時沒有整合shiro,這得自
springboot2.0--結合spring security5.0進行許可權控制,從資料庫中取許可權資訊及增加驗證碼
1.在pom.xml中增加spring security jar的引用: <!--引入spring security--> <dependency> <groupId>org.springframework
ASP.net Menu控制元件動態新增選單項實現許可權控制
對於動態選單生成,在很多具有許可權控制的專案中非常常見。最近遇到一個需求就是不同使用者具有不同許可權,該許可權是頁面級的,所以需要根據不同使用者的許可權情況動態生成選單項。 首先,我把選單項中的內容先儲存在一個XML裡面,在載入模板頁時只需根據查詢
spring註解方式實現事務
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001