解析 HTTP 的摘要式身份验证的正确正则表达式模式是什么?
What is correct regex pattern to parse HTTP's digest authentication?
我有一个程序来解析HTTP摘要的组件,如下所示:
#include "stdafx.h"
#include <iostream>
#include <string>
#include <regex>
#include <unordered_map>
int main()
{
std::string nsInput = R"(Digest realm = "http-auth@example.org",
qop= " auth, auth-int ", algorithm = MD5 ,
nonce ="7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v" ,
opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS"
)";
// Spaces are inserted into some places of the input intentionally
std::smatch mat_opt, mat_val;
std::unordered_map<std::string, std::string> mapDigest;
try {
std::regex rex_opt(R"(s*([A-Za-z]{3,})s*=)");
std::regex rex_val(R"(s*"s*(.{3,})s*"|s*(.{3,})s*,)");
auto& str = nsInput;
while (std::regex_search(nsInput, mat_opt, rex_opt))
{
if (mat_opt.size() >= 2) {
auto& field = mat_opt[1].str();
std::string& next = mat_opt.suffix().str();
if (std::regex_search(next, mat_val, rex_val) && mat_val.size() >= 2) {
auto& value = mat_val[1].str();
mapDigest[field] = value;
}
str = mat_opt.suffix().str();
}
}
for (auto& itr : mapDigest) {
std::cout << itr.first << ":" << itr.second << ".n";
}
}
catch (std::regex_error& e) {
std::cout << "regex_search failed" << e.what() << "n";
}
return 0;
}
输出:
nonce:7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v.
realm:http-auth@example.org.
qop:auth, auth-int .
algorithm:.
opaque:FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS.
我试图解决的是:
1(空格仍然出现在"qop"值的末尾。
2("算法"的值无法匹配。
有人可以照亮这个晦涩的原因以及如何解决它?
谢谢
首先,您的代码无法编译,因为您尝试将非常量左值引用绑定到以下行中的临时对象:
// ...
auto& field = mat_opt[1].str();
// ...
std::string& next = mat_opt.suffix().str();
// ...
auto& value = mat_val[1].str();
// ...
我建议删除引用,改用auto
或std::string
。由于 RVO,它几乎没有性能损失。
要删除值末尾的空格,您可以在正则表达式模式中使用.{3,}?
而不是.{3,}
。 没有?
.{3,}
将贪婪匹配,因此将匹配后面的所有字符(包括空格(。
字符串MD5
与正则表达式模式中的第二个括号匹配,因此您应该通过 mat_val[2]
而不是 mat_val[1]
来访问它。可以按如下方式使用条件表达式:
auto value = mat_val[1].matched ? mat_val[1].str() : mat_val[2].str();
顺便说一句,由于您使用的是原始字符串文字,因此您无需在正则表达式模式中的字符"
之前编写额外的。
正如其他人所说,正则表达式可能不是解析HTTP摘要的首选武器。
然而,我发现这种模式具有挑战性。使它变得比必要的更难的是,引号中有分隔符,应该忽略(在 qop 部分中(。您的其他问题源于贪婪的匹配(例如{3,}部分(。
无论如何,这是我在 15 分钟后得到的:
=s*((?:[^,"]|"s*([^"]*?)s?")+?)(?=s*,|$)
演示
更新:我加倍努力 - 只是为了证明我的观点。
#include <iostream>
#include <string>
#include <regex>
#include <unordered_map>
int main()
{
std::string nsInput = R"(Digest realm = "http-auth@example.org",
qop= " auth, auth-int ", algorithm = MD5 ,
nonce ="7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v" ,
opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS"
)";
// Spaces are inserted into some places of the input intentionally
std::smatch mat_opt, mat_val;
std::unordered_map<std::string, std::string> mapDigest;
try {
std::regex rex_opt(R"(s*([A-Za-z]{3,})s*=)");
std::regex rex_val("=\s*((?:[^,"]|"\s*([^"]*?)\s?")+?)(?=\s*,|$)");
auto& str = nsInput;
while (std::regex_search(nsInput, mat_opt, rex_opt))
{
if (mat_opt.size() >= 2) {
auto field = mat_opt[1].str();
if (std::regex_search(nsInput, mat_val, rex_val)) {
auto value = mat_val[2].matched ? mat_val[2].str() : mat_val[1].str();
mapDigest[field] = value;
}
str = mat_opt.suffix().str();
}
}
for (auto& itr : mapDigest) {
std::cout << itr.first << ":" << itr.second << ".n";
}
}
catch (std::regex_error& e) {
std::cout << "regex_search failed" << e.what() << "n";
}
return 0;
}
输出:
opaque:FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS.
nonce:7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v.
algorithm:MD5.
realm:http-auth@example.org.
qop:auth, auth-int.
相关文章:
- 正则表达式以匹配数字的重复模式,后跟任何类型的分隔符?
- 编写正则表达式模式 c++
- 标准库中的任何正则表达式语法是否支持 (?(定义)用于子模式参考?
- 有没有办法在C++正则表达式中重用模式的一部分?
- 解析 HTTP 的摘要式身份验证的正确正则表达式模式是什么?
- 如何在 QT 框架工作C++中使用变量作为正则表达式模式
- 如何将正则表达式模式存储为正则表达式对象或字符串
- 将Javascript正则表达式模式转换为C++std::regex的规则
- 正则表达式模式以匹配 switch 语句C++
- 重复特定的正则表达式模式
- C++ 中的多行正则表达式模式
- 需要帮助构建正则表达式模式
- C++ :为什么正则表达式模式"[+-/*]"匹配字符串"."?
- 解析字符串的正则表达式模式
- 增强特殊字符的正则表达式模式
- 如何从正则表达式模式列表中找到最具体的匹配项
- 从配置文件中动态加载正则表达式模式
- c++正则表达式模式检查文件扩展名
- Uri正则表达式模式匹配
- 整数匹配正则表达式模式不工作