最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringAOP實(shí)現(xiàn)自定義接口權(quán)限控制

 更新時(shí)間:2023年11月06日 10:34:34   作者:禿了也弱了。  
本文主要介紹了SpringAOP實(shí)現(xiàn)自定義接口權(quán)限控制,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

一、接口鑒權(quán)方案分析

1、接口鑒權(quán)方案

目前大部分接口鑒權(quán)方案,一般都是采用 【用戶-角色-權(quán)限】模型。

將接口與權(quán)限進(jìn)行編碼死綁定,同時(shí)角色與權(quán)限進(jìn)行動(dòng)態(tài)綁定,用戶與角色也進(jìn)行動(dòng)態(tài)綁定。

2、角色分配權(quán)限樹(shù)

創(chuàng)建用戶之后,用戶可以分配多個(gè)角色。

創(chuàng)建角色之后,通過(guò)查詢代碼內(nèi)置的權(quán)限樹(shù),進(jìn)行角色與權(quán)限綁定,存入數(shù)據(jù)庫(kù)中

二、編碼實(shí)戰(zhàn)

1、定義權(quán)限樹(shù)與常用方法

使用枚舉進(jìn)行權(quán)限的定義,通過(guò)四級(jí)權(quán)限樹(shù),將權(quán)限分為模塊、單元、功能級(jí)、接口。接口權(quán)限精細(xì)分配:

/**
 * 接口權(quán)限枚舉定義類
 */
public enum AuthPermission {
    /**
     * 四級(jí)權(quán)限樹(shù)
     * 1 模塊
     * - 2 功能
     * - - 3 接口集(一般是Controller)
     * - - - 4 具體接口(@RequestMapping)
     *
     */

    // 用戶管理
    User("user", "用戶", Type.Module),

    SysUser(User, "系統(tǒng)用戶", Type.Unit),
    SysUserManager(SysUser, "系統(tǒng)用戶管理", Type.Bunch),
    SysUserManagerSelect(SysUserManager, "系統(tǒng)用戶查詢", Type.Function),
    SysUserManagerAdd(SysUserManager, "系統(tǒng)用戶新增", Type.Function),
    SysUserManagerUpdate(SysUserManager, "系統(tǒng)用戶修改", Type.Function),
    SysUserManagerDelete(SysUserManager, "系統(tǒng)用戶刪除", Type.Function),

    NormalUser(User, "普通用戶", Type.Unit),
    NormalUserManager(NormalUser, "普通用戶管理", Type.Bunch),
    NormalUserManagerSelect(NormalUserManager, "普通用戶查詢", Type.Function),
    NormalUserManagerAdd(NormalUserManager, "普通用戶新增", Type.Function),
    NormalUserManagerUpdate(NormalUserManager, "普通用戶修改", Type.Function),
    NormalUserManagerDelete(NormalUserManager, "普通用戶刪除", Type.Function),

    // 訂單管理
    Order("order", "訂單", Type.Module),

    OrderConfirm(Order, "下單管理", Type.Unit),
    OrderConfirmKill(OrderConfirm, "秒殺下單管理", Type.Bunch),
    OrderConfirmKillAdd(OrderConfirmKill, "秒殺訂單新增", Type.Function),
    OrderConfirmKillDelete(OrderConfirmKill, "秒殺訂單刪除", Type.Function),

    OrderConfirmNormal(OrderConfirm, "普通下單管理", Type.Bunch),
    OrderConfirmNormalAdd(OrderConfirmNormal, "普通訂單新增", Type.Function),
    OrderConfirmNormalDelete(OrderConfirmNormal, "普通訂單刪除", Type.Function),

    // ...其他
    ;


    /**
     * 功能權(quán)限類型
     */
    public enum Type {
        Module, // 功能模塊
        Unit, // 功能單元
        Bunch, // 功能接口集
        Function, // 功能接口
    }

    // 模塊
    private final String module;
    // 名稱
    private final String title;
    // 父
    private final AuthPermission parent;
    // 類型
    private final Type type;

    AuthPermission(AuthPermission parent, String title, Type type) {
        this(parent.module, parent, title, type);
    }

    AuthPermission(String title, String module, Type type) {
        this(module, null, title, type);
    }

    AuthPermission(String module, AuthPermission parent, String title, Type type) {
        this.module = module;
        this.title = title;
        this.parent = parent;
        this.type = type;
    }

    public String getModule() {
        return module;
    }

    public String getTitle() {
        return title;
    }

    public AuthPermission getParent() {
        return parent;
    }

    public Type getType() {
        return type;
    }
}

import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 接口權(quán)限管理類
 */
public class AuthPermissionManagement {

    private static List<AuthArchetype> permissionTree = new ArrayList<>();

    private static Map<AuthPermission, AuthArchetype> permissionMap = new HashMap<>();

    static {
        // 遞歸設(shè)置樹(shù)
        // 設(shè)置子樹(shù)
        recursePermissions(permissionTree, permissionMap, null);
    }

    public static void main(String[] args) {
    	// 獲取權(quán)限樹(shù)(到時(shí)候給前端展示樹(shù))
        System.out.println(Json.toJson(getPermissionTree()));

		// 校驗(yàn)權(quán)限
        System.out.println(checkPermission(AuthPermission.NormalUserManagerDelete, AuthPermission.NormalUser));
        System.out.println(checkPermission(AuthPermission.NormalUserManagerDelete, AuthPermission.OrderConfirm));
        System.out.println(checkPermission(AuthPermission.NormalUserManagerDelete, AuthPermission.NormalUserManagerDelete));

    }

    /**
     * 校驗(yàn)權(quán)限 遞歸
     * @param userPermission 用戶角色權(quán)限
     * @param interfacePermission 接口權(quán)限
     * @return
     */
    public static boolean checkPermission(AuthPermission userPermission, AuthPermission interfacePermission) {
        if (userPermission == interfacePermission) {
            return true;
        }
        // 有子接口權(quán)限也可
        AuthArchetype authArchetype = permissionMap.get(interfacePermission);
        if (authArchetype == null) {
            return false;
        }
        return checkChildrenPermission(userPermission, authArchetype);
    }

    private static boolean checkChildrenPermission(AuthPermission userPermission, AuthArchetype authArchetype) {
        if (authArchetype.getName().equals(userPermission.name())) {
            return true;
        }
        if (!CollectionUtils.isEmpty(authArchetype.getSubPermissions())) {
            for (AuthArchetype subPermission : authArchetype.getSubPermissions()) {
                if (subPermission.getName().equals(userPermission.name())) {
                    return true;
                }
                // 遞歸
                if (checkChildrenPermission(userPermission, subPermission)) {
                    return true;
                }
            }
        }
        return false;
    }

    // 獲取權(quán)限樹(shù)
    public static List<AuthArchetype> getPermissionTree() {
        return permissionTree;
    }

    private static void recursePermissions(List<AuthArchetype> permissionTree, Map<AuthPermission, AuthArchetype> permissionMap, AuthPermission current) {
        for (AuthPermission permission : AuthPermission.values()) {
            if (permission.getParent() == current) {
                AuthArchetype permissionArchetype = new AuthArchetype(permission);
                if (current == null) {
                    permissionTree.add(permissionArchetype);
                } else {
                    permissionMap.get(current).addSubPermission(permissionArchetype);
                }
                permissionMap.put(permission, permissionArchetype);
                recursePermissions(permissionTree, permissionMap, permission);

            }

        }
    }


    public static class AuthArchetype {
        // name
        private String name;
        // 模塊
        private String module;
        // 名稱
        private String title;
        // 父
        private AuthPermission parent;
        // 類型
        private AuthPermission.Type type;
        // 子
        private List<AuthArchetype> subPermissions;

        public AuthArchetype(AuthPermission permission) {
            this.name = permission.name();
            this.module = permission.getModule();
            this.title = permission.getTitle();
            this.parent = permission.getParent();
            this.type = permission.getType();
        }

        public void addSubPermission(AuthArchetype subPermission) {
            if (this.subPermissions == null) {
                this.subPermissions = new ArrayList<>();
            }
            this.subPermissions.add(subPermission);
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getModule() {
            return module;
        }

        public void setModule(String module) {
            this.module = module;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public AuthPermission getParent() {
            return parent;
        }

        public void setParent(AuthPermission parent) {
            this.parent = parent;
        }

        public AuthPermission.Type getType() {
            return type;
        }

        public void setType(AuthPermission.Type type) {
            this.type = type;
        }

        public List<AuthArchetype> getSubPermissions() {
            return subPermissions;
        }

        public void setSubPermissions(List<AuthArchetype> subPermissions) {
            this.subPermissions = subPermissions;
        }
    }
}

2、自定義AOP注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Auth {

    AuthPermission[] value() default {};
}

3、AOP切面類(也可以用攔截器實(shí)現(xiàn))

import org.apache.commons.lang3.ArrayUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Component
public class AuthAdvice {

    /**
     * 我們希望的是如果方法上有注解,則對(duì)方法進(jìn)行限制,若方法上無(wú)注解,單是類上有注解,那么類上的權(quán)限注解對(duì)該類下所有的接口生效。
     */
    @Around("@annotation(com.qstcloud.athena.opencourse.auth.Auth) || @within(com.qstcloud.athena.opencourse.auth.Auth)")
    public Object preAuth(ProceedingJoinPoint point) throws Throwable {
        if (handleAuth(point)) {
            return point.proceed();
        }
        throw new RuntimeException("權(quán)限不足,請(qǐng)求被拒絕");
    }

    /**
     * 邏輯判斷,返回true or false
     * true :權(quán)限校驗(yàn)通過(guò)
     * false :權(quán)限校驗(yàn)不通過(guò)
     */
    private boolean handleAuth(ProceedingJoinPoint point) {
        MethodSignature ms = point.getSignature() instanceof MethodSignature ? (MethodSignature) point.getSignature() : null;
        Method method = ms.getMethod();
        // 讀取權(quán)限注解,優(yōu)先方法上,沒(méi)有則讀取類
        Auth Annotation = getAnnotation(method, Auth.class);


        // 判斷權(quán)限
        AuthPermission[] authPermissions = Annotation.value();
        if (ArrayUtils.isEmpty(authPermissions)) {
            // 沒(méi)有權(quán)限樹(shù),登錄就可以訪問(wèn)
            return checkLogin();
        }
        // 校驗(yàn)當(dāng)前登錄用戶,是否包含其中權(quán)限之一
        return checkHasPermission(authPermissions);

    }

    /**
     * 校驗(yàn)當(dāng)前登錄用戶,是否包含其中權(quán)限之一
     */
    private boolean checkHasPermission(AuthPermission[] authPermissions) {
//        User user = UserUtil.getCurrentUser();
//        Role role = user.getRole(); // 獲取角色

        // TODO 判斷角色中的權(quán)限,是否包含接口的權(quán)限
        return ArrayUtils.contains(authPermissions, AuthPermission.NormalUserManagerUpdate);
    }

    /**
     * 判斷是否登錄
     */
    private boolean checkLogin() {
        // TODO 從redis或者session中判斷是否登錄
        return true;
    }

    /**
     * 讀取權(quán)限注解,優(yōu)先方法上,沒(méi)有則讀取類
     */
    private Auth getAnnotation(Method method, Class<Auth> authClass) {
        Auth annotation = method.getAnnotation(authClass);
        if (annotation != null) {
            return annotation;
        }

        annotation = method.getDeclaringClass().getAnnotation(authClass);
        return annotation;
    }
}

4、測(cè)試一下

@RestController
@RequestMapping("/test")
@Auth
public class TestController {


    @GetMapping("/test1")
    public String test1() {
        return "success";
    }

    @GetMapping("/test2")
    @Auth(AuthPermission.NormalUserManagerDelete)
    public String test2() {
        return "success";
    }

    @GetMapping("/test3")
    @Auth(AuthPermission.NormalUserManagerUpdate)
    public String test3() {
        return "success";
    }
}

 到此這篇關(guān)于SpringAOP實(shí)現(xiàn)自定義接口權(quán)限控制的文章就介紹到這了,更多相關(guān)SpringAOP 接口權(quán)限控制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java生成壓縮文件示例代碼

    java生成壓縮文件示例代碼

    在工作過(guò)程中,需要將一個(gè)文件夾生成壓縮文件,然后提供給用戶下載。寫(xiě)了一個(gè)壓縮文件的工具類。該工具類支持單個(gè)文件和文件夾壓縮
    2013-11-11
  • 在@Value注解內(nèi)使用SPEL自定義函數(shù)方式

    在@Value注解內(nèi)使用SPEL自定義函數(shù)方式

    這篇文章主要介紹了在@Value注解內(nèi)使用SPEL自定義函數(shù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • 關(guān)于Unsupported major.minor version 49.0的錯(cuò)誤解決辦法

    關(guān)于Unsupported major.minor version 49.0的錯(cuò)誤解決辦法

    這篇文章主要介紹了關(guān)于Unsupported major.minor version 49.0的錯(cuò)誤解決辦法的相關(guān)資料,需要的朋友可以參考下
    2015-11-11
  • JAVAE中servlet的概念及使用示例詳解

    JAVAE中servlet的概念及使用示例詳解

    servlet是一種實(shí)現(xiàn)動(dòng)態(tài)頁(yè)面的技術(shù),他是由tomcat提供給程序員的一組API可以幫助程序員開(kāi)發(fā)一個(gè)web程序,這篇文章主要介紹了JAVAE中servlet的概念及使用,需要的朋友可以參考下
    2024-05-05
  • Spring應(yīng)用拋出NoUniqueBeanDefinitionException異常的解決方案

    Spring應(yīng)用拋出NoUniqueBeanDefinitionException異常的解決方案

    這篇文章介紹了解決org.springframework.beans.factory.NoUniqueBeanDefinitionException異常的一些解決方案,從這些解決方案可以看出Spring框架的設(shè)計(jì)精妙,遇見(jiàn)此問(wèn)題的朋友可以參考下該解決方案
    2021-06-06
  • Java常用正則表達(dá)式驗(yàn)證工具類RegexUtils.java

    Java常用正則表達(dá)式驗(yàn)證工具類RegexUtils.java

    相信大家對(duì)正則表達(dá)式一定都有所了解和研究,這篇文章主要為大家分享了Java 表單注冊(cè)常用正則表達(dá)式驗(yàn)證工具類,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • java遞歸菜單樹(shù)轉(zhuǎn)換成pojo對(duì)象

    java遞歸菜單樹(shù)轉(zhuǎn)換成pojo對(duì)象

    這篇文章介紹了java遞歸菜單樹(shù)轉(zhuǎn)換成pojo對(duì)象的具體實(shí)現(xiàn),有需要的朋友可以參考一下
    2013-08-08
  • Spring?@Cacheable讀取配置常量方式

    Spring?@Cacheable讀取配置常量方式

    這篇文章主要介紹了Spring?@Cacheable讀取配置常量方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • MyBatis中SQL映射與動(dòng)態(tài)查詢的技巧分享

    MyBatis中SQL映射與動(dòng)態(tài)查詢的技巧分享

    SQL映射文件是MyBatis框架中用于定義數(shù)據(jù)庫(kù)操作的XML文件,它與應(yīng)用程序的數(shù)據(jù)訪問(wèn)層進(jìn)行交互,將Java對(duì)象與數(shù)據(jù)庫(kù)表之間的映射關(guān)系進(jìn)行配置,并提供了執(zhí)行SQL語(yǔ)句的方式,本文給大家介紹了MyBatis中SQL映射與動(dòng)態(tài)查詢的技巧,需要的朋友可以參考下
    2025-09-09
  • SpringCloud集成sleuth和zipkin實(shí)現(xiàn)微服務(wù)鏈路追蹤的實(shí)戰(zhàn)分享

    SpringCloud集成sleuth和zipkin實(shí)現(xiàn)微服務(wù)鏈路追蹤的實(shí)戰(zhàn)分享

    最近項(xiàng)目上準(zhǔn)備引入接口調(diào)用鏈路追蹤,說(shuō)到這個(gè)我們就不得不想到springcloud全家桶中的sleuth了,他可以將跨多個(gè)服務(wù)請(qǐng)求鏈路記錄下來(lái),供我們查詢分析,所以今天就分享一期微服務(wù)架構(gòu)接入sleuth+zipkin實(shí)戰(zhàn)演示,需要的朋友可以參考下
    2024-12-12

最新評(píng)論

昌黎县| 荥阳市| 宁河县| 萝北县| 仲巴县| 兴宁市| 乌兰察布市| 南昌县| 浙江省| 惠东县| 乳山市| 高淳县| 鄂伦春自治旗| 洪雅县| 高雄市| 蓬莱市| 休宁县| 涪陵区| 泾源县| 从江县| 新化县| 西安市| 忻城县| 剑川县| 龙口市| 靖西县| 枣阳市| 尉氏县| 芜湖县| 绥滨县| 平山县| 商城县| 温州市| 裕民县| 金寨县| 卓尼县| 盘山县| 巴塘县| 平遥县| 德化县| 岚皋县|