大家在使用ASP.NET的时候一定都用过FormsAuthentication做登录用户的身份认证,FormsAuthentication的核心就是Cookie,ASP.NET会将用户名存储在Cookie中。

现在到了ASP.NET CORE的时代,但是ASP.NET CORE中没有FormsAuthentication这个东西,那么怎么做身份认证呢?答案是ASP.NET CORE已经为我们内置了Cookie身份认证的功能,而且使用起来非常方便,注意本文是基于ASP.NET CORE 2.0版本来阐述Cookie认证方式的。

1.从ASP.NET CORE OWIN框架中启用Cookie身份认证功能


要在ASP.NET CORE中使用Cookie身份认证,第一步就是在项目中的OWIN框架文件Startup.cs中启用Cookie身份认证中间件。

首先我们在Startup中的ConfigureServices方法中使用services.AddAuthentication注册Cookie认证服务,如下代码所示:

public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(); //注册Cookie认证服务
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
}

注意,我们还可以用AddCookie的重载方法,来设置存储用户登录信息(用户Token信息)Cookie的属性,详情可以查看CookieBuilder,如下代码所示:

public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(); //注册Cookie认证服务
services
.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, option =>
{
option.Cookie.Name = "MyApplicationTokenCookie";//设置存储用户登录信息(用户Token信息)的Cookie名称
option.Cookie.HttpOnly = true;//设置存储用户登录信息(用户Token信息)的Cookie,无法通过客户端浏览器脚本(如JavaScript等)访问到
option.Cookie.SecurePolicy = Microsoft.AspNetCore.Http.CookieSecurePolicy.Always;//设置存储用户登录信息(用户Token信息)的Cookie,只会通过HTTPS协议传递,如果是HTTP协议,Cookie不会被发送。注意,option.Cookie.SecurePolicy属性的默认值是Microsoft.AspNetCore.Http.CookieSecurePolicy.SameAsRequest
});
}

注意,option.Cookie.SecurePolicy属性的值是枚举类型Microsoft.AspNetCore.Http.CookieSecurePolicy,其默认值是Microsoft.AspNetCore.Http.CookieSecurePolicy.SameAsRequest。当我们使用上面的代码,来设置存储用户登录信息(用户Token信息)Cookie的属性后,在用户成功登录我们的站点后,我们可以看到客户端浏览器在HTTP响应中,会收到如下Cookie信息,和我们上面代码中设置的三个Cookie属性是匹配的:

然后在Startup中的Configure方法中使用app.UseAuthentication启用Cookie认证中间件(注意其中app.UseAuthentication和app.UseMvc的调用顺序不能反),如下代码所示:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
} app.UseStaticFiles(); //注意app.UseAuthentication方法一定要放在下面的app.UseMvc方法前面,否者后面就算调用HttpContext.SignInAsync进行用户登录后,使用
//HttpContext.User还是会显示用户没有登录,并且HttpContext.User.Claims读取不到登录用户的任何信息。
//这说明Asp.Net OWIN框架中MiddleWare的调用顺序会对系统功能产生很大的影响,各个MiddleWare的调用顺序一定不能反
app.UseAuthentication(); app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
}); }

这里顺便说一下app.UseAuthentication是用来干什么的,app.UseAuthentication会启用Authentication中间件,该中间件会根据当前Http请求中的Cookie信息来设置HttpContext.User属性(后面会用到),所以只有在app.UseAuthentication方法之后注册的中间件才能够从HttpContext.User中读取到值,这也是为什么上面强调app.UseAuthentication方法一定要放在下面的app.UseMvc方法前面,因为只有这样ASP.NET Core的MVC中间件中才能读取到HttpContext.User的值。

ASP.NET Core 3.0

由于在ASP.NET Core 3.0中,app.UseMvcapp.UseRoutingapp.UseEndpoints替代,所以app.UseAuthenticationapp.UseAuthorization,要放在app.UseRoutingapp.UseCors之后,并且在app.UseEndpoints之前,如下所示:

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
} app.UseStaticFiles(); app.UseRouting();
app.UseCors(); app.UseAuthentication();
app.UseAuthorization(); app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}

详情可以查看:Migrate from ASP.NET Core 2.2 to 3.0

2.登录用户


在ASP.NET CORE中使用Cookie认证登录用户的方法和传统的FormsAuthentication不太一样,大致步骤如下:

  • 创建Claim类型的数组,将登录用户的所有信息(比如用户名)存储在Claim类型的字符串键值对中
  • 将上面创建的Claim类型的数组传入ClaimsIdentity中,用来构造一个ClaimsIdentity对象
  • 将上面创建的ClaimsIdentity对象传入ClaimsPrincipal中,用来构造一个ClaimsPrincipal对象
  • 调用HttpContext.SignInAsync方法,传入上面创建的ClaimsPrincipal对象,完成用户登录

所以我们可以看到整个ASP.NET CORE的Cookie认证登录流程比以前ASP.NET的FormsAuthentication还是要复杂许多,毕竟以前一个FormsAuthentication.SetAuthCookie方法就搞定了。

在本文的例子中我们在项目中默认的HomeController中创建了一个Acion方法Login,来实现用户登录的代码。当然这里我们实现的是最简的Cookie登录,下面代码中实际上还可以设置Cookie是否持久化、Cookie多久过期、存储登录用户信息的Cookie的名字是什么等,我们就不做过多介绍了,大家可以阅读本文最后推荐的两份官方文档了解更多。

Login方法的代码如下:

/// <summary>
/// 该Action登录用户Wangdacui到Asp.Net Core
/// </summary>
public IActionResult Login()
{
//下面的变量claims是Claim类型的数组,Claim是string类型的键值对,所以claims数组中可以存储任意个和用户有关的信息,
//不过要注意这些信息都是加密后存储在客户端浏览器cookie中的,所以最好不要存储太多特别敏感的信息,这里我们只存储了用户名到claims数组,
//表示当前登录的用户是谁
var claims = new[] { new Claim("UserName", "Wangdacui") }; var claimsIdentity = new ClaimsIdentity(
claims,
CookieAuthenticationDefaults.AuthenticationScheme); ClaimsPrincipal user = new ClaimsPrincipal(claimsIdentity); Task.Run(async () =>
{
//登录用户,相当于ASP.NET中的FormsAuthentication.SetAuthCookie
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, user); //可以使用HttpContext.SignInAsync方法的重载来定义持久化cookie存储用户认证信息,例如下面的代码就定义了用户登录后60分钟内cookie都会保留在客户端计算机硬盘上,
//即便用户关闭了浏览器,60分钟内再次访问站点仍然是处于登录状态,除非调用Logout方法注销登录。
//注意其中的AllowRefresh属性,如果AllowRefresh为true,表示如果用户登录后在超过50%的ExpiresUtc时间间隔内又访问了站点,就延长用户的登录时间(其实就是延长cookie在客户端计算机硬盘上的保留时间),
//例如本例中我们下面设置了ExpiresUtc属性为60分钟后,那么当用户登录后在大于30分钟且小于60分钟内访问了站点,那么就将用户登录状态再延长到当前时间后的60分钟。但是用户在登录后的30分钟内访问站点是不会延长登录时间的,
//因为ASP.NET Core有个硬性要求,是用户在超过50%的ExpiresUtc时间间隔内又访问了站点,才延长用户的登录时间。
//如果AllowRefresh为false,表示用户登录后60分钟内不管有没有访问站点,只要60分钟到了,立马就处于非登录状态(不延长cookie在客户端计算机硬盘上的保留时间,60分钟到了客户端计算机就自动删除cookie)
/*
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
user, new AuthenticationProperties()
{
IsPersistent = true,
ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(60),
AllowRefresh = true
});
*/ }).Wait(); return View();
}

如果当前Http请求本来登录了用户A,现在调用HttpContext.SignInAsync方法登录用户B,那么相当于注销用户A,登录用户B

3.读取登录用户信息


那么用户登录后怎么将登录用户的信息(比如用户名)读取出来呢?我们在HomeController的Index方法中演示了如何判断当前用户是否已经登录,并且读出登录用户的用户名,Index方法的代码如下所示:

/// <summary>
/// 该Action判断用户是否已经登录,如果已经登录,那么读取登录用户的用户名
/// </summary>
public IActionResult Index()
{
//如果HttpContext.User.Identity.IsAuthenticated为true,
//或者HttpContext.User.Claims.Count()大于0表示用户已经登录
if (HttpContext.User.Identity.IsAuthenticated)
{
//这里通过 HttpContext.User.Claims 可以将我们在Login这个Action中存储到cookie中的所有
//claims键值对都读出来,比如我们刚才定义的UserName的值Wangdacui就在这里读取出来了
var userName = HttpContext.User.Claims.First().Value;
} return View();
}

注意,最好还是用HttpContext.User.Identity.IsAuthenticated来判断用户是否已经登录

4.注销用户


那么登录用户后怎么注销登录呢?我们在HomeController的Logout方法中演示了如何注销登录的用户,代码如下所示:

/// <summary>
/// 该Action从Asp.Net Core中注销登录的用户
/// </summary>
public IActionResult Logout()
{
Task.Run(async () =>
{
//注销登录的用户,相当于ASP.NET中的FormsAuthentication.SignOut
await HttpContext.SignOutAsync();
}).Wait(); return View();
}

如果当前Http请求本来就没有登录用户,那么调用HttpContext.SignOutAsync方法时也不会报错

5.负载均衡


警告:
ASP.NET Core使用 ASP.NET Core data protection stack 来实现Cookie身份认证。如果在服务器集群中必须配置 ASP.NET Core Data Protection,有关详细信息,请参阅 Configuring data protection。如果你的ASP.NET Core站点使用了负载均衡部署了多个实例,就要做ASP.NET Core Data Protection的配置,否则ASP.NET CORE跨多个实例进行Cookie身份认证会失败。

还可以参考:Host ASP.NET Core in a web farm 以及 Share authentication cookies among ASP.NET apps

如何管理ASP.NET Core Data Protection的过期key,可以查看:Data Protection - how to manage expired key?

前面说了实际上在ASP.NET CORE的Cookie认证中还可以设置Cookie的名字、是否持久化存储等,可以参考如下两篇官方文档了解:

Using Cookie Authentication without ASP.NET Core Identity

Cutting Edge - Cookies, Claims and Authentication in ASP.NET Core

ASP.NET CORE中使用Cookie身份认证的更多相关文章

  1. asp.net core中使用cookie身份验证

    配置 在 Startup.ConfigureServices 方法中,创建具有 AddAuthentication 和 AddCookie 方法的身份验证中间件服务: services.AddAuth ...

  2. ASP.NET Core系列:JWT身份认证

    1. JWT概述 JSON Web Token(JWT)是目前流行的跨域身份验证解决方案. JWT的官网地址:https://jwt.io JWT的实现方式是将用户信息存储在客户端,服务端不进行保存. ...

  3. 在ASP.NET Core 中使用Cookie中间件

    在ASP.NET Core 中使用Cookie中间件 ASP.NET Core 提供了Cookie中间件来序列化用户主题到一个加密的Cookie中并且在后来的请求中校验这个Cookie,再现用户并且分 ...

  4. 在ASP.NET Core 中使用Cookie中间件 (.net core 1.x适用)

    在ASP.NET Core 中使用Cookie中间件 ASP.NET Core 提供了Cookie中间件来序列化用户主题到一个加密的Cookie中并且在后来的请求中校验这个Cookie,再现用户并且分 ...

  5. ASP.NET Core如何使用WSFederation身份认证集成ADFS

    如果要在ASP.NET Core项目中使用WSFederation身份认证,首先需要在项目中引入NuGet包: Microsoft.AspNetCore.Authentication.WsFedera ...

  6. 关于ASP.Net Core Web及API身份认证的解决方案

    6月15日,在端午节前的最后一个工作日,想起有段日子没有写过文章了,倒有些荒疏了.今借夏日蒸蒸之气,偷得浮生半日悠闲.闲话就说到这里吧,提前祝大家端午愉快(屈原听了该不高兴了:))!.NetCore自 ...

  7. ASP.NET Core编程实现基本身份认证

    概览 在HTTP中,基本认证(Basic access authentication,简称BA认证)是一种用来允许网页浏览器或其他客户端程序在请求资源时提供用户名和口令形式的身份凭证的一种登录验证方式 ...

  8. ASP.NET Core的无状态身份认证框架IdentityServer4

    Identity Server 4是IdentityServer的最新版本,它是流行的OpenID Connect和OAuth Framework for .NET,为ASP.NET Core和.NE ...

  9. ASP.NET Core 3.0 gRPC 身份认证和授权

    一.开头聊骚 本文算是对于 ASP.NET Core 3.0 gRPC 研究性学习的最后一篇了,以后在实际使用中,可能会发一些经验之文.本文主要讲 ASP.NET Core 本身的认证授权和gRPC接 ...

随机推荐

  1. ReactJS webpack实现JS模块化使用的坑

    从一个原生HTML/CSS/JS模式的网页改造到ReactJS模块化的结构,需要以下步骤: (1)引用ReactJS框架 ->(2)使用webpack 工具 -> (3)配置webpack ...

  2. 看jpg和png图片

    emacs 24.4 下载http://pan.baidu.com/s/1mgIEPHe里的: zlib1.dll, libpng16-16.dll(png)和libjpeg-9.dll到emacs里 ...

  3. phpcms更换域名||外网访问本地网站

    在网站在发展的过程中,很可能多次的修改域名:然后就发现我的搜索页还是之前的域名的链接地址,那么在PHPCMS V9中我们要怎么进行设置呢?   请进行以下步骤的修改: 修改/caches/config ...

  4. 安卓向服务器发送List数据

    第一步: 首先写一个自定义的JavaBean,以UserInfo.java为例,需要实现对象序列化的接口,因为之后输出流对象需要实现输出可序列化的对象.不这样的话,后续时发送时会报异常 package ...

  5. left (outer) join , right (outer) join, full (outer) join, (inner) join, cross join 区别

    z       --     -- select   a.*,b.*   from   a   left   join   b   on   a.k   =   b.k      select   a ...

  6. IOS 10适配https 包含对于一些http的一些兼容配置

    iOS10 从2017年1月1日起苹果提出所有新提交的App默认不允许使用NSAllowsArbitraryLoads来绕过ATS的限制,也就是说强制我们用HTTPS,如果不这样的话提交App可能会被 ...

  7. oracle 11G rac 11.2.0.1 打补丁9413827

    这是升级到以后11.2.0.2.11.2.0.3.11.2.0.4的基础 主要参考两篇文章: Upgrade_11.2.0.1_GI_CRS_to_11.2.0.2_in_Linux.PDF文件 ht ...

  8. 动态验证码处理UI自动化获取处理

    解决思路两种:1.直接linux catalina.out读取:一分每10s轮询出现新的直接读取返回<br>2.缓存注入cookie,先手动登录获取session 然后通过注入user,p ...

  9. centos7.2安装mysql5.7

    1.安装前工作 在安装前需要确定现在这个系统有没有 mysql,如果有那么必须卸载(在 centos7 自带的是 mariaDb 数据库,所以第一步是卸载数据库). 卸载系统自带的Mariadb: 查 ...

  10. Eclipse中安装Maven插件 M2eclipse

    下面是官网的说明,基本上的意思下面有图片说明. To install m2eclipse, use the following Eclipse update site to install the c ...