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

SpringSecurity實現(xiàn)動態(tài)權限校驗的過程

 更新時間:2025年02月15日 12:04:37   作者:深藏Blued藍先生  
Spring Security過濾器鏈中,AuthorizationFilter的authorizationManager是我們要找的組件,該組件的check方法已被棄用,推薦使用authorize方法,最終通過接口路徑和權限進行校驗,本文給大家介紹SpringSecurity實現(xiàn)動態(tài)權限校驗的相關知識,感興趣的朋友一起看看吧

在框架DefaultSecurityFilterChain源碼內(nèi)打斷點可以找到SpringSecurity的過濾器鏈可以看見一個叫AuthorizationFilter的過濾器

很明顯這個叫authorizationManager的應該是我們要找的玩意,直接去AuthorizationFilter內(nèi)找這個類看他的源碼可以發(fā)現(xiàn)check方法已經(jīng)棄用,他推薦用的方法是authorize但這玩意也還是調(diào)用的check

@FunctionalInterface
public interface AuthorizationManager<T> {
	/**
	 * Determines if access should be granted for a specific authentication and object.
	 * @param authentication the {@link Supplier} of the {@link Authentication} to check
	 * @param object the {@link T} object to check
	 * @throws AccessDeniedException if access is not granted
	 */
	default void verify(Supplier<Authentication> authentication, T object) {
		AuthorizationDecision decision = check(authentication, object);
		if (decision != null && !decision.isGranted()) {
			throw new AuthorizationDeniedException("Access Denied", decision);
		}
	}
	/**
	 * Determines if access is granted for a specific authentication and object.
	 * @param authentication the {@link Supplier} of the {@link Authentication} to check
	 * @param object the {@link T} object to check
	 * @return an {@link AuthorizationDecision} or null if no decision could be made
	 * @deprecated please use {@link #authorize(Supplier, Object)} instead
	 */
	@Nullable
	@Deprecated
	AuthorizationDecision check(Supplier<Authentication> authentication, T object);
	/**
	 * Determines if access is granted for a specific authentication and object.
	 * @param authentication the {@link Supplier} of the {@link Authentication} to
	 * authorize
	 * @param object the {@link T} object to authorize
	 * @return an {@link AuthorizationResult}
	 * @since 6.4
	 */
	@Nullable
	default AuthorizationResult authorize(Supplier<Authentication> authentication, T object) {
		return check(authentication, object);
	}

繼續(xù)往下面看可以看見他是進行了校驗然后返回了一個布爾值

@Override
	public AuthorizationDecision check(Supplier<Authentication> authentication, T object) {
		boolean granted = this.authorizationStrategy.isGranted(authentication.get());
		return new AuthorizationDecision(granted);
	}

代碼實現(xiàn) 邏輯大概是通過傳進來的接口路徑然后匹配權限

@Component
public class DynamicAuthorizationManager implements AuthorizationManager<RequestAuthorizationContext> {
    @Resource
    private DynamicSecurityMetadataSource securityMetadataSource;
    @Override
    public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext context) {
        HttpServletRequest request = context.getRequest();
        // 獲取當前請求所需的權限
        String url = request.getRequestURI();
        String method = request.getMethod();
        FilterInvocation fi = new FilterInvocation(String.valueOf(request), url, method);
        Collection<ConfigAttribute> attributes = securityMetadataSource.getAttributes(fi);
        // 沒有配置權限要求,允許訪問
        if (CollectionUtils.isEmpty(attributes)) {
            return new AuthorizationDecision(true);
        }
        // 獲取當前用戶認證信息
        Authentication auth = authentication.get();
        if (auth == null || !auth.isAuthenticated()) {
            return new AuthorizationDecision(false);
        }
        // 獲取用戶所擁有的權限
        Set<String> userPermissions = auth.getAuthorities().stream()
            .map(GrantedAuthority::getAuthority)
            .collect(Collectors.toSet());
        // 判斷是否有所需權限
        boolean hasPermission = attributes.stream()
            .map(ConfigAttribute::getAttribute)
            .anyMatch(userPermissions::contains);
        return new AuthorizationDecision(hasPermission);
    }
}

getAllConfigAttributes和supports我大概看了一下直接復制粘貼的框架的源碼以后萬一有用呢

@Component
public class DynamicSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
    @Resource
    private TPMenuService menuService;
    private Map<String, Collection<ConfigAttribute>> configAttributeMap;
    @PostConstruct
    public void loadDataSource() {
        configAttributeMap = new HashMap<>();
        List<TPMenu> menus = menuService.list();
        configAttributeMap = menus.stream()
                .filter(menu -> StringUtils.hasText(menu.getPath()) && StringUtils.hasText(menu.getPerms()))
                .collect(Collectors.toMap(
                        TPMenu::getPath,
                        menu -> {
                            List<ConfigAttribute> attributes = new ArrayList<>();
                            attributes.add(new SecurityConfig(menu.getPerms()));
                            return attributes;
                        }
                ));
    }
    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
        String requestUrl = ((FilterInvocation) object).getRequestUrl();
        if (requestUrl.contains("?")) {
            requestUrl = requestUrl.substring(0, requestUrl.indexOf("?"));
        }
        int count = StringUtils.countOccurrencesOf(requestUrl, "/");
        if (count > 2) {
            requestUrl = requestUrl.replaceAll("/[^/]+$", "");
        }
        for (Map.Entry<String, Collection<ConfigAttribute>> entry : configAttributeMap.entrySet()) {
            String pattern = entry.getKey();
            if (new AntPathMatcher().match(pattern, requestUrl)) {
                return entry.getValue();
            }
        }
        return null;
    }
    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        Set<ConfigAttribute> allAttributes = new HashSet<>();
        configAttributeMap.values().forEach(allAttributes::addAll);
        return allAttributes;
    }
    @Override
    public boolean supports(Class<?> clazz) {
        return FilterInvocation.class.isAssignableFrom(clazz);
    }
}

過濾器實現(xiàn)然后記得security配置文件添加這個過濾器就ok了,配置文件可以看我另外一篇文章

@Component
public class DynamicSecurityFilter extends OncePerRequestFilter {
    @Resource
    private DynamicSecurityMetadataSource securityMetadataSource;
    @Resource
    private DynamicAuthorizationManager authorizationManager;
    @Resource
    private AccessDeniedHandler accessDeniedHandler;
    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain chain) throws ServletException, IOException, IOException {
        if (shouldNotFilter(request)) {
            chain.doFilter(request, response);
            return;
        }
        try {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            RequestAuthorizationContext context = new RequestAuthorizationContext(request);
            // 權限檢查
            AuthorizationDecision check = authorizationManager.check(
                    () -> authentication,
                    context
            );
            if (check.isGranted()) {
                chain.doFilter(request, response);
            } else {
                accessDeniedHandler.handle(request, response, new AccessDeniedException("權限不足"));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (ServletException e) {
            throw new RuntimeException(e);
        }
    }
    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) {
        String path = request.getRequestURI();
        return whitelist.stream()
                .anyMatch(pattern ->
                        pattern.endsWith("/**")
                                ? path.startsWith(pattern.substring(0, pattern.length() - 3))
                                : pattern.equals(path)
                );
    }
}

debug重啟可以看見我的過濾器已經(jīng)添加進去了

如果有需要還可以直接去看官方demo
https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/java/jwt/login/src/main

到此這篇關于SpringSecurity實現(xiàn)動態(tài)權限校驗的過程的文章就介紹到這了,更多相關SpringSecurity動態(tài)權限校驗內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Spring創(chuàng)建Bean的生命周期詳析

    Spring創(chuàng)建Bean的生命周期詳析

    這篇文章主要介紹了Spring創(chuàng)建Bean的生命周期詳析,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-09-09
  • 聊聊Spring Cloud Cli 初體驗

    聊聊Spring Cloud Cli 初體驗

    這篇文章主要介紹了聊聊Spring Cloud Cli 初體驗,SpringBoot CLI 是spring Boot項目的腳手架工具。非常具有實用價值,需要的朋友可以參考下
    2018-04-04
  • 詳解spring多線程與定時任務

    詳解spring多線程與定時任務

    本篇文章主要介紹了spring多線程與定時任務,詳細的介紹了spring多線程任務和spring定時任務,有興趣的可以了解一下。
    2017-04-04
  • 手把手教你JAVA進制之間的轉換

    手把手教你JAVA進制之間的轉換

    這篇文章主要介紹了Java實現(xiàn)的進制轉換,結合完整實例形式分析了Java實現(xiàn)二進制、十六進制、字符串、數(shù)組等相關轉換操作技巧,需要的朋友可以參考下
    2021-08-08
  • Java如何使用httpclient檢測url狀態(tài)及鏈接是否能打開

    Java如何使用httpclient檢測url狀態(tài)及鏈接是否能打開

    這篇文章主要介紹了Java如何使用httpclient檢測url狀態(tài)及鏈接是否能打開,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • springboot多租戶設計過程圖解

    springboot多租戶設計過程圖解

    這篇文章主要介紹了springboot多租戶設計過程圖解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-12-12
  • 詳解springboot熱啟動與熱部署

    詳解springboot熱啟動與熱部署

    本篇文章主要介紹了詳解springboot熱啟動與熱部署,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • Java怎么獲取當前時間、計算程序運行時間源碼詳解(超詳細!)

    Java怎么獲取當前時間、計算程序運行時間源碼詳解(超詳細!)

    有的時候,我們需要查看某一段代碼的性能如何,最為簡單的方式,可以通過計算該段代碼執(zhí)行的耗時,來進行簡單的判斷,這篇文章主要給大家介紹了關于Java怎么獲取當前時間、計算程序運行時間的相關資料,需要的朋友可以參考下
    2024-07-07
  • java多線程之定時器Timer的使用詳解

    java多線程之定時器Timer的使用詳解

    本篇文章主要介紹了java多線程之定時器Timer的使用詳解,Time類主要負責完成定時計劃任務的功能,有興趣的可以了解一下。
    2017-04-04
  • Java封裝實現(xiàn)自適應的單位轉換工具類

    Java封裝實現(xiàn)自適應的單位轉換工具類

    這篇文章主要為大家詳細介紹了如何使用Java封裝實現(xiàn)一個自適應的單位轉換工具類,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2025-03-03

最新評論

河西区| 屯门区| 周宁县| 阿拉善右旗| 横峰县| 姚安县| 马公市| 原平市| 海门市| 庆云县| 延津县| 湘乡市| 安陆市| 枣庄市| 德格县| 石河子市| 顺昌县| 潜江市| 焦作市| 安福县| 重庆市| 南岸区| 玉山县| 遵化市| 桐梓县| 武义县| 黄骅市| 定州市| 桐梓县| 巨野县| 泰顺县| 青铜峡市| 秦安县| 江阴市| 江油市| 环江| 柳州市| 肇州县| 汉寿县| 临夏市| 新营市|