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

这个话题让我非常困惑。我是 HTTP 应用程序方面的新手,但是需要开发一个 iPhone 客户端,从某个地方使用 JSON 数据。我选择了 MS 中的 Web API,因为它看起来很简单,但是当涉及到用户身份验证时,事情就变得相当令人沮丧了。

我很惊讶,我没有能够找到一个明确的例子,如何验证一个用户的权利,从登录屏幕到使用 Authorize属性在我的 ApiController方法后,几个小时的谷歌。

这不是一个问题,而是一个如何做到这一点的例子的请求。我看过以下几页:

尽管这些解释了如何处理未经授权的请求,但是它们并没有清楚地展示类似于 LoginController或类似的东西来请求用户凭据并验证它们。

有人愿意写一个简单的例子或者给我指明正确的方向吗?

谢谢。

118833 次浏览

我惊讶地发现,在几个小时的 Google 搜索之后,我还没有找到一个清晰的例子来说明如何从登录屏幕到使用 Authorize 属性通过我的 ApiController 方法来验证用户。

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

  • 认证是系统可以安全地识别其用户的机制,认证系统为这些问题提供了答案:

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

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

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

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

上述规则只允许 在 < em > Admin 和 < em > Super User 角色中的用户访问该方法

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

  <location path="Home/AdministratorsOnly">
<system.web>
<authorization>
<allow roles="Administrators"/>
<deny users="*"/>
</authorization>
</system.web>
</location>

但是,在执行这些授权规则之前,您必须是 认证到当前网站

尽管它们解释了如何处理未经授权的请求,但是它们并没有清楚地展示诸如 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>
    

    用户将被重定向到 帐户/登入名单路由,在那里您将呈现自定义控件来请求用户凭据,然后您将使用以下方法设置身份验证 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);
    
  • Cross - platform authentication

    This case would be when you are only exposing Web API services within the Web application therefore, you would have another client consuming the services, the client could be another Web application or any .Net application (Win Forms, WPF, console, Windows service, etc)

    For example assume that you will be consuming the Web API service from another web application on the same network domain (within an intranet), in this case you could rely on the Windows authentication provided by ASP.Net.

    <authentication mode="Windows" />
    

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

    欲了解更多信息,请浏览以下文章:

如果您希望针对 用户名和密码没有授权 cookie进行身份验证,那么 MVC4 授权属性将无法开箱即用。但是,可以向控制器添加以下帮助器方法以接受基本身份验证标头。从控制器的方法开始调用它。

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"));
}

在客户端,这个 helper 创建一个具有身份验证头的 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;
}

我正在从事一个 MVC5/Web API 项目,需要能够获得 Web API 方法的授权。当我的索引视图第一次加载时,我调用了我认为是自动创建的“令牌”Web API 方法。

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

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

如果成功,将调用以下命令,从而在本地保存身份验证令牌:

saveAccessToken = (response) ->
window.authenticationToken = response.access_token

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

{ "Authorization": "Bearer " + window.authenticationToken }