使用成员资格提供程序的ASP.NET MVC 4 Web API身份验证

INN*_*VTV 43 asp.net-mvc forms-authentication asp.net-membership fiddler asp.net-web-api

我有一个使用Web API的ASP.NET MVC 4项目.在控制器上,我已使用[Authorize]属性将类设置为需要授权.对于身份验证我使用ASP.NET成员资格提供程序并将我的Web.Config设置为使用"表单"身份验证.这是我被困的地方:

一切都工作得很好,直到我完成测试API的步骤,我想用[Authorize]属性保护控制器,这样我就可以开始对我的Membership Provider中的用户进行身份验证.所以我启动Fiddler并进行相同的调用,添加Authorization:Basic属性以及来自我的会员提供者的用户名:密码,如下所示:

在此输入图像描述

我得到的响应是未经授权的401,在"Auth"下,我得到"没有WWW-Authenticate Header".然后我意识到API正在寻找SHA1编码密钥.所以我从搜索中启动一个SHA1生成器并获取我的用户名的密码:password并更新我的Request Header,如下所示:

在此输入图像描述

这也不起作用,我得到相同的结果.此外,我显然需要某种"共享密​​钥"与服务器一起使用来解码我的用户名/密码.

所以我的问题:

  1. 如何从服务器获取此密钥(或者在这种情况下,虚拟IIS运行VS 2012).
  2. 如何使用它来使用ASP.NET成员资格提供程序中的用户名/密码在Fiddler中进行Authenticated调用.
  3. 如何在我的客户端应用程序中使用它来进行相同的调用(C#WPF应用程序).
  4. 在我的HTTP调用中与SSL结合使用时,这是最好的吗?如果不是什么?

提前致谢!

Dar*_*rov 68

您可以使用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);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我们将此处理程序注册到Application_Start:

GlobalConfiguration.Configuration.MessageHandlers.Add(
    new BasicAuthenticationMessageHandler()
);
Run Code Online (Sandbox Code Playgroud)

现在我们可以使用[Authorize]属性修饰Api控制器,以确保只有经过身份验证的用户才能访问其操作:

[Authorize]
public class ValuesController : ApiController
{
    public string Get()
    {
        return string.Format("Hello {0}", User.Identity.Name);
    }
}
Run Code Online (Sandbox Code Playgroud)

好的,现在让我们来看一个示例客户端:

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);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 嗨,方法:“ Membership.ValidateUser()”返回false。我假设我需要设置成员资格默认数据库连接?如果是这样,我该在哪里做? (2认同)