Spring Security6 教程

DeferringObservationAuthorizationManager 授权管理器

DeferringObservationAuthorizationManager 类用于在授权决策过程中收集观测数据(observability data),特别是针对需要延迟执行的授权决策。它主要作为一个装饰器(Decorator),包装其他 AuthorizationManager 实例,并在授权决策完成后记录观察指标(如执行时间、成功 / 失败状态)。

核心功能

  • 延迟观察,在授权决策执行后,捕获并记录决策结果和性能指标。

  • 指标收集,集成 Micrometer 观测系统,自动收集授权决策的执行时间、成功率等指标。

  • 非侵入式增强,不改变原有授权逻辑,仅在决策完成后进行观察记录。

适用场景

  • 需要监控授权决策性能的场景。

  • 分析不同权限规则的执行效率。

  • 记录授权失败的频率和原因。

源码分析

下面是 DeferringObservationAuthorizationManager 类的部分源码:

package org.springframework.security.config.annotation.method.configuration;

import java.util.function.Supplier;
import io.micrometer.observation.ObservationRegistry;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.authorization.AuthorizationResult;
import org.springframework.security.authorization.ObservationAuthorizationManager;
import org.springframework.security.authorization.method.MethodAuthorizationDeniedHandler;
import org.springframework.security.authorization.method.MethodInvocationResult;
import org.springframework.security.authorization.method.ThrowingMethodAuthorizationDeniedHandler;
import org.springframework.security.core.Authentication;
import org.springframework.util.function.SingletonSupplier;

/**
 * 延迟观察授权管理器 - 用于在授权决策后进行指标收集和观察
 * 该类包装另一个 AuthorizationManager,在其决策完成后记录观察指标
 * 支持与 Micrometer 集成,实现授权决策的性能监控
 */
final class DeferringObservationAuthorizationManager<T>
       implements AuthorizationManager<T>, MethodAuthorizationDeniedHandler {
    // 被装饰的授权管理器提供者(延迟初始化)
    private final Supplier<AuthorizationManager<T>> delegate;
    // 方法授权拒绝处理器
    private MethodAuthorizationDeniedHandler handler = new ThrowingMethodAuthorizationDeniedHandler();

    /**
     * 构造函数
     * @param provider ObservationRegistry 对象提供者
     * @param delegate 被装饰的授权管理器
     */
    DeferringObservationAuthorizationManager(ObjectProvider<ObservationRegistry> provider,
          AuthorizationManager<T> delegate) {
       // 使用单例提供者延迟初始化授权管理器
       this.delegate = SingletonSupplier.of(() -> {
          // 获取 ObservationRegistry 实例,如果不可用则使用 NOOP 实现
          ObservationRegistry registry = provider.getIfAvailable(() -> ObservationRegistry.NOOP);
          // 如果注册表为 NOOP(无操作),则直接使用原始授权管理器
          if (registry.isNoop()) {
             return delegate;
          }
          // 否则使用 ObservationAuthorizationManager 包装原始管理器以添加观察功能
          return new ObservationAuthorizationManager<>(registry, delegate);
       });
       if (delegate instanceof MethodAuthorizationDeniedHandler h) {
          this.handler = h;
       }
    }

    /**
      * 检查授权决策
      * @param authentication 认证信息提供者
      * @param object 待授权的对象
      * @return 授权决策结果
      */
    @Override
    public AuthorizationDecision check(Supplier<Authentication> authentication, T object) {
       // 委托给实际的授权管理器进行决策
       return this.delegate.get().check(authentication, object);
    }

     /**
      * 处理方法调用被拒绝的情况
      * @param methodInvocation 方法调用对象
      * @param authorizationResult 授权结果
      * @return 处理结果对象
      */
    @Override
    public Object handleDeniedInvocation(MethodInvocation methodInvocation, AuthorizationResult authorizationResult) {
       // 委托给拒绝处理器处理
       return this.handler.handleDeniedInvocation(methodInvocation, authorizationResult);
    }

    /**
      * 处理带返回值的方法调用被拒绝的情况
      * @param methodInvocationResult 方法调用结果对象
      * @param authorizationResult 授权结果
      * @return 处理结果对象
      */
    @Override
    public Object handleDeniedInvocationResult(MethodInvocationResult methodInvocationResult,
          AuthorizationResult authorizationResult) {
       // 委托给拒绝处理器处理
       return this.handler.handleDeniedInvocationResult(methodInvocationResult, authorizationResult);
    }

}

DeferringObservationAuthorizationManager 类通过非侵入式方式为授权决策添加监控能力。它适用于需要深入了解权限控制行为的生产环境,帮助开发者优化授权策略和排查问题。

简单应用

虽然不能直接访问 DeferringObservationAuthorizationManager,但 Spring Security 提供了自动配置机制和工厂方法来启用观察功能。详细步骤如下:

添加依赖

在 Spring Boot 应用中,只需添加 Micrometer 依赖并启用观察功能:

<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-core</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

添加配置

配置文件添加如下配置,启用安全指标:

management.metrics.enable.security= true

此时,Spring Security 会自动包装所有授权管理器,添加观察功能。

公开指标

通过 Actuator 端点查看指标,添加如下接口,如下:

package com.hxstrive.spring_security.controller;

import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collection;
import java.util.stream.Collectors;

/**
 * 简单控制器
 * @author hxstrive.com
 */
@RestController
public class HelloController {

    @Autowired
    private MeterRegistry meterRegistry;

    // 通过 Actuator 端点查看指标
    @GetMapping("/metrics")
    public Collection<Meter> getMetrics() {
        return meterRegistry.getMeters()
                .stream()
                .filter(m -> m.getId().getName().startsWith("spring.security"))
                .collect(Collectors.toList());
    }

}

重启服务器,访问 /metrics 接口,浏览器返回信息如下图:

image.png

从上图中可以看出,输出了很多关于 spring.security 的指标信息。

 

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
其他应用
公众号