asp.net-mvc 具有成员资格提供程序的 ASP.NET MVC 4 Web API 身份验证
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11535075/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ASP.NET MVC 4 Web API Authentication with Membership Provider
提问by INNVTV
I have an ASP.NET MVC 4 Project using the Web API. On the controller I have set the class to require authorization using the [Authorize] attribute. For Authentication I am using the ASP.NET Membership Provider and have my Web.Config set to use "Forms" Authentication. Here is where I am stuck:
我有一个使用 Web API 的 ASP.NET MVC 4 项目。在控制器上,我使用 [Authorize] 属性将类设置为需要授权。对于身份验证,我使用 ASP.NET 成员身份提供程序并将我的 Web.Config 设置为使用“表单”身份验证。这是我被困的地方:
Everything is working great up until the point that I am done with testing the API and I want to secure the controller with the [Authorize] attribute so I can start testing authentication against users in my Membership Provider. So I fire up Fiddler and make the same call adding the Authorization:Basic attribute along with a username:password from my membership provider like so:
在我完成 API 测试之前,一切都运行良好,并且我想使用 [Authorize] 属性保护控制器,以便我可以开始针对我的会员提供程序中的用户测试身份验证。所以我启动 Fiddler 并进行相同的调用,添加 Authorization:Basic 属性以及来自我的会员提供商的用户名:密码,如下所示:


The response I get is 401 unauthorized and under "Auth" I get "No WWW-Authenticate Header is present." Then I realize that the API is looking for an SHA1 encoded key. So I fire up an SHA1 generator from a search and get a hash for my username:password and update my Request Header like so:
我得到的响应是 401 未经授权,在“Auth”下我得到“No WWW-Authenticate Header is present”。然后我意识到 API 正在寻找一个 SHA1 编码的密钥。所以我从搜索中启动一个 SHA1 生成器并获取我的用户名:密码的哈希值并更新我的请求标头,如下所示:


This does not work either and I get the same results. Also I obviously need some sort of "shared secret key" to use with the server to decode my username/password.
这也不起作用,我得到了相同的结果。此外,我显然需要某种“共享密钥”与服务器一起使用来解码我的用户名/密码。
So my questions:
所以我的问题:
- How do I get this key from the server (or in this case Virtual IIS running off VS 2012).
- How do I use this to make Authenticated calls in Fiddler using usernames/passwords from an ASP.NET Membership Provider.
- How will I use this in my client application to make the same calls (C# WPF App).
- Is this best practive when combined with SSL on my HTTP calls? If not what is?
- 如何从服务器(或在这种情况下从 VS 2012 运行的虚拟 IIS)获取此密钥。
- 我如何使用它来使用来自 ASP.NET 成员资格提供程序的用户名/密码在 Fiddler 中进行身份验证调用。
- 我将如何在我的客户端应用程序中使用它来进行相同的调用(C# WPF 应用程序)。
- 在我的 HTTP 调用中与 SSL 结合使用时,这是最佳实践吗?如果不是什么是?
Thanks in advance!
提前致谢!
回答by Darin Dimitrov
You could use basic authenticationwith SSL. On the server side we could write a custom delegating handler which will verify the credentials by querying the memebership provider that we registered, and if valid, retrieve the roles and set the current principal:
您可以将基本身份验证与 SSL 结合使用。在服务器端,我们可以编写一个自定义委托处理程序,它将通过查询我们注册的成员资格提供程序来验证凭据,如果有效,则检索角色并设置当前主体:
public class BasicAuthenticationMessageHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var authHeader = request.Headers.Authorization;
if (authHeader == null)
{
return base.SendAsync(request, cancellationToken);
}
if (authHeader.Scheme != "Basic")
{
return base.SendAsync(request, cancellationToken);
}
var encodedUserPass = authHeader.Parameter.Trim();
var userPass = Encoding.ASCII.GetString(Convert.FromBase64String(encodedUserPass));
var parts = userPass.Split(":".ToCharArray());
var username = parts[0];
var password = parts[1];
if (!Membership.ValidateUser(username, password))
{
return base.SendAsync(request, cancellationToken);
}
var identity = new GenericIdentity(username, "Basic");
string[] roles = Roles.Provider.GetRolesForUser(username);
var principal = new GenericPrincipal(identity, roles);
Thread.CurrentPrincipal = principal;
if (HttpContext.Current != null)
{
HttpContext.Current.User = principal;
}
return base.SendAsync(request, cancellationToken);
}
}
We then register this handler in Application_Start:
然后我们在Application_Start以下位置注册此处理程序:
GlobalConfiguration.Configuration.MessageHandlers.Add(
new BasicAuthenticationMessageHandler()
);
Now we could have an Api controller that will be decorated with the [Authorize] attribute to ensure that only authenticated users can access its actions:
现在我们可以有一个 Api 控制器,该控制器将使用 [Authorize] 属性进行修饰,以确保只有经过身份验证的用户才能访问其操作:
[Authorize]
public class ValuesController : ApiController
{
public string Get()
{
return string.Format("Hello {0}", User.Identity.Name);
}
}
Alright, now let's look at a sample client:
好的,现在让我们看一个示例客户端:
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
class Program
{
static void Main()
{
// since for testing purposes I am using IIS Express
// with an invalid SSL certificate I need to desactivate
// the check for this certificate.
ServicePointManager.ServerCertificateValidationCallback +=
(sender, certificate, chain, sslPolicyErrors) => true;
using (var client = new HttpClient())
{
var buffer = Encoding.ASCII.GetBytes("john:secret");
var authHeader = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(buffer));
client.DefaultRequestHeaders.Authorization = authHeader;
var task = client.GetAsync("https://localhost:44300/api/values");
if (task.Result.StatusCode == HttpStatusCode.Unauthorized)
{
Console.WriteLine("wrong credentials");
}
else
{
task.Result.EnsureSuccessStatusCode();
Console.WriteLine(task.Result.Content.ReadAsAsync<string>().Result);
}
}
}
}

