MVC .NET cookie身份验证系统使用令牌身份验证访问Web Api

时间:2014-03-21 19:59:08

标签: asp.net-mvc asp.net-web-api owin bearer-token

我有一个拥有Ownin cookie身份验证的Mvc 5客户端。 我还有一个受Owin Bearer令牌保护的Web Api(我使用了VS2013 Web Api模板,创建了Token端点)

好的,现在我的Mvc 5客户端需要使用我的WebApi。 我创建了一个获取持票人令牌的方法:

internal async Task<string> GetBearerToken(string siteUrl, string Username, string Password)
{
     HttpClient client = new HttpClient();

     client.BaseAddress = new Uri(siteUrl);
     client.DefaultRequestHeaders.Accept.Clear();

     HttpContent requestContent = new StringContent("grant_type=password&username=" + Username + "&password=" + Password, Encoding.UTF8, "application/x-www-form-urlencoded");

     HttpResponseMessage responseMessage = await client.PostAsync("Token", requestContent);

     if (responseMessage.IsSuccessStatusCode)
     {
         TokenResponseModel response = await responseMessage.Content.ReadAsAsync<TokenResponseModel>();
         return response.AccessToken;
     }

     return "";
}

在我的Mvc行动中,我打电话给:

public async Task<ActionResult> Index()
{
     var token = await GetBearerToken("http://localhost:6144/", "teste", "123456");

     using (var client = new HttpClient())
     {
         client.DefaultRequestHeaders.Add("Authorization", "Bearer "+ token);

         var response = await client.GetAsync("http://localhost:6144/api/values");

         if (response.IsSuccessStatusCode)
         {
             var data = response.Content.ReadAsAsync<IEnumerable<string>>();

             return Json(data.Result, JsonRequestBehavior.AllowGet);
         }
     }   
}

一切正常......但我需要在所有行动中使用Web Api ...... 那么我如何保留该令牌(尽管每个请求都获得一个新令牌)以及如何验证它是否已过期...是否可以将其与身份验证cookie保持在一起? 处理这种情况的最佳实践是什么?

由于

3 个答案:

答案 0 :(得分:14)

如果我说得对,你的MVC 5客户端应用程序正在访问不同应用程序的WebAPI。 MVC 5客户端使用cookie来验证用户。要访问WebAPI,您将从/ Token端点获取Bearer tokeen并将其发送到Authorization标头。

您不会从客户端Javascript代码调用WebAPI,只需在MVC5应用程序的服务器上运行的MVC Actions中调用它。

在每次服务呼叫听起来错误之前获取新令牌。这意味着每次往返2次。这无法表现出来。

如果我做对了,你可以:

  1. 将令牌存储在Session对象中。只要您的MVC应用程序的用户通过身份验证并且他的会话处于活动状态,您就会拥有相同的令牌。 如果它过期,您将从WebAPI获得401未经授权的访问。 要保持MVC操作单元可测试,您可以将会话访问包装到您注入Action(依赖注入)的服务中。

  2. 您可以将令牌存储在类似于已存在的身份验证cookie的cookie中。这样,您就不需要在服务器端使用Session。在这里,我将再次封装访问权限,以便在您所有操作都使用的服务中从Cookie中获取令牌。

  3. 我会使用Session存储。简单。直接前进。 但也许我错过了一些东西

    希望这会对你有所帮助。 反馈意见: - )

答案 1 :(得分:4)

不记名令牌不是授权您的Web应用程序的好方法。如果您存储服务&#39; cookie中的令牌将可供应用程序的客户端使用,因此服务层将容易受到应用程序客户端的攻击。唯一的解决方案似乎是在会话中保留令牌,但您将失去应用程序的无状态特性。

Here is describied what/how bearer token should be used:&#34;承载令牌只是客户端在每次API调用时必须出现的一个大的随机字符串。承载令牌很简单,因为两端都不需要特殊的签名或验证码。客户端负责将令牌存储在安全的地方并随每次请求发送。服务器负责在数据库中查找令牌并确保它是有效的 - 这就是它。&#34;。

以下是在single page application中使用承载令牌的好例子,其中客户端直接与服务进行通信。

无论如何,我建议您使用HMAC authentication,BCrypt或ClientCertificates。甚至amazon使用它来验证REST请求。

答案 2 :(得分:2)

如果要在所有操作中管理令牌,则应更改代码以使用自定义授权过滤器。该过滤器可以添加到所有Web API请求,控制器的所有操作或单个操作。为此,从AuthorizeAttribute派生并从过滤器发出GetBearerToken调用。将令牌粘贴到HTTP上下文中以供请求处理期间使用。您可以使用工厂生成它们并添加适当的标记以进行身份​​验证,而不是直接调用创建HttpClient实例。

至于确定令牌是否已过期,您可以添加一个额外的过滤器,用于检查返回的特定错误,或者替代在授权过滤器中检查。我不知道您的所有要求,因此很难确定那里的适当解决方案。