基于 header 的 Rocket 中的全局 authentication/authorization

Global authentication/authorization in Rocket based on a header

我知道我可以使用 Request guard。但是,如果我有一个包含数百个处理程序的 REST API,不仅必须向所有这些处理程序添加一个额外的函数参数会很烦人,而且让我有点害怕的是很容易错过添加这样的一个参数在这里或那里,因此创建一个安全漏洞。这就是为什么我想知道是否有办法进行这样的验证 globally.

Fairings 上的文档提到它们可以 用于全局安全策略:

As a general rule of thumb, only globally applicable actions should be implemented via fairings. For instance, you should not use a fairing to implement authentication or authorization (preferring to use a request guard instead) unless the authentication or authorization applies to the entire application. On the other hand, you should use a fairing to record timing and/or usage statistics or to implement global security policies.

但与此同时,on_request() 回调的文档是这样说的:

A request callback can modify the request at will and Data::peek() into the incoming data. It may not, however, abort or respond directly to the request; these issues are better handled via request guards or via response callbacks.

那么我应该如何 return 在令牌无效的情况下向用户发出错误消息?

好的,我想我找到了一个方法...

首先我们创建一个像这样的“虚拟”处理程序:

#[put("/errHnd", format = "json")]
fn err_handler() -> ApiResult {
    // Here simply return an error
}

然后我们附上这样的整流罩:

rocket::custom(cfg)
    .attach(AdHoc::on_request("OnReq", |req, _| {
        // Here we validate the token and if it's not OK,
        // forward the request to our "dummy" handler:
        let u = Origin::parse("/errHnd").unwrap();
        req.set_uri(u);
        req.set_method(Method::Put);
    }))
    .mount("/", routes![err_handler, ...
    

我不确定这是最好的方法,但我测试了它并且它似乎有效。我愿意接受其他建议。

P.S。可能还值得一提的是,如果我们想有一个例外,以便跳过整流罩中的验证,比如说,基于URL,我们可以简单地添加里面有这样的东西:

if req.uri().path() == "/let-me-in-please" {
    return;
}