首页 文章

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

提问于
浏览
16

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

好的,现在我的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 回答

  • 2

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

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

    在每次服务呼叫之前获取新令牌听起来是错误的 . 这意味着每次往返2次 . 这不可能是高效的 .

    如果我做对了,你可以:

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

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

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

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

  • 4

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

    Here is describied what/how bearer token should be used: "A bearer token is just a big, random string that a client must present on every API call. Bearer tokens are simple because there's no special signature or validation code required on either end. The client is responsible for storing the token in a safe place and sending it with every request. The server is responsible for looking up the token in a database and making sure it's a valid one -- that's it." .

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

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

  • 14

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

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

相关问题