欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringSecurity怎樣使用注解控制權(quán)限

 更新時間:2021年06月23日 14:17:52   作者:小樓夜聽雨QAQ  
這篇文章主要介紹了SpringSecurity怎樣使用注解控制權(quán)限的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

一般的系統(tǒng)在權(quán)限設(shè)計上,都會分為角色、權(quán)限(RDBC),復(fù)雜一點的可能會有用戶組、組織之類的概念。

用戶的權(quán)限是寫死的,對應(yīng)于后臺的接口或者資源,是沒辦法改變的,一般不對用戶開放修改權(quán)限。

管理員用戶可以通過給角色分配權(quán)限的方式,來實現(xiàn)訪問控制。

所以當(dāng)我們寫過濾器,或者用一些安全框架時(比如Shiro,Spring Security),也需要將可變的“角色”,轉(zhuǎn)化為不可變的“權(quán)限”,注入到框架中。

具體的可以看我之前寫的一篇(Spring Security整合jwt完整版

注入當(dāng)前用戶的權(quán)限后,就需要進(jìn)行訪問控制了。

常見的做法有

1、路徑比對

之前有個項目用過一次,定義一個過濾器,添加到security的過濾鏈中,在這個過濾器中做這么一件事:

分析當(dāng)前訪問路徑所需要的權(quán)限,檢查當(dāng)前用戶是否具有該權(quán)限,做一個對比,根據(jù)對比結(jié)果來決定當(dāng)前用戶是否可以訪問該資源。

這種做法的好處是代碼的入侵性不高,不需要再每個接口上加注解。但相對來說,顯得不那么直觀,可讀性比較差,所以這次換個方法。

2、使用注解的方式

SpringSecurity使用注解來控制訪問時,需要提前開啟這個功能。

在配置類上加上注解

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

在接口中如此使用

   /**
     * 條件查詢
     */
    @PreAuthorize("hasAuthority('IMPORT:SELECT')")
    @ApiOperation(value = "查詢")
    @GetMapping("/list")
    public R<Page<Task>> list(TaskDto taskDto){
        //測試階段,隨機(jī)生成任務(wù)
        Random random = new Random();
 
        //todo
        int i = random.nextInt(4);
        if(i == 2) {
            metroServerAdapterService.reloadShelveTask();
        }
        Page<Task> list = taskService.list(taskDto);
        return R.ok(list);
    }

hasAuthority可以替換成hasRole,雖然可以達(dá)到相同的目的,但是在使用的方法上還是有些不同的。

hasRole要求內(nèi)容必須以"ROLE_"開頭,也是官方推薦的命名方式,否則沒有效果。但是hasAuthority沒有限制,數(shù)據(jù)庫中怎樣寫的,代碼里就怎么寫。

同樣的功能的注解為什么要有兩個名字呢。或許這么做可能在語義上比較清晰明確一點,將角色與權(quán)限這兩個概念稍加區(qū)分。

仔細(xì)想一下,確實有些小型的系統(tǒng)或許壓根就不需要權(quán)限,只有給用戶分配角色,沒有給角色分配權(quán)限這一過程。這樣的話,角色也是不可變的,就可以根據(jù)角色來做訪問控制了。

但考慮通用性,個人覺得用hasAuthority就可以了。

SpringSecurity_權(quán)限注解@PreAuthorize、@PostAuthorize

spring是如何實現(xiàn)對HTTP請求進(jìn)行安全檢查和資源使用授權(quán)的?

實現(xiàn)過程由類AbstractSecurityInterceptor在beforeInvocation方法中完成,在beforeInvocation的實現(xiàn)中,

首先,需要讀取IoC容器中Bean的配置,在這些屬性配置中配置了對HTTP請求資源的安全需求,

比如,哪個角色的用戶可以接入哪些URL請求資源,具體實現(xiàn)邏輯見:

#與Web環(huán)境的接口FilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter

@PreAuthorize、@PostAuthorize注解實現(xiàn)邏輯

繼承根節(jié)點:SecurityMetaSource

可以通過Spring注解聲明,需要依賴類注入,實現(xiàn)權(quán)限靈活配置如:

@Component("securityMetadataSource")
public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource
PrePostAnnotationSecurityMetadataSource類繼承關(guān)系
AbstractMethodSecurityMetadataSource類繼承關(guān)系
package org.springframework.security.access.prepost; 
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.method.AbstractMethodSecurityMetadataSource;
import org.springframework.util.ClassUtils; 
public class PrePostAnnotationSecurityMetadataSource extends AbstractMethodSecurityMetadataSource {
    private final PrePostInvocationAttributeFactory attributeFactory;
    public PrePostAnnotationSecurityMetadataSource(PrePostInvocationAttributeFactory attributeFactory) {
        this.attributeFactory = attributeFactory;
    }
 
    public Collection<ConfigAttribute> getAttributes(Method method, Class<?> targetClass) {
        if (method.getDeclaringClass() == Object.class) {
            return Collections.emptyList();
        } else {
            this.logger.trace("Looking for Pre/Post annotations for method '" + method.getName() + "' on target class '" + targetClass + "'");
            PreFilter preFilter = (PreFilter)this.findAnnotation(method, targetClass, PreFilter.class);
            PreAuthorize preAuthorize = (PreAuthorize)this.findAnnotation(method, targetClass, PreAuthorize.class);
            PostFilter postFilter = (PostFilter)this.findAnnotation(method, targetClass, PostFilter.class);
            PostAuthorize postAuthorize = (PostAuthorize)this.findAnnotation(method, targetClass, PostAuthorize.class);
            if (preFilter == null && preAuthorize == null && postFilter == null && postAuthorize == null) {
                this.logger.trace("No expression annotations found");
                return Collections.emptyList();
            } else {
                String preFilterAttribute = preFilter == null ? null : preFilter.value();
                String filterObject = preFilter == null ? null : preFilter.filterTarget();
                String preAuthorizeAttribute = preAuthorize == null ? null : preAuthorize.value();
                String postFilterAttribute = postFilter == null ? null : postFilter.value();
                String postAuthorizeAttribute = postAuthorize == null ? null : postAuthorize.value();
                ArrayList<ConfigAttribute> attrs = new ArrayList(2);
                PreInvocationAttribute pre = this.attributeFactory.createPreInvocationAttribute(preFilterAttribute, filterObject, preAuthorizeAttribute);
                if (pre != null) {
                    attrs.add(pre);
                }
 
                PostInvocationAttribute post = this.attributeFactory.createPostInvocationAttribute(postFilterAttribute, postAuthorizeAttribute);
                if (post != null) {
                    attrs.add(post);
                }
 
                attrs.trimToSize();
                return attrs;
            }
        }
    }
 
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }
 
    private <A extends Annotation> A findAnnotation(Method method, Class<?> targetClass, Class<A> annotationClass) {
        Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
        A annotation = AnnotationUtils.findAnnotation(specificMethod, annotationClass);
        if (annotation != null) {
            this.logger.debug(annotation + " found on specific method: " + specificMethod);
            return annotation;
        } else {
            if (specificMethod != method) {
                annotation = AnnotationUtils.findAnnotation(method, annotationClass);
                if (annotation != null) {
                    this.logger.debug(annotation + " found on: " + method);
                    return annotation;
                }
            }
 
            annotation = AnnotationUtils.findAnnotation(specificMethod.getDeclaringClass(), annotationClass);
            if (annotation != null) {
                this.logger.debug(annotation + " found on: " + specificMethod.getDeclaringClass().getName());
                return annotation;
            } else {
                return null;
            }
        }
    }
}
//注解開啟權(quán)限
@EnableResourceServer
@EnableGlobalMethodSecurity
SecurityContextHolder作為全局緩存,從上下文獲取授權(quán)信息
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();

上面權(quán)限列表初始化由具體實現(xiàn)類實現(xiàn):

public class User implements UserDetails, CredentialsContainer {
    ...
    private final Set<GrantedAuthority> authorities;
    ...
    //authorities權(quán)限列表
    public User(String username, String password, Collection<? extends GrantedAuthority> authorities) {
        this(username, password, true, true, true, true, authorities);
    }

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java使用utf8格式保存文本文件的方法

    Java使用utf8格式保存文本文件的方法

    這篇文章主要介紹了Java使用utf8格式保存文本文件的方法,涉及Java針對字符流編碼操作的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-11-11
  • Java?NIO實現(xiàn)聊天功能

    Java?NIO實現(xiàn)聊天功能

    這篇文章主要為大家詳細(xì)介紹了Java?NIO實現(xiàn)聊天功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • Spring依賴注入的兩種方式(根據(jù)實例詳解)

    Spring依賴注入的兩種方式(根據(jù)實例詳解)

    這篇文章主要介紹了Spring依賴注入的兩種方式(根據(jù)實例詳解),非常具有實用價值,需要的朋友可以參考下
    2017-05-05
  • java集合進(jìn)行排序的方式總結(jié)

    java集合進(jìn)行排序的方式總結(jié)

    在本篇文章里小編給大家整理的是一篇關(guān)于java集合進(jìn)行排序的兩種方式總結(jié),有興趣的朋友們可以學(xué)習(xí)參考下。
    2021-08-08
  • Java線程實現(xiàn)的兩種方式解析

    Java線程實現(xiàn)的兩種方式解析

    這篇文章主要介紹了Java線程實現(xiàn)的兩種方式解析,注意在構(gòu)造器中啟動這個線程的話,很容易造成this逃逸的問題,這是要注意的,這是通過直接集成thread來成為線程,同時在這種情況下,你可以通過調(diào)用合適的方法來,需要的朋友可以參考下
    2024-01-01
  • Mybatis常見注解有哪些(總結(jié))

    Mybatis常見注解有哪些(總結(jié))

    這篇文章主要介紹了Mybatis常見注解有哪些(總結(jié)),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • JAVA下單接口優(yōu)化實戰(zhàn)TPS性能提高10倍

    JAVA下單接口優(yōu)化實戰(zhàn)TPS性能提高10倍

    今天小編就為大家分享一篇關(guān)于JAVA下單接口優(yōu)化實戰(zhàn)TPS性能提高10倍,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • Java中的IP地址和InetAddress類使用詳解

    Java中的IP地址和InetAddress類使用詳解

    這篇文章主要介紹了Java中的IP地址和InetAddress類使用詳解,是Java入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-10-10
  • Java正則表達(dá)式API字符類

    Java正則表達(dá)式API字符類

    這篇文章主要介紹了Java正則表達(dá)式API字符類,Java正則表達(dá)式API也接受預(yù)定義的字符類,下面文章內(nèi)容展開了更多的相關(guān)內(nèi)容介紹,需要的朋友可以參考一下
    2022-06-06
  • Java多態(tài)到底都有啥好處

    Java多態(tài)到底都有啥好處

    Java中的多態(tài)性有兩種類型:編譯時多態(tài)(靜態(tài)綁定)和運行時多態(tài)(動態(tài)綁定)。方法重載是靜態(tài)多態(tài)的一個例子,而方法重寫是動態(tài)多態(tài)的一個例子,接下來通過本文給大家分享Java多態(tài)到底教了我干啥?有啥好處,一起了解下吧
    2021-05-05

最新評論