Skip to content

条件匹配器

条件匹配器为策略和声明评估添加了细粒度控制。动作匹配器决定什么请求被发出,而条件匹配器决定规则何时应基于请求属性、安全上下文、速率限制或自定义表达式来应用。

ConditionMatcher 接口

ConditionMatcher 扩展了 RequestMatcher

kotlin
interface ConditionMatcher : RequestMatcher

AbstractConditionMatcher

AbstractConditionMatcher 提供了 negate 选项和模板方法模式:

kotlin
abstract class AbstractConditionMatcher(
    final override val type: String,
    final override val configuration: Configuration
) : ConditionMatcher {
    private val negate: Boolean = configuration.get("negate")?.asBoolean() ?: false

    override fun match(request, securityContext): Boolean {
        val match = internalMatch(request, securityContext)
        return if (negate) !match else match
    }
}

任何条件都可以通过在配置中设置 "negate": true 来取反。

PartExtractor 框架

许多条件匹配器共享一个通用模式:从请求或安全上下文中提取值,然后进行比较。PartExtractor 框架将此形式化:

kotlin
fun interface PartExtractor {
    fun extract(request: Request, securityContext: SecurityContext): String
}

部分标识符

DefaultPartExtractor 支持以下部分标识符:

请求部分(前缀 request.):

部分描述
request.path请求 URL 路径
request.methodHTTP 方法
request.appId应用 ID
request.spaceId空间 ID
request.deviceId设备 ID
request.remoteIp客户端 IP 地址
request.originOrigin 头 URI
request.origin.hostOrigin 主机
request.refererReferer 头 URI
request.referer.hostReferer 主机
request.header.{key}请求头值
request.attributes.{key}请求属性
request.path.var.{key}路径变量(由 PathActionMatcher 设置)

安全上下文部分(前缀 context.):

部分描述
context.tenantId当前租户 ID
context.principal.id主体用户 ID
context.principal.attributes.{key}主体属性值

条件匹配器类型

基于路径的匹配器

所有基于路径的匹配器都扩展了 PartConditionMatcher,操作提取的字符串值:

匹配器类型键描述
EqConditionMatchereq相等检查(支持模板表达式和 ignoreCase
ContainsConditionMatchercontains子字符串包含检查
StartsWithConditionMatcherstartsWith前缀检查
EndsWithConditionMatcherendsWith后缀检查
InConditionMatcherin集合成员检查
RegularConditionMatcherregular正则表达式匹配
PathConditionMatcherpathSpring PathPattern 匹配

基于上下文的匹配器

这些匹配器直接检查安全上下文:

匹配器类型键描述
AuthenticatedConditionMatcherauthenticated检查 securityContext.principal.authenticated
InRoleConditionMatcherinRole检查主体是否具有特定角色
InTenantConditionMatcherinTenant检查租户类型(DEFAULT、USER、PLATFORM)

速率限制器

匹配器类型键描述
RateLimiterConditionMatcherrateLimiter使用 Guava RateLimiter 的全局速率限制
GroupedRateLimiterConditionMatchergroupedRateLimiter按组的速率限制(例如,按用户、按 IP)

RateLimiterConditionMatcher 创建一个跨所有请求共享的单个速率限制器。GroupedRateLimiterConditionMatcher 创建一个按提取的部分值为键的 LoadingCache 速率限制器,访问后自动过期。

当超出速率限制时,会抛出 TooManyRequestsException,授权层会捕获并将其转换为 AuthorizeResult.TOO_MANY_REQUESTS

基于表达式的匹配器

匹配器类型键描述
OgnlConditionMatcherognlOGNL 表达式评估
SpelConditionMatcherspelSpring 表达式语言评估

两者都在其表达式根中提供对 requestcontext 对象的访问,支持任意复杂的条件。

布尔组合器

BoolConditionMatcher 使用 AND/OR 逻辑组合多个条件:

kotlin
class BoolConditionMatcher(configuration: Configuration) {
    val and: List<ConditionMatcher>
    val or: List<ConditionMatcher>
}
  • ANDand 列表中的所有条件都必须匹配。如果任何一个失败,结果为 false。
  • ORor 列表中至少一个条件必须匹配。如果都不匹配,结果为 false。
  • 当只有 and(没有 or)时,所有 AND 条件通过后返回 true。

SPI:ConditionMatcherFactory

ConditionMatcherFactory 是 SPI 接口:

kotlin
interface ConditionMatcherFactory {
    val type: String
    fun create(configuration: Configuration): ConditionMatcher
}

自定义条件匹配器通过 META-INF/services/me.ahoo.cosec.policy.condition.ConditionMatcherFactory 注册。

架构图

条件匹配器类层次结构

mermaid
classDiagram
    direction TB
    class ConditionMatcher {
        <<interface>>
        +match(request, context): Boolean
    }
    class AbstractConditionMatcher {
        <<abstract>>
        +type: String
        -negate: Boolean
        +match(request, context): Boolean
        #internalMatch(request, context): Boolean
    }
    class PartConditionMatcher {
        <<abstract>>
        -partExtractor: PartExtractor
        #internalMatch(request, context): Boolean
        #matchPart(partValue, context): Boolean
    }

    ConditionMatcher <|.. AbstractConditionMatcher
    ConditionMatcher <|.. RateLimiterConditionMatcher
    ConditionMatcher <|.. BoolConditionMatcher
    AbstractConditionMatcher <|-- PartConditionMatcher
    AbstractConditionMatcher <|-- AuthenticatedConditionMatcher
    AbstractConditionMatcher <|-- InRoleConditionMatcher
    AbstractConditionMatcher <|-- InTenantConditionMatcher
    AbstractConditionMatcher <|-- OgnlConditionMatcher
    AbstractConditionMatcher <|-- SpelConditionMatcher
    PartConditionMatcher <|-- EqConditionMatcher
    PartConditionMatcher <|-- ContainsConditionMatcher
    PartConditionMatcher <|-- StartsWithConditionMatcher
    PartConditionMatcher <|-- EndsWithConditionMatcher
    PartConditionMatcher <|-- InConditionMatcher
    PartConditionMatcher <|-- RegularConditionMatcher
    PartConditionMatcher <|-- PathConditionMatcher
    PartConditionMatcher <|-- GroupedRateLimiterConditionMatcher

基于部分的条件评估流程

mermaid
flowchart TD
    A["PartConditionMatcher.match(request, context)"] --> B["negate check"]
    B --> C["partExtractor.extract(request, context)"]
    C --> D["Extract value from request or context"]
    D --> E["matchPart(partValue, context)"]
    E --> F{"Result"}
    F -->|"true"| G["return true (or false if negate)"]
    F -->|"false"| H["return false (or true if negate)"]

    style A fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style B fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style C fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style D fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style E fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style F fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style G fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style H fill:#2d333b,stroke:#6d5dfc,color:#e6edf3

布尔组合器评估

mermaid
sequenceDiagram
    autonumber
    participant Caller
    participant Bool as BoolConditionMatcher
    participant AndC as "AND Conditions"
    participant OrC as "OR Conditions"

    Caller->>Bool: match(request, context)
    loop each AND condition
        Bool->>AndC: condition.match(request, context)
        alt AND fails
            AndC-->>Bool: false
            Bool-->>Caller: false
        end
    end
    Note over Bool: All AND conditions passed
    alt OR list is empty
        Bool-->>Caller: true
    else OR list has items
        loop each OR condition
            Bool->>OrC: condition.match(request, context)
            alt OR matches
                OrC-->>Bool: true
                Bool-->>Caller: true
            end
        end
        Note over Bool: No OR condition matched
        Bool-->>Caller: false
    end

策略 JSON 示例

基于路径的条件

json
{
  "condition": {
    "eq": {
      "part": "request.path",
      "value": "/api/admin"
    }
  }
}

速率限制器(按用户)

json
{
  "condition": {
    "groupedRateLimiter": {
      "part": "context.principal.id",
      "permitsPerSecond": 10.0,
      "expireAfterAccessSecond": 60
    }
  }
}

布尔组合

json
{
  "condition": {
    "bool": {
      "and": [
        { "authenticated": {} },
        { "inRole": { "value": "admin" } }
      ],
      "or": [
        { "eq": { "part": "request.method", "value": "GET" } },
        { "startsWith": { "part": "request.path", "value": "/api/public" } }
      ]
    }
  }
}

参考文献

相关页面

基于 Apache License 2.0 发布