【问题标题】:Rust: Thread panics when run inside an iframe but not in a regular browser tabRust:在 iframe 中运行而不是在常规浏览器选项卡中运行时线程恐慌
【发布时间】:2020-12-14 08:05:51
【问题描述】:

我正在使用 Rust 在 Zendesk 上构建应用程序。下面是一个在路由中调用的服务器端 rust 函数

pub fn oktaredirectprocessor(mut cookies: Cookies, code: String, state: String) -> bool {
    let cookie_state_string = cookies.get_private("state").unwrap().value().to_string();
    println!("cookie retrieved in oktaredirectprocessor is {}", cookie_state_string);
    if state != cookie_state_string {
        debug!("State did not match");
        false
    }else if code == ""{
        debug!("Code is empty");
        false
    }else{
        let oktarequest: Oktarequest = Oktarequest::new();
        let http = reqwest::Client::new();
        let config = oidc::discovery::discover(&http, oktarequest.issuer).expect("error in config-discovery-oidc");
        let jwks = oidc::discovery::jwks(&http, config.jwks_uri.clone()).expect("error in jwks-discovery-oidc");
        let provider = oidc::discovery::Discovered(config);
        let client = oidc::Client::new(oktarequest.id, oktarequest.secret, oktarequest.redirect, provider, jwks);
        let mut token = client.request_token(&http, code.as_str()).expect("error in request token-oidc");
        client.decode_token(&mut token.id_token).expect("error in decode token oidc");
        client.validate_token(&token.id_token, Some(cookies.get_private("nonce").unwrap().value()), None).expect("error in validate token oidc");               cookies.add_private(Cookie::new("access_token", token.access_token().to_string()));
        true
    }

}

当我直接从浏览器选项卡运行 localhost 时,它可以工作。但是,如果我从 Zendesk 内部运行应用程序,线程会出现混乱。下面是回溯。我是新手程序员,完全不明白。

thread '<unnamed>' panicked at 'called `Option::unwrap()` on a `None` value', src/main.rs:214:60
stack backtrace:
   0: rust_begin_unwind
             at /rustc/7efc097c4fe6e97f54a44cee91c56189e9ddb41c/library/std/src/panicking.rs:493:5
   1: core::panicking::panic_fmt
             at /rustc/7efc097c4fe6e97f54a44cee91c56189e9ddb41c/library/core/src/panicking.rs:92:14
   2: core::panicking::panic
             at /rustc/7efc097c4fe6e97f54a44cee91c56189e9ddb41c/library/core/src/panicking.rs:50:5
   3: core::option::Option<T>::unwrap
             at /rustc/7efc097c4fe6e97f54a44cee91c56189e9ddb41c/library/core/src/option.rs:386:21
   4: app_remote::oktaredirecthandler
             at ./src/main.rs:214:28
   5: app_remote::rocket_route_fn_oktaredirecthandler
             at ./src/main.rs:213:4
   6: core::ops::function::Fn::call
             at /rustc/7efc097c4fe6e97f54a44cee91c56189e9ddb41c/library/core/src/ops/function.rs:70:5
   7: <F as rocket::handler::Handler>::handle
             at /Users/nalinnarayan/.cargo/registry/src/github.com-1ecc6299db9ec823/rocket-0.4.5/src/handler.rs:177:9
   8: rocket::rocket::Rocket::route
             at /Users/nalinnarayan/.cargo/registry/src/github.com-1ecc6299db9ec823/rocket-0.4.5/src/rocket.rs:296:27
   9: rocket::rocket::Rocket::route_and_process
             at /Users/nalinnarayan/.cargo/registry/src/github.com-1ecc6299db9ec823/rocket-0.4.5/src/rocket.rs:242:34
  10: rocket::rocket::Rocket::dispatch
             at /Users/nalinnarayan/.cargo/registry/src/github.com-1ecc6299db9ec823/rocket-0.4.5/src/rocket.rs:217:28
  11: <rocket::rocket::Rocket as hyper::server::Handler>::handle
             at /Users/nalinnarayan/.cargo/registry/src/github.com-1ecc6299db9ec823/rocket-0.4.5/src/rocket.rs:82:24
  12: hyper::server::Worker<H>::keep_alive_loop
             at /Users/nalinnarayan/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-0.10.16/src/server/mod.rs:340:13
  13: hyper::server::Worker<H>::handle_connection
             at /Users/nalinnarayan/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-0.10.16/src/server/mod.rs:282:15
  14: hyper::server::handle::{{closure}}
             at /Users/nalinnarayan/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-0.10.16/src/server/mod.rs:242:34
  15: hyper::server::listener::spawn_with::{{closure}}
             at /Users/nalinnarayan/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-0.10.16/src/server/listener.rs:50:31

奇怪的是,即使在 Zendesk 中运行,有问题的“cookies.get_private("state").unwrap()”也可以在另一个函数中工作。下面是它工作的功能

fn oktalogin(mut cookies: Cookies) -> Redirect {
    let oktarequest: Oktarequest = Oktarequest::new();
    cookies.add_private(Cookie::new("state", oktarequest.state.clone()));
    cookies.add_private(Cookie::new("nonce", oktarequest.nonce.clone()));
    println!("stored state cookie from random gen is: {}", cookies.get_private("state").unwrap().value().to_string());
    let http = reqwest::Client::new();
    let config = oidc::discovery::discover(&http, oktarequest.issuer).expect("error in config-discovery-oidc");
    let jwks = oidc::discovery::jwks(&http, config.jwks_uri.clone()).expect("error in jwks-discovery-oidc");
    let provider = oidc::discovery::Discovered(config);
    let client = oidc::Client::new(oktarequest.id, oktarequest.secret, oktarequest.redirect, provider, jwks);
    let options = Options{
        scope: Some("openid profile email".to_string()),
        state: Some(oktarequest.state.clone()),
        nonce: Some(oktarequest.nonce.clone()),
        ..Default::default()
        };
    let auth_url = client.auth_url(&options);
    Redirect::to(auth_url.into_string())
}

我的货物.toml

[dependencies]
rocket = { version = "0.4.5", features = ["private-cookies"] }
rocket_codegen = "0.4.5"
serde = "1.0.116"
serde_derive = "1.0.116"
diesel = { version = "1.4.5", features = ["postgres"] }
dotenv = "0.15.0"
serde_urlencoded = "0.7.0"
oidc = "0.3.0"
ring = "=0.16.15"
log = "0.4.8"
rand = "0.7.3"
reqwest = "=0.9.24"
inth-oauth2 = "0.16.0"
url = "=1.7.2"
serde_json = "1.0"
console_log = { version = "0.2", features = ["color"] }

[dependencies.rocket_contrib]
version = "*"
default-features = false
features = ["tera_templates", "json"]

【问题讨论】:

  • 我并不感到惊讶 get_private 在你的第二个例子中考虑到你事先做了add_private。使用.unwrap() 是一种用于假设值存在的钝器。对于检查 cookie,您可能应该避免使用它,而是决定如果预期的 cookie 不存在,oktaredirectprocessor 应该做什么。那么你的问题就变成了,“为什么使用 localhost 传递 cookie,而不使用 zendesk”
  • @kmdreko 谢谢,你是对的。处理 get_private 抛出的 None 可以消除恐慌。关于什么可以让 Zendesk 不通过 cookie 的任何想法?
  • 这取决于您的测试。我不熟悉 Zendesk,但我假设它使用与 localhost 不同的域托管。 Cookie 是特定于域的,iframe 可以有一个单独的域。 Zendesk 托管域显然看不到 localhost 使用的 cookie。但是,如果oktalogin(设置cookie)和oktaredirectprocessor(获取cookie)肯定发生在同一个域上,那么我不知道。

标签: rust zendesk zendesk-api rust-rocket


【解决方案1】:

它在 localhost 中起作用的原因是 cookie 仍然存在。要正常工作需要在cookie不存在时添加代码,没有unwrap()

let cookie_state_string = match cookies.get_private("state") {
    Ok(v) => v.value().to_string(),
    Err(_) => return false,
};

【讨论】:

  • 谢谢明仁。以这种方式处理它避免了线程恐慌。但是,从 Zendesk 运行时,cookie 仍然没有保留。有什么想法吗?
  • 应先调用oktalogin,并存储cookie。然后访问oktaredirectprocessor 并可以得到正确的响应。但是键名“state”太流行了,可能不会被 Zendesk 的 cookie 覆盖,所以它可以通过更改键名来工作。
猜你喜欢
  • 1970-01-01
  • 2015-03-21
  • 1970-01-01
  • 1970-01-01
  • 2012-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-27
相关资源
最近更新 更多