Asp.net mvc 4 跨web角色和客户端应用程序共享ASP.NET simplemembership身份验证

Asp.net mvc 4 跨web角色和客户端应用程序共享ASP.NET simplemembership身份验证,asp.net-mvc-4,authentication,azure,simplemembership,Asp.net Mvc 4,Authentication,Azure,Simplemembership,我已经试着弄明白这一点有一段时间了,阅读了大量的博客、MSDN文档、示例代码和其他stackoverflow问题,但还没有让它起作用 以下是我的设想: 我正在使用Windows Azure托管两个web角色。一个是我的MVC4 web API,另一个是我的MVC4 web应用程序,它使用web API。我还有许多使用.NET的客户端应用程序可以访问web API 因此,我的主要组成部分是: Web API 网络应用 .NET客户端 我想使用Web应用中“托管”的表单身份验证。我正在使用内置的

我已经试着弄明白这一点有一段时间了,阅读了大量的博客、MSDN文档、示例代码和其他stackoverflow问题,但还没有让它起作用

以下是我的设想:

我正在使用Windows Azure托管两个web角色。一个是我的MVC4 web API,另一个是我的MVC4 web应用程序,它使用web API。我还有许多使用.NET的客户端应用程序可以访问web API

因此,我的主要组成部分是:

  • Web API
  • 网络应用
  • .NET客户端
我想使用Web应用中“托管”的表单身份验证。我正在使用内置的simplemembership身份验证机制,它非常有效。我可以在Web应用程序中创建和登录帐户

现在,我还想使用这些相同的帐户来验证Web API,包括Web应用程序和任何.NET客户端应用程序

我已经阅读了许多方法来实现这一点,最简单的方法似乎是在Web API上使用基本身份验证。目前我正在使用此代码,因为它似乎解决了我的确切问题:

我不能让它工作。我成功登录到我的Web应用程序(127.0.0.1:81),当我尝试调用需要身份验证的Web API(例如127.0.0.1:8081/API/values)时,调用失败,出现401(未经授权)响应。在单步执行代码时,WebSecurity.IsAuthenticated返回false。WebSecurity.Initialized返回true

我已经实现了这段代码,正在尝试使用以下代码从我的Web应用程序(登录后)调用我的Web API:

using ( var handler = new HttpClientHandler() )
{
    var cookie = FormsAuthentication.GetAuthCookie( User.Identity.Name, false );
    handler.CookieContainer.Add( new Cookie( cookie.Name, cookie.Value, cookie.Path, cookie.Domain ) );

    using ( var client = new HttpClient() )
    {
        //client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
        //  "Basic",
        //  Convert.ToBase64String( System.Text.ASCIIEncoding.ASCII.GetBytes(
        //  string.Format( "{0}:{1}", User.Identity.Name, "123456" ) ) ) );
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
            "Cookie",
            Convert.ToBase64String( System.Text.ASCIIEncoding.ASCII.GetBytes( User.Identity.Name ) ) );

        string response = await client.GetStringAsync( "http://127.0.0.1:8080/api/values" );

        ViewBag.Values = response;
    }
}
如您所见,我尝试了使用cookie和用户名/密码。很明显,我想使用cookie,但在这一点上,如果任何东西都有效,这将是一个很好的步骤

我的Web API中的ValuesController已正确修饰:

// GET api/values
[BasicAuthorize]
public IEnumerable<string> Get()
{
    return new string[] { "value1", "value2" };
}
这成功了,WebSecurity后来说它已经初始化了,所以我想这部分工作正常

根据需要,我的配置文件具有匹配的身份验证设置

以下是API配置:

<authentication mode="Forms">
<forms protection="All" path="/" domain="127.0.0.1" enableCrossAppRedirects="true" timeout="2880" />
</authentication>
<machineKey decryption="AES" decryptionKey="***" validation="SHA1" validationKey="***" />
因为它比我需要的功能多得多,而且似乎没有必要


我错过了什么?

嗯,这太尴尬了。我的主要问题是一个简单的代码错误。这是正确的代码。告诉我你能在我的问题中发现代码的不同

using ( var handler = new HttpClientHandler() )
{
    var cookie = FormsAuthentication.GetAuthCookie( User.Identity.Name, false );
    handler.CookieContainer.Add( new Cookie( cookie.Name, cookie.Value, cookie.Path, cookie.Domain ) );

    using ( var client = new HttpClient( handler ) )
...
}
一旦修复了,我就开始出现
403禁止的
错误。因此,我跟踪了这一点,并对
BasicAuthorizeAttribute
类做了一个小的更改,以便在未指定角色时正确支持
[BasicAuthorize]
属性

以下是修改后的代码:

private bool isAuthorized( string username )
{
    // if there are no roles, we're good!
    if ( this.Roles == "" )
        return true;

    bool authorized = false;

    var roles = (SimpleRoleProvider)System.Web.Security.Roles.Provider;
    authorized = roles.IsUserInRole( username, this.Roles );
    return authorized;
}
通过传递表单cookie来更改基本身份验证

现在让非web客户端应用程序正常工作,然后按照建议重构web应用程序


我希望这对将来的人有帮助

这太尴尬了。我的主要问题是一个简单的代码错误。这是正确的代码。告诉我你能在我的问题中发现代码的不同

using ( var handler = new HttpClientHandler() )
{
    var cookie = FormsAuthentication.GetAuthCookie( User.Identity.Name, false );
    handler.CookieContainer.Add( new Cookie( cookie.Name, cookie.Value, cookie.Path, cookie.Domain ) );

    using ( var client = new HttpClient( handler ) )
...
}
一旦修复了,我就开始出现
403禁止的
错误。因此,我跟踪了这一点,并对
BasicAuthorizeAttribute
类做了一个小的更改,以便在未指定角色时正确支持
[BasicAuthorize]
属性

以下是修改后的代码:

private bool isAuthorized( string username )
{
    // if there are no roles, we're good!
    if ( this.Roles == "" )
        return true;

    bool authorized = false;

    var roles = (SimpleRoleProvider)System.Web.Security.Roles.Provider;
    authorized = roles.IsUserInRole( username, this.Roles );
    return authorized;
}
通过传递表单cookie来更改基本身份验证

现在让非web客户端应用程序正常工作,然后按照建议重构web应用程序


我希望这对将来的人有帮助

我已经读了好几遍这个问题,但我仍然不确定问题是什么,或者失败发生在哪里。当您尝试使用服务器端代码从Web应用程序调用Web API时是否失败?失败到底是什么?您是否收到任何错误或是意外行为?对于初学者,我不建议从服务器端代码调用Web API。这是不必要的网络流量。看看这个建议的架构[这将允许您直接访问您的应用程序域。您仍然可以使用自定义ClaimsAuthorizationManager处理授权,而无需Web API调用。很抱歉,没有将我的特定错误放在其中。我花了很多时间试图输入所有详细信息,但错过了最重要的一个。授权确实失败当从服务器端代码调用Web API时。@KevinJunghans我很欣赏关于不必要的网络流量和链接的评论。这样做可能有意义。虽然我现在想让它工作,因为我还需要从.NET客户端应用程序验证和调用此Web API。我正在从首先在我的web应用中,因为它看起来很方便。由于您是从服务器端代码进行web API调用,因此必须在http请求中包含cookie。由于您不知道用户的密码,因此使用基本身份验证将不起作用。您使用的自定义授权属性同时执行身份验证和作者身份验证仅对应用程序域进行方法调用会带来很大的开销。同样,我建议您直接调用应用程序域(而不是通过Web API)并使用自定义ClaimsAuthorizationManager仅执行授权。用户已通过身份验证。我已多次阅读此问题,但仍不确定问题是什么,或故障发生在何处。当您尝试使用服务器端代码从Web应用程序调用Web API时是否失败?具体是什么失败?您是否收到任何错误或是意外行为?对于初学者,我不建议从服务器端代码调用Web API。这是不必要的网络流量。请查看此建议的体系结构[它将允许您直接访问应用程序域。您仍然可以在