微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

火箭 - 在我的守卫中使用状态失败,因为特征没有实现

如何解决火箭 - 在我的守卫中使用状态失败,因为特征没有实现

我想在我的守卫中使用 state。我想拥有需要使用 api 密钥进行身份验证的路由,我想在我的 Rocket.toml 中定义该密钥。但是运行此代码我收到以下错误

特征 From<(Status,())> 未实现 (Status,ApiKeyError)

对于这行代码 let config_state = try_outcome!(req.guard::<State<'_,Config>>().await);

我如何实现这个特性?或者有没有更好的解决方案来管理 Rocket 中的 api 令牌。

我使用的是 0.5.0-dev 版本的 Rocket。

#[macro_use] extern crate rocket;

use rocket::http::Status;
use rocket::request::{Outcome,Request,Fromrequest};
use rocket::State;
use rocket::fairing::AdHoc;
use serde::Deserialize;

#[derive(Deserialize)]
struct Config {
    api_key: String,}

struct ApiKey<'r>(&'r str);

#[derive(Debug)]
enum ApiKeyError {
    Missing,Invalid,}

#[rocket::async_trait]
impl<'r> Fromrequest<'r> for ApiKey<'r> {
    type Error = ApiKeyError;

    async fn from_request(req: &'r Request<'_>) -> Outcome<Self,Self::Error> {

        let config_state = try_outcome!(req.guard::<State<'_,Config>>().await);

        /// Returns true if `key` is a valid API key string.
        fn is_valid(key: &str,api_key: String) -> bool {
            key == api_key
        }

        match req.headers().get_one("Authorization") {
            None => Outcome::Failure((Status::Unauthorized,ApiKeyError::Missing)),Some(key) if is_valid(key,config_state.api_key) => Outcome::Success(ApiKey(key)),Some(_) => Outcome::Failure((Status::Unauthorized,ApiKeyError::Invalid)),}
    }
}

#[get("/")]
async fn index(config: State<'_,Config>,key: ApiKey<'_>) -> &'static str {
    "Hello,world!"
}

fn rocket() -> rocket::Rocket {
    let rocket = rocket::ignite();
    let figment = rocket.figment();

    let config: Config = figment.extract().expect("config");

    rocket
    .mount("/",routes![index])
    .attach(AdHoc::config::<Config>())
}

#[rocket::main]
async fn main() {
    rocket()
        .launch()
        .await;
}

解决方法

我已经使用 AdHoch::config() 存储了配置,但要在防护中检索它,我需要使用 request.rocket().state::<Config>()。更正后的源代码如下:

#[macro_use] extern crate rocket;

use rocket::http::Status;
use rocket::request::{Outcome,Request,FromRequest};
use rocket::State;
use rocket::fairing::AdHoc;
use serde::Deserialize;

#[derive(Deserialize)]
struct Config {
    api_key: String,}

struct ApiKey<'r>(&'r str);

#[derive(Debug)]
enum ApiKeyError {
    Missing,Invalid,}

#[rocket::async_trait]
impl<'r> FromRequest<'r> for ApiKey<'r> {
    type Error = ApiKeyError;

    async fn from_request(req: &'r Request<'_>) -> Outcome<Self,Self::Error> {

        // Retrieve the config state like this
        let config = req.rocket().state::<Config>().unwrap();

        /// Returns true if `key` is a valid API key string.
        fn is_valid(key: &str,api_key: &str) -> bool {
            key == api_key
        }

        match req.headers().get_one("Authorization") {
            None => Outcome::Failure((Status::Unauthorized,ApiKeyError::Missing)),Some(key) if is_valid(key,&config.api_key) => Outcome::Success(ApiKey(key)),Some(_) => Outcome::Failure((Status::Unauthorized,ApiKeyError::Invalid)),}
    }
}

#[get("/")]
async fn index(config: State<'_,Config>,key: ApiKey<'_>) -> &'static str {
    "Hello,world!"
}

fn rocket() -> rocket::Rocket {
    let rocket = rocket::ignite();
    let figment = rocket.figment();

    let config: Config = figment.extract().expect("config");

    rocket
    .mount("/",routes![index])
    .attach(AdHoc::config::<Config>())
}

#[rocket::main]
async fn main() {
    rocket()
        .launch()
        .await;
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。