如何通过远程WebApi2应用程序将此MVC5客户端登录?

时间:2014-04-09 14:44:13

标签: asp.net-mvc-5 identity setcookie owin asp.net-web-api2

我正在分两部分创建一个应用程序。在一台服务器上是使用Owin的.net Webapi2。在另一台服务器上是一个MVC5网站,目前没有登录,它将充当api的前端。这也是一个很好的卖点,表明应用程序本身就是客户可以开发的一个例子,因为它依赖于相同的api。我把用户身份验证的东西放在api中,因为我需要第三方才能使用api开发自己的前端应用程序。

我想要完成的事情(理论上) 我需要让用户在前端提交他们的登录信息,它将通过resourceownergrant类型对他们进行身份验证,并收到允许前端创建包含accesstoken和identityuser / roles的cookie的结果。只要这个cookie存在,mvc app就会使用accesstoken调用api。 MVC应用程序和API都可以使用[Authorize]属性。

到目前为止我有什么 我有api up and working,我可以发布“grant_type = password& username = testuser& password = password123”,我在json中收到类似的内容

{
  "access_token":"-longasstokenhere-",
  "token_type":"bearer",
  "expires_in":1209599,
  "userName":"testuser",
  ".issued":"Thu, 03 Apr 2014 16:21:06 GMT",
  ".expires":"Thu, 17 Apr 2014 16:21:06 GMT"
}

web api的回复也有一个标题

set-cookie: -Long-assserializedcookiestuffhere-

我的问题是如何连接我的mvc应用。

在我的mvc5应用程序中,我在configureauth中使用此设置为owin创建了一个启动

app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                CookieName = "MyCookie",
                LoginPath = new PathString("/Account/Login")
            });

我在测试页面上设置了[Authorize]属性,当我访问时,它正确地将我重定向到登录页面。我缺少的是如何制作它,以便点击登录使网站回复到api并创建一个Owin Cookie,网站将使用该Cookie允许用户通过[authorize] attibute。我还希望它包含identityuser,因此Web应用程序将自动拥有用户信息,而无需在每次调用时回发到api。我不知道我是否能以某种方式从返回结果中获取cookie。

如果他们有更好的方式,我愿意接受建议。

Heeelp!?

1 个答案:

答案 0 :(得分:2)

我有完全相同的要求。我试图让MVC5 CookieAuthentication工作,但它不会让我使用自己的cookie值。但是,您的WebAPI不应返回set-cookie。 WebAPI应该是RESTful,并要求客户端在每个请求上传递一个持有者令牌。

所以,这是我的解决方案。用户名和密码将发送到外部API,后者返回JSON Web令牌。 API中的令牌存储在cookie中。您可以在JavaScript或MVC帐户控制器中执行此操作。该cookie由MVC应用程序检查,如果存在,则cookie表示用户也登录到MVC应用程序。

在JavaScript中,您从cookie中提取该令牌,并将其添加到Authorization标头中作为Bearer令牌的API的所有请求中。此外,MVC应用程序可以使用cookie(令牌)的值来访问所有用户的声明。要注销,只需使cookie过期。

首先,将应用程序连接到我们的自定义提供程序

以使用Bearer令牌
// Api controllers with an [Authorize] attribute will be validated with JWT
app.UseJwtBearerAuthentication(
    new JwtBearerAuthenticationOptions
    {
        AllowedAudiences = audienceId.ToArray(),
        IssuerSecurityTokenProviders = providers.ToArray(),
        Provider = new CookieOAuthBearerProvider("MyCookieName")
        {
            LoginPath = new PathString("/Account/Login")
        }
    }
);

现在,我不得不使用自定义提供程序,因为Bearer令牌存储在cookie中,而不是标准头中。我还需要重定向到登录页面,而不是简单地发布401。

public class CookieOAuthBearerProvider : IOAuthBearerAuthenticationProvider
{
    public PathString LoginPath {get; set;}

    public string CookieName { get; set; }

    public CookieOAuthBearerProvider(string cookieName)
    {
        if(string.IsNullOrWhiteSpace(cookieName)) {
            throw new ArgumentNullException("cookieName");
        }
        else {
            this.CookieName = cookieName;
        };
    }

    public Task ApplyChallenge(OAuthChallengeContext context)
    {
        if (this.LoginPath.HasValue)
        {
            context.Response.Redirect(this.LoginPath.Value);
        }
        return Task.FromResult<object>(null);
    }

    public Task RequestToken(OAuthRequestTokenContext context)
    {
        string token = context.Request.Cookies[this.CookieName];
        if (!string.IsNullOrEmpty(token))
        {
            context.Token = token;
        }
        return Task.FromResult<object>(null);
    }

    public Task ValidateIdentity(OAuthValidateIdentityContext context)
    {
        // prove that the cookie token matches this site using context.Ticket.Identity
        return Task.FromResult<object>(null);
    }
}

然后,在您的MVC应用程序中的任何其他位置,只需说出以下内容即可获得声明:

ClaimsPrincipal.Current