【问题标题】:Deserializing a Claims field to string returns additional characters将 Claims 字段反序列化为字符串会返回其他字符
【发布时间】:2019-09-30 05:08:52
【问题描述】:

我需要反序列化以下负载,特别是 JSON 对象中的 aud 字段:

claims: Claims { 
    aud: One("CBr3zBlrKBbwmxOAM1avZQ=="), // 24 len
    // ...
}

claims::aud 是一个 Aud 枚举:

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
#[serde(untagged)]
pub enum Aud {
    One(String),
    Many(Vec<String>),
}

当我尝试从serde_json::to_string() 获取String 时,它会返回另外两个字符,一个开始字符和结束字符。

use serde_json::Result;

fn aud_from_json(data: &claims::Aud) -> Result<String> {
    let v = serde_json::to_string(&data)?;
    Ok(v.to_owned())
}
let aud = aud_from_json(&token_data.claims.aud)?;
log::debug!("aud field: {:?}\t aud field len({})", &aud, &aud.len());
$ aud field: "\"CBr3zBlrKBbwmxOAM1avZQ==\""         aud field len(26)

看起来可能有尾随转义字符序列化到字符串中。
有没有一种方法可以返回aud 字段返回为String,并在没有多余字符的情况下进行清理?
例如"CBr3zBlrKBbwmxOAM1avZQ=="

【问题讨论】:

  • 很难回答您的问题,因为它不包含minimal reproducible example。我们无法分辨代码中存在哪些 crate(及其版本)、类型、特征、字段等。如果您尝试在 Rust Playground 上重现您的错误,如果可能的话,这将使我们更容易为您提供帮助,否则在全新的 Cargo 项目中,然后在 edit 您的问题中包含附加信息。您可以使用Rust-specific MRE tips 来减少您在此处发布的原始代码。谢谢!
  • 您还有一些名称不佳的函数,这些函数可能是您的一些问题的基础。例如,您有一个名为 aud_from_json 的函数,它不接受 JSON 作为参数。相反,它似乎创建 JSON。

标签: rust escaping serde-json


【解决方案1】:

问题在于 serde_json::to_string() 被误认为是实际的 to_string() 实现,而不是 JSON 字符串。

提取枚举变体的内部成员最好通过模式匹配来完成。由于OP的要求,Vec的最后一个aud成员是最重要的一个

最终实现(playground):

use std::io::Result;
use serde;
#[macro_use] extern crate serde_derive;

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
#[serde(untagged)]
pub enum Aud {
    One(String),
    Many(Vec<String>),
}

fn aud_from_json(data: &Aud) -> Result<String> {
    match data {
        Aud::One(audience) => Ok(audience.clone()),
        Aud::Many(audiences) => audiences
          .last()
          .ok_or(std::io::Error::new(std::io::ErrorKind::NotFound, "No audience found"))
          .map(|r| r.clone())
    }
}

【讨论】:

  • 他的问题是关于“在字符串中序列化的额外转义字符”,你根本没有解决这个问题
  • 添加了免责声明,尽管老实说我不明白这可能是什么问题。这实际上是标准的Debug 行为。
  • @SébastienRenauld,感谢您的澄清。我确实需要解析不带引号的字符串,因为我需要解密 aud 字段。正如您所指出的那样,我可能需要对 Deserialize 特征进行更多挖掘或手动解析它们。我想也许 serde-json 有一个方便的方法来处理这种情况,我不知道。
  • @Alex 我感觉你使用了错误的工具来完成这项工作。以问题中提供的 base64 编码字符串为例,对吗?这是 JWT 的一部分吗?如果是这样,JSON 在哪里以及如何涉及?
  • @SébastienRenauld aud 被用作加密的受众服务器标识符,以 base64 的形式注入到令牌中。这只是在 Atlassian S2S 身份验证协议规范之上增加的一层混淆。我想从给定的令牌响应中解构 aud 并将其值解密为检查方法。
【解决方案2】:

如果我正确理解了您在回复 @SébastienRenauld 的回答时所说的话,您希望对 Aud 实例中包含的字符串进行 base-64 解码。这可以通过以下方式实现:

let aud = Aud::One("CBr3zBlrKBbwmxOAM1avZQ==".to_string());
if let Aud::One(code) = aud {
    let decoded = base64::decode(&code).unwrap();
    log::debug!("Decoded: {:?}", decoded);
}

playground

【讨论】:

  • 不完全是,aud 是一个 AES 256 位 base64 编码字段。我将在包装方法中使用密钥,该方法将调用decrypt_base64_to_string(aud: &amp;str)
猜你喜欢
  • 2021-01-08
  • 2020-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多