我正在尝试编写一些使用基本身份验证的简单测试用户身份验证机制。如何从标题中检索凭据?
string authorizationHeader = this.HttpContext.Request.Headers["Authorization"];
我从哪里开始?有几个教程,但我是.NET和身份验证的新手,你能在答案中一步一步地解释你正在做什么和为什么。
答案 0 :(得分:160)
来自我的博客:
这将详细解释这一切是如何运作的:
每当您使用基本身份验证时,都会向HTTP请求添加一个标头,它将类似于:
授权:基本QWxhZGRpbjpvcGVuIHNlc2FtZQ ==
来源:http://en.wikipedia.org/wiki/Basic_access_authentication
“QWxhZGRpbjpvcGVuIHNlc2FtZQ ==”只是在Base64(http://en.wikipedia.org/wiki/Base64)中编码的“用户名:密码”。要在.NET(C#)中访问标头和其他HTTP属性,您需要有权访问当前的Http上下文:
HttpContext httpContext = HttpContext.Current;
您可以在System.Web命名空间中找到它。
授权标头不是HttpContext中唯一的标头。为了访问标题,我们需要从请求中获取它。
string authHeader = this.httpContext.Request.Headers["Authorization"];
如果您调试代码,您会看到该标题的内容与此类似:
基本QWxhZGRpbjpvcGVuIHNlc2FtZQ ==
您已经提取了标题,现在您需要做几件事:
像这样:
if (authHeader != null && authHeader.StartsWith("Basic")) {
//Extract credentials
} else {
//Handle what happens if that isn't the case
throw new Exception("The authorization header is either empty or isn't Basic.");
}
现在您已经检查过您是否有从中提取数据的内容。
您现在可以尝试获取用户名和密码的值。首先,你需要摆脱“基本”子串。你可以这样做:
string encodedUsernamePassword = authHeader.Substring("Basic ".Length).Trim();
有关详细信息,请参阅以下链接:
现在我们需要从Base64解码回字符串:
//the coding should be iso or you could use ASCII and UTF-8 decoder
Encoding encoding = Encoding.GetEncoding("iso-8859-1");
string usernamePassword = encoding.GetString(Convert.FromBase64String(encodedUsernamePassword));
现在,用户名和密码将采用以下格式:
username:password
为了获得用户名和密码,我们可以简单地获得“:”
的索引int seperatorIndex = usernamePassword.IndexOf(':');
username = usernamePassword.Substring(0, seperatorIndex);
password = usernamePassword.Substring(seperatorIndex + 1);
现在您可以使用这些数据进行测试。祝你好运!
PS:最终代码可能如下所示:
HttpContext httpContext = HttpContext.Current;
string authHeader = this.httpContext.Request.Headers["Authorization"];
if (authHeader != null && authHeader.StartsWith("Basic")) {
string encodedUsernamePassword = authHeader.Substring("Basic ".Length).Trim();
Encoding encoding = Encoding.GetEncoding("iso-8859-1");
string usernamePassword = encoding.GetString(Convert.FromBase64String(encodedUsernamePassword));
int seperatorIndex = usernamePassword.IndexOf(':');
var username = usernamePassword.Substring(0, seperatorIndex);
var password = usernamePassword.Substring(seperatorIndex + 1);
} else {
//Handle what happens if that isn't the case
throw new Exception("The authorization header is either empty or isn't Basic.");
}
答案 1 :(得分:3)
来自@DawidO的精彩回答。
如果你只想提取基本的auth信誉并依赖于.NET魔法给你有HttpContext,这也会有效:
public static void StartListener() {
using (var hl = new HttpListener()) {
hl.Prefixes.Add("http://+:8008/");
hl.AuthenticationSchemes = AuthenticationSchemes.Basic;
hl.Start();
Console.WriteLine("Listening...");
while (true) {
var hlc = hl.GetContext();
var hlbi = (HttpListenerBasicIdentity)hlc.User.Identity;
Console.WriteLine(hlbi.Name);
Console.WriteLine(hlbi.Password);
//TODO: validater user
//TODO: take action
}
}
}
答案 2 :(得分:2)
因此,只需添加主要答案,即可摆脱“基本”子字符串的最佳方法是:
var header = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]);
var credentials = header.Parameter;
如果标头的内容无效,例如:“基本”部分不存在,它将引发FormatException。
答案 3 :(得分:0)
请记住,使用字符串可能不太安全。它们将保留在内存中,直到被GC选中为止。