我需要解析的值是Www-Authenticate
HTTP响应标头的一部分:
realm="https://auth.docker.io/token",service="registry.docker.io",scope="registry:catalog:*"
我想获得一个包含以下值的字典(或类似字体):
{ "realm", "https://auth.docker.io/token" },
{ "service", "registry.docker.io" },
{ "scope", "registry:catalog:*"},
.NET中是否有一些实用程序可以解析它?
这就是我获得价值的方式。在调用Web API服务时,我收到了一个未经授权的响应(这是预期的):
var httpClient = new HttpClient();
//This is a public url
var response = await httpClient.GetAsync("https://registry-1.docker.io/v2/_catalog")
// This is the value that needs to be parsed
string parameter = response.Headers.WwwAuthenticate.FirstOrDefault().Parameter;
我尝试/看过的事情:
string.Split
。这样安全吗?如果引用值中有逗号,该怎么办?答案 0 :(得分:1)
使用RFC6750和RFC2616中定义的架构,下面提供了一个更为精确的解析器实现。该解析器考虑了字符串可能包含=
,,
和/或转义的"
的可能性。
internal class AuthParamParser
{
private string _buffer;
private int _i;
private AuthParamParser(string param)
{
_buffer = param;
_i = 0;
}
public static Dictionary<string, string> Parse(string param)
{
var state = new AuthParamParser(param);
var result = new Dictionary<string, string>();
var token = state.ReadToken();
while (!string.IsNullOrEmpty(token))
{
if (!state.ReadDelim('='))
return result;
result.Add(token, state.ReadString());
if (!state.ReadDelim(','))
return result;
token = state.ReadToken();
}
return result;
}
private string ReadToken()
{
var start = _i;
while (_i < _buffer.Length && ValidTokenChar(_buffer[_i]))
_i++;
return _buffer.Substring(start, _i - start);
}
private bool ReadDelim(char ch)
{
while (_i < _buffer.Length && char.IsWhiteSpace(_buffer[_i]))
_i++;
if (_i >= _buffer.Length || _buffer[_i] != ch)
return false;
_i++;
while (_i < _buffer.Length && char.IsWhiteSpace(_buffer[_i]))
_i++;
return true;
}
private string ReadString()
{
if (_i < _buffer.Length && _buffer[_i] == '"')
{
var buffer = new StringBuilder();
_i++;
while (_i < _buffer.Length)
{
if (_buffer[_i] == '\\' && (_i + 1) < _buffer.Length)
{
_i++;
buffer.Append(_buffer[_i]);
_i++;
}
else if (_buffer[_i] == '"')
{
_i++;
return buffer.ToString();
}
else
{
buffer.Append(_buffer[_i]);
_i++;
}
}
return buffer.ToString();
}
else
{
return ReadToken();
}
}
private bool ValidTokenChar(char ch)
{
if (ch < 32)
return false;
if (ch == '(' || ch == ')' || ch == '<' || ch == '>' || ch == '@'
|| ch == ',' || ch == ';' || ch == ':' || ch == '\\' || ch == '"'
|| ch == '/' || ch == '[' || ch == ']' || ch == '?' || ch == '='
|| ch == '{' || ch == '}' || ch == 127 || ch == ' ' || ch == '\t')
return false;
return true;
}
}
答案 1 :(得分:0)
从Forty3指示我的答案中,我想出了以下内容:
public static class AuthenticateParser
{
public static IDictionary<string, string> Parse(string value)
{
//https://stackoverflow.com/questions/45516717/extracting-and-parsing-the-www-authenticate-header-from-httpresponsemessage-in/45516809#45516809
string[] commaSplit = value.Split(", ".ToCharArray());
return commaSplit
.ToDictionary(GetKey, GetValue);
}
private static string GetKey(string pair)
{
int equalPos = pair.IndexOf("=");
if (equalPos < 1)
throw new FormatException("No '=' found.");
return pair.Substring(0, equalPos);
}
private static string GetValue(string pair)
{
int equalPos = pair.IndexOf("=");
if (equalPos < 1)
throw new FormatException("No '=' found.");
string value = pair.Substring(equalPos + 1).Trim();
//Trim quotes
if (value.StartsWith("\"") && value.EndsWith("\""))
{
value = value.Substring(1, value.Length - 2);
}
return value;
}
}