<option id="mwy0y"><strong id="mwy0y"></strong></option>
  • <ul id="mwy0y"><sup id="mwy0y"></sup></ul>
  • <ul id="mwy0y"></ul>
  • <del id="mwy0y"><dfn id="mwy0y"></dfn></del><ul id="mwy0y"><sup id="mwy0y"></sup></ul>
  • <abbr id="mwy0y"></abbr>

    千鋒教育-做有情懷、有良心、有品質(zhì)的職業(yè)教育機(jī)構(gòu)

    400-811-9990
    手機(jī)站
    千鋒教育

    千鋒學(xué)習(xí)站 | 隨時(shí)隨地免費(fèi)學(xué)

    千鋒教育

    掃一掃進(jìn)入千鋒手機(jī)站

    領(lǐng)取全套視頻
    千鋒教育

    關(guān)注千鋒學(xué)習(xí)站小程序
    隨時(shí)隨地免費(fèi)學(xué)習(xí)課程

    上海
    • 北京
    • 鄭州
    • 武漢
    • 成都
    • 西安
    • 沈陽
    • 廣州
    • 南京
    • 深圳
    • 大連
    • 青島
    • 杭州
    • 重慶
    當(dāng)前位置:長沙千鋒IT培訓(xùn)  >  技術(shù)要點(diǎn)  >  長沙Java培訓(xùn)班分享:Spring教程之Spring Security的四種權(quán)限控制方式

    長沙Java培訓(xùn)班分享:Spring教程之Spring Security的四種權(quán)限控制方式

    來源:千鋒教育
    發(fā)布人:千鋒長沙
    時(shí)間: 2021-10-27 17:22:00

           在前面的章節(jié)中,一一哥 已經(jīng)給大家介紹了Spring Security的很多功能,在這些眾多功能中,我們知道其核心功能其實(shí)就是認(rèn)證+授權(quán)。下面長沙Java培訓(xùn)班分享:Spring教程之Spring Security的四種權(quán)限控制方式。

           在前面我們分別基于內(nèi)存模型、基于默認(rèn)的數(shù)據(jù)庫模型、基于自定義數(shù)據(jù)庫模型實(shí)現(xiàn)了認(rèn)證和授權(quán)功能,但是不管哪種方式,我們對(duì)某個(gè)接口的攔截限制,都是通過編寫一個(gè)SecurityConfig配置類,在該類的configure (Http Security http)方法中,通過http. authorize Requests ( ). antMatchers ("/admin/**")...這樣的代碼進(jìn)行的權(quán)限控制。

           這種權(quán)限控制方法雖然也可以實(shí)現(xiàn)對(duì)某些接口的攔截或放行,但是不夠靈活,其實(shí)Spring Security對(duì)接口的攔截或放行的寫法,還有另外的方式,接下來請跟我學(xué)習(xí)一下吧!

           一. 權(quán)限控制方式

           在Spring Security 中,我們既可以使用 Spring Security 提供的默認(rèn)方式進(jìn)行授權(quán),也可以進(jìn)行自定義授權(quán),總之在Spring Security中權(quán)限控制的實(shí)現(xiàn)方式是比較靈活多樣的。在Spring Security 中,對(duì)接口的攔截或放行,有四種常見的權(quán)限控制方式:

           利用Ant表達(dá)式實(shí)現(xiàn)權(quán)限控制;

           利用授權(quán)注解結(jié)合SpEl表達(dá)式實(shí)現(xiàn)權(quán)限控制;

           利用過濾器注解實(shí)現(xiàn)權(quán)限控制;

           利用動(dòng)態(tài)權(quán)限實(shí)現(xiàn)權(quán)限控制。

           對(duì)上面說到的四種權(quán)限控制方式,我們接下來分別進(jìn)行講解實(shí)現(xiàn)。

           二. 利用Ant表達(dá)式實(shí)現(xiàn)權(quán)限控制

           利用Ant表達(dá)式的權(quán)限控制方式,是我們之前一直在使用的權(quán)限控制方式,在進(jìn)行代碼實(shí)現(xiàn)之前,我先對(duì)這種方式的底層實(shí)現(xiàn)進(jìn)行簡單分析。

           1. Spring Security中的權(quán)限控制方法

           在Spring Security中,有一個(gè)Security Expression Operations 接口,在該接口中定義了一系列的方法,用于用戶權(quán)限的設(shè)置,如下圖:

    640.webp

           SecurityExpressionOperations接口中的

           這些方法作用如下圖所示:

    640.webp (1)

           2. Spring Security中的權(quán)限控制粒度

           這個(gè)接口有一個(gè)SecurityExpressionRoot子類,該類提供了基于表達(dá)式的權(quán)限控制實(shí)現(xiàn)方式。而這個(gè)SecurityExpressionRoot 又有兩個(gè)實(shí)現(xiàn)子類,分別用于實(shí)現(xiàn) URL Web接口粒度的權(quán)限控制和 方法粒度的權(quán)限控制,如下圖所示:

    640.webp (2)

           3. 代碼實(shí)現(xiàn)

           從上面的小節(jié)中,我們知道在Spring Security中,支持2種粒度的權(quán)限控制,即URL Web接口粒度 和方法粒度,而我們這里所謂的 Ant表達(dá)式授權(quán)控制方式,就是通過Ant表達(dá)式來控制 URL 接口的訪問權(quán)限。

           那么如果我們需要對(duì)URL接口粒度進(jìn)行權(quán)限控制,按如下代碼即可實(shí)現(xiàn):

    @Override

    protected void configure(HttpSecurity http) throws Exception {

    http.authorizeRequests()

    .antMatchers("/admin/**")

    .hasRole("ADMIN")

    .antMatchers("/user/**")

    .hasRole("USER")

    .antMatchers("/visitor/**")

    .permitAll()

    .anyRequest()

    .authenticated()

    .and()

    .formLogin()

    .permitAll()

    .and()

    //對(duì)跨域請求偽造進(jìn)行防護(hù)---->csrf:利用用戶帶有登錄狀態(tài)的cookie進(jìn)行攻擊的手段

    .csrf()

    .disable();

    }

           以上代碼中,/admin/ 格式的路徑需要 admin 角色才可以訪問,/user/ 格式的路徑需要 user 角色才可以訪問,/visitor/** 格式的路徑可以直接訪問,其他接口路徑則需要登錄后才能訪問。

           三. 利用授權(quán)注解結(jié)合SpEl表達(dá)式實(shí)現(xiàn)權(quán)限控制

           1. 授權(quán)注解

           除了可以使用上面的Ant表達(dá)式進(jìn)行授權(quán)實(shí)現(xiàn),我們也可以在方法上添加授權(quán)注解來權(quán)限控制,常用的授權(quán)注解有3個(gè):

           @PreAuthorize:方法執(zhí)行前進(jìn)行權(quán)限檢查;

           @PostAuthorize:方法執(zhí)行后進(jìn)行權(quán)限檢查;

           @Secured:類似于 @PreAuthorize。

           2. 代碼實(shí)現(xiàn)

           要想利用以上3個(gè)授權(quán)注解進(jìn)行權(quán)限控制,我們首先需要利用@EnableGlobalMethodSecurity注解開啟授權(quán)注解功能,代碼如下:

    @Configuration

    @EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true)

    public class SecurityConfig extends WebSecurityConfigurerAdapter {

    ...

    ...

    }

    然后在具體的接口方法上利用授權(quán)注解進(jìn)行權(quán)限控制,代碼如下:

    @RestController

    public class UserController {

    @Secured({"ROLE_USER"})

    //@PreAuthorize("principal.username.equals('user')")

    @GetMapping("/user/hello")

    public String helloUser() {

    return "hello, user";

    }

    @PreAuthorize("hasRole('ADMIN')")

    @GetMapping("/admin/hello")

    public String helloAdmin() {

    return "hello, admin";

    }

    @PreAuthorize("#age>100")

    @GetMapping("/age")

    public String getAge(@RequestParam("age") Integer age) {

    return String.valueOf(age);

    }

    @GetMapping("/visitor/hello")

    public String helloVisitor() {

    return "hello, visitor";

    }

    }

           可以看出,這種寫法明顯比利用Ant表達(dá)式進(jìn)行權(quán)限控制更靈活方便,所以開發(fā)時(shí)這種寫法很常用。

           四. 利用過濾器注解實(shí)現(xiàn)權(quán)限控制

           1. 過濾器注解簡介

           在Spring Security中還提供了另外的兩個(gè)注解,即@PreFilter和@PostFilter,這兩個(gè)注解可以對(duì)集合類型的參數(shù)或返回值進(jìn)行過濾。使用@PreFilter和@PostFilter時(shí),Spring Security將移除對(duì)應(yīng)表達(dá)式結(jié)果為false的元素。

           2. @PostFilter的用法

           @PostFilter注解主要是用于對(duì)集合類型的返回值進(jìn)行過濾,filterObject是@PostFilter中的一個(gè)內(nèi)置表達(dá)式,表示集合中的元素對(duì)象。

    @Slf4j

    @RestController

    public class FilterController {

    /**

    * 只返回結(jié)果中id為偶數(shù)的user元素。

    * filterObject是@PreFilter和@PostFilter中的一個(gè)內(nèi)置表達(dá)式,表示集合中的當(dāng)前對(duì)象。

    */

    @PostFilter("filterObject.id%2==0")

    @GetMapping("/users")

    public List<User> getAllUser() {

    List<User> users = new ArrayList<>();

    for (int i = 0; i < 10; i++) {

    users.add(new User(i, "yyg-" + i));

    }

    return users;

    }

    }

    我們啟動(dòng)瀏覽器進(jìn)行測試,可以看到測試接口中只返回了id為偶數(shù)的元素。

    640.webp (4)

           3. @PreFilter的用法

           使用@PreFilter也可以對(duì)集合類型的參數(shù)進(jìn)行過濾,當(dāng)@PreFilter標(biāo)注的方法內(nèi)擁有多個(gè)集合類型的參數(shù)時(shí),可以通過@PreFilter的filterTarget屬性來指定當(dāng)前是針對(duì)哪個(gè)參數(shù)進(jìn)行過濾的;而filterObject是@PreFilter中的一個(gè)內(nèi)置表達(dá)式,表示集合中的元素對(duì)象。

    為了方便測試,我們在Service層中進(jìn)行過濾操作,然后在Controller層中進(jìn)行調(diào)用。

    FilterService類中的方法定義:

    @Slf4j

    @Service

    public class FilterService {

    /**

    * 當(dāng)@PreFilter標(biāo)注的方法內(nèi)擁有多個(gè)集合類型的參數(shù)時(shí),

    * 可以通過@PreFilter的filterTarget屬性來指定當(dāng)前是針對(duì)哪個(gè)參數(shù)進(jìn)行過濾的。

    */

    @PreFilter(filterTarget = "ids", value = "filterObject%2==0")

    public List<Integer> doFilter(List<Integer> ids, List<User> users) {

    log.warn("ids=" + ids.toString());

    log.warn("users=" + users.toString());

    return ids;

    }

    }

    在Controller中定義一個(gè)測試接口:

    @Slf4j

    @RestController

    public class FilterController {

    /**

    * 只返回結(jié)果中id為偶數(shù)的user元素。

    * filterObject是@PreFilter和@PostFilter中的一個(gè)內(nèi)置表達(dá)式,表示集合中的當(dāng)前對(duì)象。

    */

    @PostFilter("filterObject.id%2==0")

    @GetMapping("/users")

    public List<User> getAllUser() {

    List<User> users = new ArrayList<>();

    for (int i = 0; i < 10; i++) {

    users.add(new User(i, "yyg-" + i));

    }

    return users;

    }

    @Autowired

    private FilterService filterService;

    @GetMapping("/users2")

    public List<Integer> getUserInfos() {

    List<Integer> ids = new ArrayList<>();

    for (int i = 0; i < 10; i++) {

    ids.add(i);

    }

    List<User> users = new ArrayList<>();

    for (int i = 0; i < 10; i++) {

    users.add(new User(i, "yyg-" + i));

    }

    return filterService.doFilter(ids, users);

    }

    }

    我們啟動(dòng)瀏覽器進(jìn)行測試,可以看到測試接口中只返回id為偶數(shù)的元素。

    640.webp (5)

           4. 代碼結(jié)構(gòu)

           下圖是上面案例的代碼結(jié)構(gòu),請參考實(shí)現(xiàn):

    640.webp (6)

           五. 利用動(dòng)態(tài)權(quán)限實(shí)現(xiàn)權(quán)限控制

           我們知道一個(gè)標(biāo)準(zhǔn)的RABC, 權(quán)限系統(tǒng)需要支持動(dòng)態(tài)配置,Spring Security默認(rèn)是在代碼里約定好權(quán)限,真實(shí)的業(yè)務(wù)場景里通常需要可以支持動(dòng)態(tài)配置角色訪問權(quán)限,即在運(yùn)行時(shí)去配置url對(duì)應(yīng)的訪問角色。

           而Spring Security中的動(dòng)態(tài)權(quán)限,主要是通過重寫攔截器和決策器來進(jìn)行實(shí)現(xiàn),最簡單的方法就是自定義一個(gè)Filter去完成權(quán)限判斷。其實(shí)這里涉及到的代碼,基本和Spring Security關(guān)系不大,主要是在傳統(tǒng)的Filter進(jìn)行實(shí)現(xiàn),我這里就不再進(jìn)行描述了,感興趣的同學(xué)可以自行實(shí)現(xiàn)!

           至此,我就給各位介紹了Spring Security中的4種進(jìn)行權(quán)限控制的方式,各位可以結(jié)合自己的項(xiàng)目需求進(jìn)行選擇。

    43566

                                        掃碼關(guān)注公眾號(hào)【Java架構(gòu)棧】,獲取全套專欄內(nèi)容及代碼

    聲明:本站稿件版權(quán)均屬千鋒教育所有,未經(jīng)許可不得擅自轉(zhuǎn)載。

    猜你喜歡LIKE

    最新文章NEW

    相關(guān)推薦HOT

    更多>>

    快速通道 更多>>

    最新開班信息 更多>>

    網(wǎng)友熱搜 更多>>