验证是识别一个用户身份的过程。验证是决定一个用户是否有权访问特定资源的过程。在ASP.NET Core中,验证是通过 IAuthenticationService 来处理的,其被验证中间件所使用。验证服务使用已经注册过的验证处理器来完成验证相关的动作。验证相关的动作举例如下:
- 验证一个用户。
- 当未验证用户试图访问受限资源时候进行响应。
已注册的验证处理器以及其配置选项被成为“模式”(schemes)。
验证模式通过在Startup.ConfigureServices中注册验证服务来指定。
- 通过在调用services.AddAuthentication之后调用一个特定模式的扩展方法(举个例子,
AddJwtBearer
或者AddCookie
)。这些扩展方法通过调用 AuthenticationBuilder.AddScheme 来以必要的配置注册模式。 - 在很少的情况下,通过直接调用AuthenticationBuilder.AddScheme 来添加模式。
举个例子,如下代码为 Cookies 以及 JWT 验证模式注册了验证服务以及处理器:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => Configuration.Bind("JwtSettings", options)) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => Configuration.Bind("CookieSettings", options));
当没有特定的模式被请求时,AddAuthentication
的参数JwtBearerDefaults.AuthenticationScheme 是默认使用的模式名字。
如果我们定义了多个模式,授权策略(或者说授权特性)可以指定它们所依赖的验证模式来对用户进行验证。在如上的示例中,cookie验证模式可以通过指定其名称来使用(默认是CookieAuthenticationDefaults.AuthenticationScheme,然而当我们调用AddCookie时候可以提供一个不同的名称)。
在某些情形下,对AddAuthentication的调用会被其他扩展方法自动触发。举个例子,当使用ASP.NET Core Identity 时,AddAuthentication在会在内部被调用。
通过在Startup.Configure中,调用 IApplicationBuilder上的 UseAuthentication 扩展方法,我们会添加一个验证中间件。调用UseAuthentication会注册一个使用之前注册过的验证模式的中间件。在任何依赖已验证用户的中间件之前调用UseAuthentication。当我们还使用终结点路由时,对UseAuthentication的调用必须按如下策略:
- 在UseRouting之后,这样路由信息对于验证决策来说便是可用的。
- 在UseEndpoints之前,这样用户在访问终结点前便已经被验证。
验证基本概念
验证模式
一个验证模式其实是一个名称,其与如下所列举的组件相关:
- 一个验证处理器。
- 用来配置处理器的特定实例的选项。
对于涉及到相关处理器的验证,挑战和禁止行为,模式是一种有用的机制。举个例子,一个授权策略可以使用一个模式名字来指定哪一个验证模式应该被用来验证用户。当我们配置验证时,通常 我们会指定默认的验证模式。除非一个资源请求了特定的模式,否则会使用默认的验证模式。
也有可能:
- 指定不同的默认模式用于验证,挑战,以及禁止动作。
- 使用policy schemes 将多个模式组合为一个。
验证处理器
一个验证处理器:
- 是一个实现了模式行为的类型。
- 继承于 IAuthenticationHandler 或 AuthenticationHandler<TOptions>。
- 首要职责是验证用户。
基于验证模式的配置以及后续的请求上下文,验证上下文:
- 负责构造AuthenticationTicket 对象,如果验证成功的话,其代表了用户的身份。
- 如果验证失败的话,便返回“无结果”或者“失败”。
- 当用户试图访问如下资源时,其具有用于挑战或者禁止的方法。
- 它们为被授权访问(forbid)。
- 当用户未验证通过时候(challenge)。
验证
一个验证模式的验证动作负责基于请求上下文来构建用户的身份。它返回一个 AuthenticateResult,其指示了验证是否成功,以及,如果成功了的话,其也会在一个验证票据中指示用户的身份。请查看AuthenticateAsync。验证示例包括:
- 一个Cookie验证模式从Cookie中构建了用户身份。
- 一个JWT信使模式反序列化并验证一个JWT信使凭证用来构建用户的身份。
质询
当一个未验证用户请求一个需要验证的终结点时,验证 挑战(challenge)便会被激活。一个验证询问被发出,举个例子,当一个匿名用户请求一个受限的资源或者点击登录连接。而授权会激活一个使用了特定验证模式的询问,如果没有指定模式,那么默认的模式便会被使用。可以查看ChallengeAsync。验证质询示例包括:
- 一个Cookie 验证模式将用户重定向至登录页面。
- 一个JWT信使模式会返回一个带有www-authenticate: bearer 头信息的401结果。
一个质询动作应该让用户知道什么验证机制要使用以用来访问所请求的资源。
禁止
当一个已验证的用户企图访问其不被允许访问的资源时,授权会调用一个验证模式的禁止动作。更多信息请查看ForbidAsync。验证禁止示例包含如下:
- Cookie 验证模式将用户重定向到一个页面,那个页面指示了访问被禁止。
- JWT信使模式返回一个403。
- 用户自定义模式会重定向到一个页面,在那里用户可以请求对资源的访问权限。
禁止动作可以使用户知道:
- 他们已经通过验证。
- 他们不被允许访问所请求的资源。
查看如下连接以了解质询和禁止的不同:
- Challenge and forbid with an operational resource handler.
- Differences between challenge and forbid.
对于每个租户的验证提供器
ASP.NET Core 框架没有为多租户验证提供内置的解决方案。当然用户可以使用内置的特性自己写一个,我们建议客户深入研究 Orchard Core 以获取相关解决方案。
Orchard Core 是:
- 用ASP.NET Core构建的开源的,多租户的模块化应用程序框架。
- 建立在那个应用程序框架上的内容管理系统。
请查看Orchard Core 的源代码,可以看到每个租户的验证提供器的示例。
额外资源