使用 cookie 身份验证而无需 ASP.NET Core 标识Use cookie authentication without ASP.NET Core Identity

作者: Rick AndersonLuke LathamBy Rick Anderson and Luke Latham

ASP.NET Core 标识是完整、功能齐全的身份验证提供程序,用于创建和维护登录名。ASP.NET Core Identity is a complete, full-featured authentication provider for creating and maintaining logins. 但是,可以使用不带 ASP.NET Core 标识的基于 cookie 的身份验证提供程序。However, a cookie-based authentication provider without ASP.NET Core Identity can be used. 有关更多信息,请参见ASP.NET Core 上的标识简介For more information, see ASP.NET Core 上的标识简介.

查看或下载示例代码如何下载View or download sample code (how to download)

出于演示目的,在示例应用程序中,假设用户(Maria Rodriguez)的用户帐户已硬编码到应用中。For demonstration purposes in the sample app, the user account for the hypothetical user, Maria Rodriguez, is hardcoded into the app. 使用电子邮件地址 maria.rodriguez@contoso.com 和任何密码来登录用户。Use the Email address maria.rodriguez@contoso.com and any password to sign in the user. 用户在页面/帐户/登录名. .cs文件的 AuthenticateUser 方法中进行身份验证。The user is authenticated in the AuthenticateUser method in the Pages/Account/Login.cshtml.cs file. 在实际的示例中,用户将对数据库进行身份验证。In a real-world example, the user would be authenticated against a database.

配置Configuration

如果应用程序不使用AspNetCore 元包,请在 AspNetCore 包的项目文件中创建包引用(& c )。If the app doesn't use the Microsoft.AspNetCore.App metapackage, create a package reference in the project file for the Microsoft.AspNetCore.Authentication.Cookies package.

Startup.ConfigureServices 方法中,创建具有 AddAuthenticationAddCookie 方法的身份验证中间件服务:In the Startup.ConfigureServices method, create the Authentication Middleware services with the AddAuthentication and AddCookie methods:

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie();

AuthenticationScheme 传递到 AddAuthentication 设置应用程序的默认身份验证方案。AuthenticationScheme passed to AddAuthentication sets the default authentication scheme for the app. 如果有多个 cookie 身份验证实例,并且你想要使用特定方案进行授权AuthenticationScheme 会很有用。AuthenticationScheme is useful when there are multiple instances of cookie authentication and you want to authorize with a specific scheme. AuthenticationScheme 设置为CookieAuthenticationDefaults。 AuthenticationScheme为方案提供值 "cookie"。Setting the AuthenticationScheme to CookieAuthenticationDefaults.AuthenticationScheme provides a value of "Cookies" for the scheme. 可以提供任何用于区分方案的字符串值。You can supply any string value that distinguishes the scheme.

应用的身份验证方案不同于应用的 cookie 身份验证方案。The app's authentication scheme is different from the app's cookie authentication scheme. 如果未向 AddCookie提供 cookie 身份验证方案,则使用 CookieAuthenticationDefaults.AuthenticationScheme ("Cookie")。When a cookie authentication scheme isn't provided to AddCookie, it uses CookieAuthenticationDefaults.AuthenticationScheme ("Cookies").

默认情况下,身份验证 cookie 的 IsEssential 属性设置为 trueThe authentication cookie's IsEssential property is set to true by default. 当站点访问者未同意数据收集时,允许使用身份验证 cookie。Authentication cookies are allowed when a site visitor hasn't consented to data collection. 有关更多信息,请参见在 ASP.NET Core中的常规数据保护法规 (GDPR) 支持For more information, see 在 ASP.NET Core中的常规数据保护法规 (GDPR) 支持.

Startup.Configure中,调用 UseAuthenticationUseAuthorization 设置 HttpContext.User 属性,并为请求运行授权中间件。In Startup.Configure, call UseAuthentication and UseAuthorization to set the HttpContext.User property and run Authorization Middleware for requests. 调用 UseEndpoints之前调用 UseAuthenticationUseAuthorization 方法:Call the UseAuthentication and UseAuthorization methods before calling UseEndpoints:

app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
    endpoints.MapRazorPages();
});

CookieAuthenticationOptions 类用于配置身份验证提供程序选项。The CookieAuthenticationOptions class is used to configure the authentication provider options.

在服务配置中设置 CookieAuthenticationOptions,以便在 Startup.ConfigureServices 方法中进行身份验证:Set CookieAuthenticationOptions in the service configuration for authentication in the Startup.ConfigureServices method:

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options =>
    {
        ...
    });

Cookie 策略中间件支持 cookie 策略功能。Cookie Policy Middleware enables cookie policy capabilities. 将中间件添加到应用处理管道是区分顺序的—它仅影响在管道中注册的下游组件。Adding the middleware to the app processing pipeline is order sensitive—it only affects downstream components registered in the pipeline.

app.UseCookiePolicy(cookiePolicyOptions);

使用提供给 Cookie 策略中间件的 CookiePolicyOptions 来控制 cookie 处理的全局特性并在附加或删除 cookie 时挂钩到 cookie 处理处理程序。Use CookiePolicyOptions provided to the Cookie Policy Middleware to control global characteristics of cookie processing and hook into cookie processing handlers when cookies are appended or deleted.

默认 MinimumSameSitePolicy 值为 SameSiteMode.Lax 以允许 OAuth2 authentication。The default MinimumSameSitePolicy value is SameSiteMode.Lax to permit OAuth2 authentication. 若要严格实施 SameSiteMode.Strict的同一站点策略,请设置 MinimumSameSitePolicyTo strictly enforce a same-site policy of SameSiteMode.Strict, set the MinimumSameSitePolicy. 尽管此设置会中断 OAuth2 和其他跨源身份验证方案,但它为不依赖于跨源请求处理的其他类型的应用提升了 cookie 安全级别。Although this setting breaks OAuth2 and other cross-origin authentication schemes, it elevates the level of cookie security for other types of apps that don't rely on cross-origin request processing.

var cookiePolicyOptions = new CookiePolicyOptions
{
    MinimumSameSitePolicy = SameSiteMode.Strict,
};

MinimumSameSitePolicy 的 Cookie 策略中间件设置会根据下面的矩阵影响 CookieAuthenticationOptions 设置中 Cookie.SameSite 的设置。The Cookie Policy Middleware setting for MinimumSameSitePolicy can affect the setting of Cookie.SameSite in CookieAuthenticationOptions settings according to the matrix below.

MinimumSameSitePolicyMinimumSameSitePolicy SameSiteCookie.SameSite 生成的 SameSite 设置Resultant Cookie.SameSite setting
SameSiteModeSameSiteMode.None SameSiteModeSameSiteMode.None
SameSiteModeSameSiteMode.Lax
SameSiteModeSameSiteMode.Strict
SameSiteModeSameSiteMode.None
SameSiteModeSameSiteMode.Lax
SameSiteModeSameSiteMode.Strict
SameSiteModeSameSiteMode.Lax SameSiteModeSameSiteMode.None
SameSiteModeSameSiteMode.Lax
SameSiteModeSameSiteMode.Strict
SameSiteModeSameSiteMode.Lax
SameSiteModeSameSiteMode.Lax
SameSiteModeSameSiteMode.Strict
SameSiteModeSameSiteMode.Strict SameSiteModeSameSiteMode.None
SameSiteModeSameSiteMode.Lax
SameSiteModeSameSiteMode.Strict
SameSiteModeSameSiteMode.Strict
SameSiteModeSameSiteMode.Strict
SameSiteModeSameSiteMode.Strict

若要创建保存用户信息的 cookie,请构造一个 ClaimsPrincipalTo create a cookie holding user information, construct a ClaimsPrincipal. 将对用户信息进行序列化并将其存储在 cookie 中。The user information is serialized and stored in the cookie.

使用任何所需的 Claim创建 ClaimsIdentity,并调用 SignInAsync 以登录用户:Create a ClaimsIdentity with any required Claims and call SignInAsync to sign in the user:

var claims = new List<Claim>
{
    new Claim(ClaimTypes.Name, user.Email),
    new Claim("FullName", user.FullName),
    new Claim(ClaimTypes.Role, "Administrator"),
};

var claimsIdentity = new ClaimsIdentity(
    claims, CookieAuthenticationDefaults.AuthenticationScheme);

var authProperties = new AuthenticationProperties
{
    //AllowRefresh = <bool>,
    // Refreshing the authentication session should be allowed.

    //ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(10),
    // The time at which the authentication ticket expires. A 
    // value set here overrides the ExpireTimeSpan option of 
    // CookieAuthenticationOptions set with AddCookie.

    //IsPersistent = true,
    // Whether the authentication session is persisted across 
    // multiple requests. When used with cookies, controls
    // whether the cookie's lifetime is absolute (matching the
    // lifetime of the authentication ticket) or session-based.

    //IssuedUtc = <DateTimeOffset>,
    // The time at which the authentication ticket was issued.

    //RedirectUri = <string>
    // The full path or absolute URI to be used as an http 
    // redirect response value.
};

await HttpContext.SignInAsync(
    CookieAuthenticationDefaults.AuthenticationScheme, 
    new ClaimsPrincipal(claimsIdentity), 
    authProperties);

SignInAsync 创建加密的 cookie,并将其添加到当前响应中。SignInAsync creates an encrypted cookie and adds it to the current response. 如果未指定 AuthenticationScheme,则使用默认方案。If AuthenticationScheme isn't specified, the default scheme is used.

ASP.NET Core 的数据保护系统用于加密。ASP.NET Core's Data Protection system is used for encryption. 对于托管在多台计算机上的应用程序、跨应用程序或使用 web 场进行负载平衡,请将数据保护配置为使用相同的密钥环和应用程序标识符。For an app hosted on multiple machines, load balancing across apps, or using a web farm, configure data protection to use the same key ring and app identifier.

注销Sign out

若要注销当前用户并删除其 cookie,请调用 SignOutAsyncTo sign out the current user and delete their cookie, call SignOutAsync:

await HttpContext.SignOutAsync(
    CookieAuthenticationDefaults.AuthenticationScheme);

如果 CookieAuthenticationDefaults.AuthenticationScheme (或 "Cookie")不用作方案(例如 "ContosoCookie"),请提供配置身份验证提供程序时所使用的方案。If CookieAuthenticationDefaults.AuthenticationScheme (or "Cookies") isn't used as the scheme (for example, "ContosoCookie"), supply the scheme used when configuring the authentication provider. 否则,将使用默认方案。Otherwise, the default scheme is used.

对后端更改作出反应React to back-end changes

创建 cookie 后,cookie 就是单一标识源。Once a cookie is created, the cookie is the single source of identity. 如果在后端系统中禁用用户帐户:If a user account is disabled in back-end systems:

  • 应用的 cookie 身份验证系统将继续根据身份验证 cookie 处理请求。The app's cookie authentication system continues to process requests based on the authentication cookie.
  • 只要身份验证 cookie 有效,用户就会保持登录到应用。The user remains signed into the app as long as the authentication cookie is valid.

ValidatePrincipal 事件可用于截获和重写 cookie 标识的验证。The ValidatePrincipal event can be used to intercept and override validation of the cookie identity. 验证每个请求的 cookie 会降低吊销用户访问应用的风险。Validating the cookie on every request mitigates the risk of revoked users accessing the app.

Cookie 验证的一种方法是基于跟踪用户数据库更改的时间。One approach to cookie validation is based on keeping track of when the user database changes. 如果在颁发用户 cookie 后数据库尚未更改,则无需重新对用户进行身份验证,前提是其 cookie 仍然有效。If the database hasn't been changed since the user's cookie was issued, there's no need to re-authenticate the user if their cookie is still valid. 在示例应用中,数据库在 IUserRepository 中实现并存储 LastChanged 值。In the sample app, the database is implemented in IUserRepository and stores a LastChanged value. 当在数据库中更新用户时,LastChanged 值设置为当前时间。When a user is updated in the database, the LastChanged value is set to the current time.

为了使数据库根据 LastChanged 值更改时使 cookie 无效,请使用包含数据库中当前 LastChanged 值的 LastChanged 声明创建 cookie:In order to invalidate a cookie when the database changes based on the LastChanged value, create the cookie with a LastChanged claim containing the current LastChanged value from the database:

var claims = new List<Claim>
{
    new Claim(ClaimTypes.Name, user.Email),
    new Claim("LastChanged", {Database Value})
};

var claimsIdentity = new ClaimsIdentity(
    claims, 
    CookieAuthenticationDefaults.AuthenticationScheme);

await HttpContext.SignInAsync(
    CookieAuthenticationDefaults.AuthenticationScheme, 
    new ClaimsPrincipal(claimsIdentity));

若要为 ValidatePrincipal 事件实现替代,请在从 CookieAuthenticationEvents派生的类中编写具有以下签名的方法:To implement an override for the ValidatePrincipal event, write a method with the following signature in a class that derives from CookieAuthenticationEvents:

ValidatePrincipal(CookieValidatePrincipalContext)

下面是 CookieAuthenticationEvents的示例实现:The following is an example implementation of CookieAuthenticationEvents:

using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;

public class CustomCookieAuthenticationEvents : CookieAuthenticationEvents
{
    private readonly IUserRepository _userRepository;

    public CustomCookieAuthenticationEvents(IUserRepository userRepository)
    {
        // Get the database from registered DI services.
        _userRepository = userRepository;
    }

    public override async Task ValidatePrincipal(CookieValidatePrincipalContext context)
    {
        var userPrincipal = context.Principal;

        // Look for the LastChanged claim.
        var lastChanged = (from c in userPrincipal.Claims
                           where c.Type == "LastChanged"
                           select c.Value).FirstOrDefault();

        if (string.IsNullOrEmpty(lastChanged) ||
            !_userRepository.ValidateLastChanged(lastChanged))
        {
            context.RejectPrincipal();

            await context.HttpContext.SignOutAsync(
                CookieAuthenticationDefaults.AuthenticationScheme);
        }
    }
}

Startup.ConfigureServices 方法中,在 cookie 服务注册期间注册事件实例。Register the events instance during cookie service registration in the Startup.ConfigureServices method. 提供 CustomCookieAuthenticationEvents 类的作用域服务注册Provide a scoped service registration for your CustomCookieAuthenticationEvents class:

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options =>
    {
        options.EventsType = typeof(CustomCookieAuthenticationEvents);
    });

services.AddScoped<CustomCookieAuthenticationEvents>();

请考虑这样一种情况:用户的名称更新—不会以任何方式影响安全性的决策。Consider a situation in which the user's name is updated—a decision that doesn't affect security in any way. 如果要以非破坏性的更新用户主体,请调用 context.ReplacePrincipal,并将 context.ShouldRenew 属性设置为 trueIf you want to non-destructively update the user principal, call context.ReplacePrincipal and set the context.ShouldRenew property to true.

警告

此处所述的方法在每个请求时触发。The approach described here is triggered on every request. 验证每个请求的所有用户的身份验证 cookie 可能会导致应用程序的性能下降。Validating authentication cookies for all users on every request can result in a large performance penalty for the app.

永久性 cookiePersistent cookies

你可能希望 cookie 在浏览器会话之间保持不变。You may want the cookie to persist across browser sessions. 仅当登录或类似机制上出现 "记住我" 复选框时,才应启用此持久性。This persistence should only be enabled with explicit user consent with a "Remember Me" check box on sign in or a similar mechanism.

下面的代码片段创建一个标识,并在浏览器闭包置了相应的 cookie。The following code snippet creates an identity and corresponding cookie that survives through browser closures. 预先配置的任何可调过期设置都将起作用。Any sliding expiration settings previously configured are honored. 如果关闭浏览器时 cookie 过期,则在重新启动后,浏览器将清除 cookie。If the cookie expires while the browser is closed, the browser clears the cookie once it's restarted.

IsPersistent 设置为 trueAuthenticationProperties中:Set IsPersistent to true in AuthenticationProperties:

// using Microsoft.AspNetCore.Authentication;

await HttpContext.SignInAsync(
    CookieAuthenticationDefaults.AuthenticationScheme,
    new ClaimsPrincipal(claimsIdentity),
    new AuthenticationProperties
    {
        IsPersistent = true
    });

绝对过期时间可使用 ExpiresUtc设置。An absolute expiration time can be set with ExpiresUtc. 若要创建持久性 cookie,还必须设置 IsPersistentTo create a persistent cookie, IsPersistent must also be set. 否则,cookie 是使用基于会话的生存期创建的,并且可能会在它所包含的身份验证票证之前或之后过期。Otherwise, the cookie is created with a session-based lifetime and could expire either before or after the authentication ticket that it holds. 设置 ExpiresUtc 后,它将覆盖 CookieAuthenticationOptionsExpireTimeSpan 选项的值(如果已设置)。When ExpiresUtc is set, it overrides the value of the ExpireTimeSpan option of CookieAuthenticationOptions, if set.

下面的代码片段将创建一个标识和对应的 cookie,此 cookie 持续20分钟。The following code snippet creates an identity and corresponding cookie that lasts for 20 minutes. 这将忽略以前配置的任何可调过期设置。This ignores any sliding expiration settings previously configured.

// using Microsoft.AspNetCore.Authentication;

await HttpContext.SignInAsync(
    CookieAuthenticationDefaults.AuthenticationScheme,
    new ClaimsPrincipal(claimsIdentity),
    new AuthenticationProperties
    {
        IsPersistent = true,
        ExpiresUtc = DateTime.UtcNow.AddMinutes(20)
    });

ASP.NET Core 标识是完整、功能齐全的身份验证提供程序,用于创建和维护登录名。ASP.NET Core Identity is a complete, full-featured authentication provider for creating and maintaining logins. 但是,可以使用不带 ASP.NET Core 标识的基于 cookie 的身份验证提供程序。However, a cookie-based authentication authentication provider without ASP.NET Core Identity can be used. 有关更多信息,请参见ASP.NET Core 上的标识简介For more information, see ASP.NET Core 上的标识简介.

查看或下载示例代码如何下载View or download sample code (how to download)

出于演示目的,在示例应用程序中,假设用户(Maria Rodriguez)的用户帐户已硬编码到应用中。For demonstration purposes in the sample app, the user account for the hypothetical user, Maria Rodriguez, is hardcoded into the app. 使用电子邮件地址 maria.rodriguez@contoso.com 和任何密码来登录用户。Use the Email address maria.rodriguez@contoso.com and any password to sign in the user. 用户在页面/帐户/登录名. .cs文件的 AuthenticateUser 方法中进行身份验证。The user is authenticated in the AuthenticateUser method in the Pages/Account/Login.cshtml.cs file. 在实际的示例中,用户将对数据库进行身份验证。In a real-world example, the user would be authenticated against a database.

配置Configuration

如果应用程序不使用AspNetCore 元包,请在 AspNetCore 包的项目文件中创建包引用(& c )。If the app doesn't use the Microsoft.AspNetCore.App metapackage, create a package reference in the project file for the Microsoft.AspNetCore.Authentication.Cookies package.

Startup.ConfigureServices 方法中,创建具有 AddAuthenticationAddCookie 方法的身份验证中间件服务:In the Startup.ConfigureServices method, create the Authentication Middleware service with the AddAuthentication and AddCookie methods:

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie();

AuthenticationScheme 传递到 AddAuthentication 设置应用程序的默认身份验证方案。AuthenticationScheme passed to AddAuthentication sets the default authentication scheme for the app. 如果有多个 cookie 身份验证实例,并且你想要使用特定方案进行授权AuthenticationScheme 会很有用。AuthenticationScheme is useful when there are multiple instances of cookie authentication and you want to authorize with a specific scheme. AuthenticationScheme 设置为CookieAuthenticationDefaults。 AuthenticationScheme为方案提供值 "cookie"。Setting the AuthenticationScheme to CookieAuthenticationDefaults.AuthenticationScheme provides a value of "Cookies" for the scheme. 可以提供任何用于区分方案的字符串值。You can supply any string value that distinguishes the scheme.

应用的身份验证方案不同于应用的 cookie 身份验证方案。The app's authentication scheme is different from the app's cookie authentication scheme. 如果未向 AddCookie提供 cookie 身份验证方案,则使用 CookieAuthenticationDefaults.AuthenticationScheme ("Cookie")。When a cookie authentication scheme isn't provided to AddCookie, it uses CookieAuthenticationDefaults.AuthenticationScheme ("Cookies").

默认情况下,身份验证 cookie 的 IsEssential 属性设置为 trueThe authentication cookie's IsEssential property is set to true by default. 当站点访问者未同意数据收集时,允许使用身份验证 cookie。Authentication cookies are allowed when a site visitor hasn't consented to data collection. 有关更多信息,请参见在 ASP.NET Core中的常规数据保护法规 (GDPR) 支持For more information, see 在 ASP.NET Core中的常规数据保护法规 (GDPR) 支持.

Startup.Configure 方法中,调用 UseAuthentication 方法来调用设置 HttpContext.User 属性的身份验证中间件。In the Startup.Configure method, call the UseAuthentication method to invoke the Authentication Middleware that sets the HttpContext.User property. 在调用 UseMvcWithDefaultRouteUseMvc之前调用 UseAuthentication 方法:Call the UseAuthentication method before calling UseMvcWithDefaultRoute or UseMvc:

app.UseAuthentication();

CookieAuthenticationOptions 类用于配置身份验证提供程序选项。The CookieAuthenticationOptions class is used to configure the authentication provider options.

在服务配置中设置 CookieAuthenticationOptions,以便在 Startup.ConfigureServices 方法中进行身份验证:Set CookieAuthenticationOptions in the service configuration for authentication in the Startup.ConfigureServices method:

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options =>
    {
        ...
    });

Cookie 策略中间件支持 cookie 策略功能。Cookie Policy Middleware enables cookie policy capabilities. 将中间件添加到应用处理管道是区分顺序的—它仅影响在管道中注册的下游组件。Adding the middleware to the app processing pipeline is order sensitive—it only affects downstream components registered in the pipeline.

app.UseCookiePolicy(cookiePolicyOptions);

使用提供给 Cookie 策略中间件的 CookiePolicyOptions 来控制 cookie 处理的全局特性并在附加或删除 cookie 时挂钩到 cookie 处理处理程序。Use CookiePolicyOptions provided to the Cookie Policy Middleware to control global characteristics of cookie processing and hook into cookie processing handlers when cookies are appended or deleted.

默认 MinimumSameSitePolicy 值为 SameSiteMode.Lax 以允许 OAuth2 authentication。The default MinimumSameSitePolicy value is SameSiteMode.Lax to permit OAuth2 authentication. 若要严格实施 SameSiteMode.Strict的同一站点策略,请设置 MinimumSameSitePolicyTo strictly enforce a same-site policy of SameSiteMode.Strict, set the MinimumSameSitePolicy. 尽管此设置会中断 OAuth2 和其他跨源身份验证方案,但它为不依赖于跨源请求处理的其他类型的应用提升了 cookie 安全级别。Although this setting breaks OAuth2 and other cross-origin authentication schemes, it elevates the level of cookie security for other types of apps that don't rely on cross-origin request processing.

var cookiePolicyOptions = new CookiePolicyOptions
{
    MinimumSameSitePolicy = SameSiteMode.Strict,
};

MinimumSameSitePolicy 的 Cookie 策略中间件设置会根据下面的矩阵影响 CookieAuthenticationOptions 设置中 Cookie.SameSite 的设置。The Cookie Policy Middleware setting for MinimumSameSitePolicy can affect the setting of Cookie.SameSite in CookieAuthenticationOptions settings according to the matrix below.

MinimumSameSitePolicyMinimumSameSitePolicy SameSiteCookie.SameSite 生成的 SameSite 设置Resultant Cookie.SameSite setting
SameSiteModeSameSiteMode.None SameSiteModeSameSiteMode.None
SameSiteModeSameSiteMode.Lax
SameSiteModeSameSiteMode.Strict
SameSiteModeSameSiteMode.None
SameSiteModeSameSiteMode.Lax
SameSiteModeSameSiteMode.Strict
SameSiteModeSameSiteMode.Lax SameSiteModeSameSiteMode.None
SameSiteModeSameSiteMode.Lax
SameSiteModeSameSiteMode.Strict
SameSiteModeSameSiteMode.Lax
SameSiteModeSameSiteMode.Lax
SameSiteModeSameSiteMode.Strict
SameSiteModeSameSiteMode.Strict SameSiteModeSameSiteMode.None
SameSiteModeSameSiteMode.Lax
SameSiteModeSameSiteMode.Strict
SameSiteModeSameSiteMode.Strict
SameSiteModeSameSiteMode.Strict
SameSiteModeSameSiteMode.Strict

若要创建保存用户信息的 cookie,请构造一个 ClaimsPrincipalTo create a cookie holding user information, construct a ClaimsPrincipal. 将对用户信息进行序列化并将其存储在 cookie 中。The user information is serialized and stored in the cookie.

使用任何所需的 Claim创建 ClaimsIdentity,并调用 SignInAsync 以登录用户:Create a ClaimsIdentity with any required Claims and call SignInAsync to sign in the user:

var claims = new List<Claim>
{
    new Claim(ClaimTypes.Name, user.Email),
    new Claim("FullName", user.FullName),
    new Claim(ClaimTypes.Role, "Administrator"),
};

var claimsIdentity = new ClaimsIdentity(
    claims, CookieAuthenticationDefaults.AuthenticationScheme);

var authProperties = new AuthenticationProperties
{
    //AllowRefresh = <bool>,
    // Refreshing the authentication session should be allowed.

    //ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(10),
    // The time at which the authentication ticket expires. A 
    // value set here overrides the ExpireTimeSpan option of 
    // CookieAuthenticationOptions set with AddCookie.

    //IsPersistent = true,
    // Whether the authentication session is persisted across 
    // multiple requests. When used with cookies, controls
    // whether the cookie's lifetime is absolute (matching the
    // lifetime of the authentication ticket) or session-based.

    //IssuedUtc = <DateTimeOffset>,
    // The time at which the authentication ticket was issued.

    //RedirectUri = <string>
    // The full path or absolute URI to be used as an http 
    // redirect response value.
};

await HttpContext.SignInAsync(
    CookieAuthenticationDefaults.AuthenticationScheme, 
    new ClaimsPrincipal(claimsIdentity), 
    authProperties);

SignInAsync 创建加密的 cookie,并将其添加到当前响应中。SignInAsync creates an encrypted cookie and adds it to the current response. 如果未指定 AuthenticationScheme,则使用默认方案。If AuthenticationScheme isn't specified, the default scheme is used.

ASP.NET Core 的数据保护系统用于加密。ASP.NET Core's Data Protection system is used for encryption. 对于托管在多台计算机上的应用程序、跨应用程序或使用 web 场进行负载平衡,请将数据保护配置为使用相同的密钥环和应用程序标识符。For an app hosted on multiple machines, load balancing across apps, or using a web farm, configure data protection to use the same key ring and app identifier.

注销Sign out

若要注销当前用户并删除其 cookie,请调用 SignOutAsyncTo sign out the current user and delete their cookie, call SignOutAsync:

await HttpContext.SignOutAsync(
    CookieAuthenticationDefaults.AuthenticationScheme);

如果 CookieAuthenticationDefaults.AuthenticationScheme (或 "Cookie")不用作方案(例如 "ContosoCookie"),请提供配置身份验证提供程序时所使用的方案。If CookieAuthenticationDefaults.AuthenticationScheme (or "Cookies") isn't used as the scheme (for example, "ContosoCookie"), supply the scheme used when configuring the authentication provider. 否则,将使用默认方案。Otherwise, the default scheme is used.

对后端更改作出反应React to back-end changes

创建 cookie 后,cookie 就是单一标识源。Once a cookie is created, the cookie is the single source of identity. 如果在后端系统中禁用用户帐户:If a user account is disabled in back-end systems:

  • 应用的 cookie 身份验证系统将继续根据身份验证 cookie 处理请求。The app's cookie authentication system continues to process requests based on the authentication cookie.
  • 只要身份验证 cookie 有效,用户就会保持登录到应用。The user remains signed into the app as long as the authentication cookie is valid.

ValidatePrincipal 事件可用于截获和重写 cookie 标识的验证。The ValidatePrincipal event can be used to intercept and override validation of the cookie identity. 验证每个请求的 cookie 会降低吊销用户访问应用的风险。Validating the cookie on every request mitigates the risk of revoked users accessing the app.

Cookie 验证的一种方法是基于跟踪用户数据库更改的时间。One approach to cookie validation is based on keeping track of when the user database changes. 如果在颁发用户 cookie 后数据库尚未更改,则无需重新对用户进行身份验证,前提是其 cookie 仍然有效。If the database hasn't been changed since the user's cookie was issued, there's no need to re-authenticate the user if their cookie is still valid. 在示例应用中,数据库在 IUserRepository 中实现并存储 LastChanged 值。In the sample app, the database is implemented in IUserRepository and stores a LastChanged value. 当在数据库中更新用户时,LastChanged 值设置为当前时间。When a user is updated in the database, the LastChanged value is set to the current time.

为了使数据库根据 LastChanged 值更改时使 cookie 无效,请使用包含数据库中当前 LastChanged 值的 LastChanged 声明创建 cookie:In order to invalidate a cookie when the database changes based on the LastChanged value, create the cookie with a LastChanged claim containing the current LastChanged value from the database:

var claims = new List<Claim>
{
    new Claim(ClaimTypes.Name, user.Email),
    new Claim("LastChanged", {Database Value})
};

var claimsIdentity = new ClaimsIdentity(
    claims, 
    CookieAuthenticationDefaults.AuthenticationScheme);

await HttpContext.SignInAsync(
    CookieAuthenticationDefaults.AuthenticationScheme, 
    new ClaimsPrincipal(claimsIdentity));

若要为 ValidatePrincipal 事件实现替代,请在从 CookieAuthenticationEvents派生的类中编写具有以下签名的方法:To implement an override for the ValidatePrincipal event, write a method with the following signature in a class that derives from CookieAuthenticationEvents:

ValidatePrincipal(CookieValidatePrincipalContext)

下面是 CookieAuthenticationEvents的示例实现:The following is an example implementation of CookieAuthenticationEvents:

using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;

public class CustomCookieAuthenticationEvents : CookieAuthenticationEvents
{
    private readonly IUserRepository _userRepository;

    public CustomCookieAuthenticationEvents(IUserRepository userRepository)
    {
        // Get the database from registered DI services.
        _userRepository = userRepository;
    }

    public override async Task ValidatePrincipal(CookieValidatePrincipalContext context)
    {
        var userPrincipal = context.Principal;

        // Look for the LastChanged claim.
        var lastChanged = (from c in userPrincipal.Claims
                           where c.Type == "LastChanged"
                           select c.Value).FirstOrDefault();

        if (string.IsNullOrEmpty(lastChanged) ||
            !_userRepository.ValidateLastChanged(lastChanged))
        {
            context.RejectPrincipal();

            await context.HttpContext.SignOutAsync(
                CookieAuthenticationDefaults.AuthenticationScheme);
        }
    }
}

Startup.ConfigureServices 方法中,在 cookie 服务注册期间注册事件实例。Register the events instance during cookie service registration in the Startup.ConfigureServices method. 提供 CustomCookieAuthenticationEvents 类的作用域服务注册Provide a scoped service registration for your CustomCookieAuthenticationEvents class:

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options =>
    {
        options.EventsType = typeof(CustomCookieAuthenticationEvents);
    });

services.AddScoped<CustomCookieAuthenticationEvents>();

请考虑这样一种情况:用户的名称更新—不会以任何方式影响安全性的决策。Consider a situation in which the user's name is updated—a decision that doesn't affect security in any way. 如果要以非破坏性的更新用户主体,请调用 context.ReplacePrincipal,并将 context.ShouldRenew 属性设置为 trueIf you want to non-destructively update the user principal, call context.ReplacePrincipal and set the context.ShouldRenew property to true.

警告

此处所述的方法在每个请求时触发。The approach described here is triggered on every request. 验证每个请求的所有用户的身份验证 cookie 可能会导致应用程序的性能下降。Validating authentication cookies for all users on every request can result in a large performance penalty for the app.

永久性 cookiePersistent cookies

你可能希望 cookie 在浏览器会话之间保持不变。You may want the cookie to persist across browser sessions. 仅当登录或类似机制上出现 "记住我" 复选框时,才应启用此持久性。This persistence should only be enabled with explicit user consent with a "Remember Me" check box on sign in or a similar mechanism.

下面的代码片段创建一个标识,并在浏览器闭包置了相应的 cookie。The following code snippet creates an identity and corresponding cookie that survives through browser closures. 预先配置的任何可调过期设置都将起作用。Any sliding expiration settings previously configured are honored. 如果关闭浏览器时 cookie 过期,则在重新启动后,浏览器将清除 cookie。If the cookie expires while the browser is closed, the browser clears the cookie once it's restarted.

IsPersistent 设置为 trueAuthenticationProperties中:Set IsPersistent to true in AuthenticationProperties:

// using Microsoft.AspNetCore.Authentication;

await HttpContext.SignInAsync(
    CookieAuthenticationDefaults.AuthenticationScheme,
    new ClaimsPrincipal(claimsIdentity),
    new AuthenticationProperties
    {
        IsPersistent = true
    });

绝对过期时间可使用 ExpiresUtc设置。An absolute expiration time can be set with ExpiresUtc. 若要创建持久性 cookie,还必须设置 IsPersistentTo create a persistent cookie, IsPersistent must also be set. 否则,cookie 是使用基于会话的生存期创建的,并且可能会在它所包含的身份验证票证之前或之后过期。Otherwise, the cookie is created with a session-based lifetime and could expire either before or after the authentication ticket that it holds. 设置 ExpiresUtc 后,它将覆盖 CookieAuthenticationOptionsExpireTimeSpan 选项的值(如果已设置)。When ExpiresUtc is set, it overrides the value of the ExpireTimeSpan option of CookieAuthenticationOptions, if set.

下面的代码片段将创建一个标识和对应的 cookie,此 cookie 持续20分钟。The following code snippet creates an identity and corresponding cookie that lasts for 20 minutes. 这将忽略以前配置的任何可调过期设置。This ignores any sliding expiration settings previously configured.

// using Microsoft.AspNetCore.Authentication;

await HttpContext.SignInAsync(
    CookieAuthenticationDefaults.AuthenticationScheme,
    new ClaimsPrincipal(claimsIdentity),
    new AuthenticationProperties
    {
        IsPersistent = true,
        ExpiresUtc = DateTime.UtcNow.AddMinutes(20)
    });

其他资源Additional resources