VaporScope

VaporAuth 是一个用于权限断言的库。

安装

Swift Package Manager

dependencies: [
    .package(url: "https://github.com/Myoland/VaporAuth.git", from: "1.0.0"),
]

快速预览

import VaporAuth
public struct User: AuthCarrier {
    enum CodingKeys: String, CodingKey {...}
    
    public var subject: SubjectClaim
    public var scopes: ScopeClaim
    
    public func verify(using signer: JWTSigner) throws {...}
    
    public init(...) {...}
}

let app = try Application(.detect())
app.routes
    .grouped(User.authenticator())
    .grouped(\User.scope, "a_scope b_scope")
    .on(.GET, "a", use: handler)

app.routes
    .grouped(User.authenticator())
    .grouped(\User.subject, "sub")
    .grouped(\User.scope, ["a_scope", "b_scope"])
    .on(.GET, "a", use: handler)

使用

创建一个 JWT 声明

public struct ScopeClaim: JWTClaim, Equatable {

    public var value: [String]

    public init(value: [String]) {
        self.value = value
    }
    
    public static func == (lhs: ScopeClaim, rhs: ScopeClaim) -> Bool {
        return Set(rhs.value) == Set(lhs.value)
    }
}

遵循 Guardable 协议

extension ScopeClaim: Comparable {
    public static func < (lhs: ScopeClaim, rhs: ScopeClaim) -> Bool {...}
}

extension ScopeClaim: Guardable {
    public func hasAuth(required: ScopeClaim) -> Bool {
        required == self || required < self
    }
}

在权限断言中使用它

app.routes
    .grouped(User.authenticator())
    .grouped(\User.scope, ["a_scope", "b_scope"])
    .on(.GET, "a", use: handler)

详情

声明的编码和解码

let scope = ScopeClaim(value: ["a", "b"])
let encoded = try JSONEncoder().encode(scope)
let decoded = try JSONDecoder().decode(ScopeClaim.self, from: encoded)

谓词 (Predicate)

为了比较所需权限和携带权限之间的值,我们使用了谓词的理念。

谓词是对获取或内存中过滤的搜索进行约束的逻辑条件的定义。

通常,要确定用户是否有权访问处理程序,我们只需要一个布尔值,一个结果。因此,我们不关心所需的权限或任何其他事情,我们只关心给定的权限和结果。这就是谓词的作用。

请注意,谓词支持基本的逻辑运算,例如 &&, ||, !

在 VaporAuth 中,我们提供 AuthPredicate 来帮助我们确定用户是否具有权限。

AuthPredicate 有两种实现: AuthBasePredicateAuthFieldPredicate

let a = AuthBasePredicate<Carrier> { user in
    user.sub == "some"
}
let b = AuthFieldPredicate(\Carrier.iss, "any")
let c = a && b

let _ = a.hasAuth(carrier: user) 
let _ = b.hasAuth(carrier: user)
let _ = c.hasAuth(carrier: user)

认证

在检查权限之前,我们需要对用户进行身份验证。

当你的信息遵循 JWTPayload 协议时,很容易进行身份验证。

 app.routes
    .grouped(User.authenticator())
    .on(.GET, "a", use: handler)