ASP.NET Web API中的用户身份验证

Lui*_*lar 148 asp.net asp.net-web-api

这个话题令我难以置信.我是HTTP应用程序的新手,但需要开发一个消费来自某个地方的JSON数据的iPhone客户端.我选择了MS的Web API,因为它似乎很容易,但是当涉及到对用户进行身份验证时,事情变得非常令人沮丧.

令我惊讶的是,在几个小时的Google搜索后Authorize,我无法找到一个明确的示例,说明如何从登录屏幕向下验证用户,直到使用我的ApiController方法中的属性.

这不是一个问题,而是一个如何准确执行此操作的示例请求.我看过以下几页:

尽管这些解释了如何处理未经授权的请求,但这些请求并没有明确地表明类似于某种类似的LoginController东西,要求用户凭据并验证它们.

有谁愿意写一个很好的简单例子或指出我正确的方向,拜托?

谢谢.

Jup*_*aol 177

令我惊讶的是,在几个小时的Google搜索后,我无法找到一个明确的示例,说明如何从登录屏幕向下验证用户身份以及使用Authorize属性覆盖我的ApiController方法.

那是因为你对这两个概念感到困惑:

  • 身份验证是系统可以安全地识别其用户的机制.身份验证系统提供问题的答案:

    • 谁是用户?
    • 用户真的是他/她代表自己的人吗?
  • 授权是一种机制,通过该机制,系统可以确定特定的已认证用户对系统控制的安全资源应具有的访问级别.例如,可以设计数据库管理系统,以便为某些指定的个人提供从数据库检索信息的能力,但不能改变存储在数据库中的数据,同时使其他人能够更改数据.授权系统提供问题的答案:

    • 用户X是否有权访问资源R?
    • 用户X是否被授权执行操作P?
    • 用户X是否被授权在资源R上执行操作P?

AuthorizeMVC中的属性用于应用访问规则,例如:

 [System.Web.Http.Authorize(Roles = "Admin, Super User")]
 public ActionResult AdministratorsOnly()
 {
     return View();
 }
Run Code Online (Sandbox Code Playgroud)

上述规则将只允许在用户管理员超级用户角色访问的方法

也可以使用该location元素在web.config文件中设置这些规则.例:

  <location path="Home/AdministratorsOnly">
    <system.web>
      <authorization>
        <allow roles="Administrators"/>
        <deny users="*"/>
      </authorization>
    </system.web>
  </location>
Run Code Online (Sandbox Code Playgroud)

但是,在执行这些授权规则之前,必须对当前网站进行身份验证.

尽管这些解释了如何处理未经授权的请求,但这些请求并没有明确地证明像LoginController或类似的东西要求用户凭据并验证它们.

从这里开始,我们可以将问题分成两部分:

  • 在同一Web应用程序中使用Web API服务时对用户进行身份验证

    这将是最简单的方法,因为您将依赖ASP.Net中身份验证

    这是一个简单的例子:

    Web.config文件

    <authentication mode="Forms">
      <forms
        protection="All"
        slidingExpiration="true"
        loginUrl="account/login"
        cookieless="UseCookies"
        enableCrossAppRedirects="false"
        name="cookieName"
      />
    </authentication>
    
    Run Code Online (Sandbox Code Playgroud)

    用户将被重定向到帐户/登录路由,在那里您将呈现自定义控件以请求用户凭据,然后您将使用以下设置身份验证cookie:

        if (ModelState.IsValid)
        {
            if (Membership.ValidateUser(model.UserName, model.Password))
            {
                FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                return RedirectToAction("Index", "Home");
            }
            else
            {
                ModelState.AddModelError("", "The user name or password provided is incorrect.");
            }
        }
    
        // If we got this far, something failed, redisplay form
        return View(model);
    
    Run Code Online (Sandbox Code Playgroud)
  • 跨平台认证

    这种情况是当您只在Web应用程序中公开Web API服务时,您将有另一个客户端使用服务,客户端可能是另一个Web应用程序或任何.Net应用程序(Win Forms,WPF,控制台,Windows服务,等等)

    例如,假设您将从同一网络域(在Intranet中)的另一个Web应用程序中使用Web API服务,在这种情况下,您可以依赖ASP.Net提供的Windows身份验证.

    <authentication mode="Windows" />
    
    Run Code Online (Sandbox Code Playgroud)

    如果您的服务在Internet上公开,那么您需要将经过身份验证的令牌传递给每个Web API服务.

    有关更多信息,请获取以下文章的战利品:

  • 我不明白为什么这个答案会得到这么多的支持.它不是关于ASP.NET Web API,而是关于ASP.NET MVC. (20认同)
  • @Jupaol我想我代表许多Web API开发人员,我不能使用表单身份验证,因为我没有网站,客户端不使用浏览器,我也不能使用集成身份验证,因为用户可以在任何设备上的任何地方(因此Web API),那我该怎么用? (6认同)
  • 这是SO上投票最多的"错误"答案吗?答案实际上并没有谈论web api,它与mvc Web应用程序有很大不同!喜欢@ B413我很震惊! (5认同)
  • 哇!这就是我所说的答案.所以,总结一下.我计划执行以下操作:1.使用Login方法创建一个帐户控制器,该方法通过HTTPS接收用户名和密码,并返回登录结果和令牌.2.客户端存储令牌并将其作为标头(不再使用HTTPS)发送到Web服务器验证的请求中.这是一个好方法吗?然后我最后的疑问是如何控制令牌篡改和过期.这可能吗? (3认同)
  • 我想重申B413的评论,并指出这个问题特别要求Web API (2认同)

Edw*_*rey 15

如果要对用户名和密码进行身份验证并且没有授权cookie,则MVC4 Authorize属性将无法开箱即用.但是,您可以将以下帮助程序方法添加到控制器以接受基本身份验证标头.从控制器的方法开始调用它.

void EnsureAuthenticated(string role)
{
    string[] parts = UTF8Encoding.UTF8.GetString(Convert.FromBase64String(Request.Headers.Authorization.Parameter)).Split(':');
    if (parts.Length != 2 || !Membership.ValidateUser(parts[0], parts[1]))
        throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "No account with that username and password"));
    if (role != null && !Roles.IsUserInRole(parts[0], role))
        throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "An administrator account is required"));
}
Run Code Online (Sandbox Code Playgroud)

从客户端,此助手创建一个HttpClient具有身份验证标头的位置:

static HttpClient CreateBasicAuthenticationHttpClient(string userName, string password)
{
    var client = new HttpClient();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(UTF8Encoding.UTF8.GetBytes(userName + ':' + password)));
    return client;
}
Run Code Online (Sandbox Code Playgroud)


Pro*_*rod 9

我正在研究MVC5/Web API项目,并且需要能够获得Web Api方法的授权.首次加载我的索引视图时,我调用了'token'Web API方法,我认为该方法是自动创建的.

获取令牌的客户端代码(CoffeeScript)是:

getAuthenticationToken = (username, password) ->
    dataToSend = "username=" + username + "&password=" + password
    dataToSend += "&grant_type=password"
    $.post("/token", dataToSend).success saveAccessToken
Run Code Online (Sandbox Code Playgroud)

如果成功,则调用以下内容,以在本地保存身份验证令牌:

saveAccessToken = (response) ->
    window.authenticationToken = response.access_token
Run Code Online (Sandbox Code Playgroud)

然后,如果我需要对具有[Authorize]标记的Web API方法进行Ajax调用,我只需将以下标题添加到我的Ajax调用中:

{ "Authorization": "Bearer " + window.authenticationToken }
Run Code Online (Sandbox Code Playgroud)