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

詳解如何在Spring?Security中自定義權(quán)限表達(dá)式

 更新時間:2022年07月12日 10:32:27   作者:_江南一點雨  
這篇文章主要和大家詳細(xì)介紹一下如何在Spring?Security中自定義權(quán)限表達(dá)式,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

1. SpEL 回顧

經(jīng)過上篇文章的學(xué)習(xí),小伙伴們已經(jīng)知道了,在 Spring Security 中,@PreAuthorize、@PostAuthorize 等注解都是支持 SpEL 表達(dá)式的。

在 SpEL 表達(dá)式中,如果上來就直接寫要執(zhí)行的方法名,那么就說明這個方法是 RootObject 對象中的方法,如果要執(zhí)行其他對象的方法,那么還需要寫上對象的名字,例如如下兩個例子:

@PreAuthorize("hasAuthority('system:user:add')")
public String add() {
    return "add";
}

上面這個例子中,表達(dá)式中的方法是 hasAuthority,沒有寫對象名,那么就說明這個方法是 SpEL 中 RootObject 對象中的方法。

@PreAuthorize("@ss.hasPermi('monitor:operlog:list')")
@GetMapping("/list")
public TableDataInfo list(SysOperLog operLog) {
    startPage();
    List<SysOperLog> list = operLogService.selectOperLogList(operLog);
    return getDataTable(list);
}

上面這個例子中,權(quán)限注解中的表達(dá)式方法是 @ss.hasPermi('monitor:operlog:list'),其中 ss 是指 Spring 容器中的一個對象名,hasPermi 則是這個對象中的方法。

好啦,經(jīng)過前面文章的學(xué)習(xí),這些基本知識大家都已經(jīng)掌握了。

2. 如何自定義

其實上面給出來的第二個例子就是一個自定義的例子。

不過,這種自定義方式太自由了,自由到?jīng)]有在 Spring Security 架構(gòu)內(nèi)完成這件事。所以,今天我想和小伙伴們聊一聊,如何在不使用第三方對象的情況下,來自定義一個權(quán)限判斷的表達(dá)式。

首先小伙伴們知道,我們在 @PreAuthorize 注解中使用的不用加對象名就能調(diào)用的權(quán)限方法,如 hasAuthority、hasPermission、hasRole、hasAnyRole 等,基本上都是由 SecurityExpressionRoot 及其子類提供的,準(zhǔn)確來說是由 MethodSecurityExpressionRoot 類提供的。

MethodSecurityExpressionRoot 類實際上繼承自 SecurityExpressionRoot,只不過增加了過濾對象以及返回值對象。我們來看下 MethodSecurityExpressionRoot 的方法摘要:

再來看看 SecurityExpressionRoot 中的方法:

這些就是 RootObject 對象中的所有方法了,也是我們能夠在 @PreAuthorize 注解中使用的所有方法了。

那么現(xiàn)在想在已有方法上繼續(xù)擴(kuò)展新方法,那么我們可以通過自定義類繼承自 SecurityExpressionRoot 對象,擴(kuò)展這個 RootObject 對象,在該對象中繼續(xù)添加新的方法,進(jìn)而實現(xiàn)自定義權(quán)限表達(dá)式。

好啦,說干就干,開搞!

本文的案例在前文的基礎(chǔ)上繼續(xù)完成,所以這里我就不從頭開始寫了。

3. 自定義 ExpressionRoot

首先我們自定義一個類繼承自 SecurityExpressionRoot 并實現(xiàn) MethodSecurityExpressionOperations 接口(本來直接繼承自 MethodSecurityExpressionRoot 即可,但是因為這個類不是 public 的,沒法繼承,所以我們就實現(xiàn) MethodSecurityExpressionOperations 接口即可):

public class CustomSecurityExpressionRoot extends SecurityExpressionRoot implements MethodSecurityExpressionOperations {

    private Object filterObject;
    private Object returnObject;
    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    /**
     * Creates a new instance
     *
     * @param authentication the {@link Authentication} to use. Cannot be null.
     */
    public CustomSecurityExpressionRoot(Authentication authentication) {
        super(authentication);
    }

    /**
     * 判斷當(dāng)前對象是否具備某一個權(quán)限
     * @param permission
     * @return
     */
    public boolean hasPermission(String permission) {
        //獲取當(dāng)前登錄用戶所具有的權(quán)限
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
        for (GrantedAuthority authority : authorities) {
            if (antPathMatcher.match(authority.getAuthority(), permission)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 是否具備多個權(quán)限中的任意一個權(quán)限
     * @param permissions
     * @return
     */
    public boolean hasAnyPermissions(String... permissions) {
        if (permissions == null || permissions.length == 0) {
            return false;
        }
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
        for (GrantedAuthority authority : authorities) {
            for (String permission : permissions) {
                if (antPathMatcher.match(authority.getAuthority(), permission)) {
                    return true;
                }
            }
        }
        return false;
    }

    public boolean hasAllPermissions:(String... permissions) {
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
        if (permissions == null || permissions.length == 0) {
            return false;
        }
        for (String permission : permissions) {
            boolean flag = false;
            for (GrantedAuthority authority : authorities) {
                if (antPathMatcher.match(authority.getAuthority(), permission)) {
                    flag = true;
                }
            }
            if (!flag) {
                return false;
            }
        }
        return true;
    }

    @Override
    public void setFilterObject(Object filterObject) {
        this.filterObject = filterObject;
    }

    @Override
    public Object getFilterObject() {
        return filterObject;
    }

    @Override
    public void setReturnObject(Object returnObject) {
        this.returnObject = returnObject;
    }

    @Override
    public Object getReturnObject() {
        return returnObject;
    }

    @Override
    public Object getThis() {
        return this;
    }
}

加了 @Override 注解的方法,都是普普通通的常規(guī)方法,沒啥好說的。我們自己主要實現(xiàn)了三個方法,分別是:

  • hasPermission:判斷當(dāng)前用戶是否具備某一個給定的權(quán)限。
  • hasAnyPermissions:判斷當(dāng)前用戶是否具備給定的多個權(quán)限中的某一個。
  • hasAllPermissions:判斷當(dāng)前用戶是否具備所有的給定的權(quán)限。

這里邊的邏輯我就不啰嗦了,都是基本的 Java 語法而已。

另外,用 AntPathMatcher 做比對是為了支持通配符,這個在上篇文章中已經(jīng)說過了,這里不再贅述。

Spring Security 中,MethodSecurityExpressionRoot 的配置是通過 DefaultMethodSecurityExpressionHandler 來完成的,現(xiàn)在我們自定義了 CustomSecurityExpressionRoot,那也得有一個 Handler 來配置 CustomSecurityExpressionRoot,所以,再來一個類繼承自 DefaultMethodSecurityExpressionHandler,如下:

public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {
    @Override
    protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, MethodInvocation invocation) {
        CustomSecurityExpressionRoot root = new CustomSecurityExpressionRoot(authentication);
        root.setTrustResolver(getTrustResolver());
        root.setPermissionEvaluator(getPermissionEvaluator());
        root.setRoleHierarchy(getRoleHierarchy());
        return root;
    }
}

在 createSecurityExpressionRoot 方法中創(chuàng)建一個 CustomSecurityExpressionRoot 對象,對象的 TrustResolver、權(quán)限評估器以及角色層級等,統(tǒng)統(tǒng)都用默認(rèn)的方案即可。

配置完成后,再配置一下 CustomMethodSecurityExpressionHandler 這個 Bean 即可,如下:

@Bean
CustomMethodSecurityExpressionHandler customMethodSecurityExpressionHandler() {
    return new CustomMethodSecurityExpressionHandler();
}

好啦,這就注入成功了。

接下來,我們就可以在權(quán)限注解中使用這個自定義的方法了:

@PreAuthorize("hasPermission('system:user:add')")
public String add() {
    return "add";
}

這個自定義權(quán)限表達(dá)式的思路,說到底還是在 Spring Security 體系中玩,個人感覺這種方式更合理一些。

到此這篇關(guān)于詳解如何在Spring Security中自定義權(quán)限表達(dá)式的文章就介紹到這了,更多相關(guān)Spring Security自定義權(quán)限表達(dá)式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用Spring Boot上傳文件功能

    使用Spring Boot上傳文件功能

    上傳文件是互聯(lián)網(wǎng)中常應(yīng)用的場景之一,最典型的情況就是上傳頭像等,今天就帶著大家做一個Spring Boot上傳文件的小案例,感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧
    2018-01-01
  • idea創(chuàng)建springboot項目(版本只能選擇17和21)的解決方法

    idea創(chuàng)建springboot項目(版本只能選擇17和21)的解決方法

    idea2023創(chuàng)建spring boot項目時,java版本無法選擇11,本文主要介紹了idea創(chuàng)建springboot項目(版本只能選擇17和21),下面就來介紹一下解決方法,感興趣的可以了解一下
    2024-01-01
  • SpringBoot增強(qiáng)Controller方法@ControllerAdvice注解的使用詳解

    SpringBoot增強(qiáng)Controller方法@ControllerAdvice注解的使用詳解

    這篇文章主要介紹了SpringBoot增強(qiáng)Controller方法@ControllerAdvice注解的使用詳解,@ControllerAdvice,是Spring3.2提供的新注解,它是一個Controller增強(qiáng)器,可對controller進(jìn)行增強(qiáng)處理,需要的朋友可以參考下
    2023-10-10
  • java實現(xiàn)統(tǒng)計字符串中大寫字母,小寫字母及數(shù)字出現(xiàn)次數(shù)的方法示例

    java實現(xiàn)統(tǒng)計字符串中大寫字母,小寫字母及數(shù)字出現(xiàn)次數(shù)的方法示例

    這篇文章主要介紹了java實現(xiàn)統(tǒng)計字符串中大寫字母,小寫字母及數(shù)字出現(xiàn)次數(shù)的方法,涉及java針對字符串的遍歷、判斷、運算相關(guān)操作技巧,需要的朋友可以參考下
    2019-06-06
  • IDEA 2020 本土化,真的是全中文了(真香)

    IDEA 2020 本土化,真的是全中文了(真香)

    去年,JetBrains 網(wǎng)站進(jìn)行了本地化,提供了 8 種不同的語言版本,而現(xiàn)在,團(tuán)隊正在對基于 IntelliJ 的 IDE 進(jìn)行本地化
    2020-12-12
  • Java并發(fā)編程之CountDownLatch解讀

    Java并發(fā)編程之CountDownLatch解讀

    這篇文章主要介紹了Java并發(fā)編程之CountDownLatch解讀,是通過一個計數(shù)器來實現(xiàn)的,計數(shù)器的初始值是線程的數(shù)量,countDownLatch這個類使一個線程等待其他線程各自執(zhí)行完畢后再執(zhí)行,需要的朋友可以參考下
    2023-12-12
  • java子類調(diào)用父類的方法中包含子類重寫的實例方法

    java子類調(diào)用父類的方法中包含子類重寫的實例方法

    在本篇文章里小編給大家整理了關(guān)于java子類調(diào)用父類的方法中包含子類重寫的實例方法以及相關(guān)知識點,需要的朋友們可以學(xué)習(xí)下。
    2019-09-09
  • Maven如何修改打包文件名稱

    Maven如何修改打包文件名稱

    這篇文章主要介紹了Maven如何修改打包文件名稱問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • Java poi導(dǎo)出Excel下載到客戶端

    Java poi導(dǎo)出Excel下載到客戶端

    這篇文章主要為大家詳細(xì)介紹了Java poi導(dǎo)出Excel下載到客戶端的相關(guān)方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • 利用Java提取PDF表格到文本、CSV及excel工作表

    利用Java提取PDF表格到文本、CSV及excel工作表

    如何精準(zhǔn)地提取PDF格式中嵌入的表格數(shù)據(jù),并將其無縫轉(zhuǎn)換為更加易于分析和操作的形式,是一項重要的文檔處理技巧,本文將介紹如何利用Java從PDF文檔提取表格數(shù)據(jù),并寫入文本文件、CSV文件以及Excel工作表,需要的朋友可以參考下
    2024-09-09

最新評論

乐山市| 抚州市| 田东县| 鄂托克旗| 手游| 泗水县| 济南市| 韶关市| 溆浦县| 卫辉市| 巴彦县| 山东| 平罗县| 绿春县| 钦州市| 枣阳市| 金寨县| 白城市| 五台县| 拉萨市| 含山县| 花莲县| 万源市| 同江市| 固原市| 商河县| 鲜城| 保康县| 沧州市| 宜城市| 明星| 郯城县| 靖州| 资溪县| 正安县| 江源县| 钦州市| 宜兰市| 江阴市| 汕尾市| 根河市|