(使用ASP.NET 4.X 中的时候一定都用过Forms认证即FormsAuthentication做登录用户的身份认证,FormsAuthentication的核心就是Cookie,ASP.NET会将用户名存储在Cookie中。但是它很难进行扩展,更无法与第三方认证集成,因此,在 ASP.NET Core 中对认证与授权进行了全新的设计,并使用基于声明的认证(claims-based authentication))

一、新建项目初始化工作

在Controllers文件夹下新建AdminController.cs

设置视图

@{
ViewData["Title"] = "Admin";
}
<h2>@ViewData["Title"]</h2> <p>Admin Page</p>

运行展示:

二、Cookie-based认证实践

1、给AdminController添加 [Authorize] 标签

提示让我们引用该空间即可。

2、在Startup方法中进行cookie的依赖注入

ConfigureServices方法下添加

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options=>{//自定义登陆地址,不配置的话则默认为http://localhost:5000/Account/Login
options.LoginPath="/Account/MyLogin";
});

提示让我们引用该空间即可。

然后要在Configure方法中把cookie中间件也添加进来,否则认证授权是不会生效的

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
} app.UseStaticFiles();
app.UseCookiePolicy(); //注意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的值。

发现已经自动跳转到登陆地址了。

3、模拟登陆

暂时不做登陆的,只是模拟一下登陆,首先创建一个AccountController.cs

添加两个API用于登陆和登出

    public class AccountController : Controller
{
public IActionResult Index()
{
return View();
}
//登陆
public IActionResult MakeLogin()
{
var claims = new List<Claim>(){
new Claim(ClaimTypes.Name,"wangyuting"),
new Claim(ClaimTypes.Role,"admin")
};
//必须要加CookieAuthenticationDefaults.AuthenticationScheme,不然无法解析
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity));
return Ok();
}
//登出
public IActionResult Logout()
{
HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); return Ok();
} }

在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来判断用户是否已经登录

注销用户

那么登录用户后怎么注销登录呢?我们在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方法时也不会报错

最新文章

  1. ExtJS 4.2 业务开发(一)主页搭建
  2. Unicode转义(\uXXXX)的编码和解码
  3. MAC npm 需要管理员权限问题
  4. Cookie 与Session 的区别(转载)
  5. nagios plugin 开发
  6. centos yum 安装问题
  7. 【spoj SEQN】【hdu 3439】Sequence
  8. GridView使用CommandField删除列实现删除时提示确认框
  9. python的交代一
  10. redis学习心得之一【安装redis初体验】
  11. POJ 1151 - Atlantis 线段树+扫描线..
  12. Android Activity Fragment 生命周期
  13. Facebook Hacker Cup 2015 Round 1--Corporate Gifting(树动态规划)
  14. NHibernate构建一个ASP.NET MVC应用程序
  15. 在数据采集器中用TensorFlow进行实时机器学习
  16. dede 5.7 任意用户重置密码前台
  17. GitHub:我们是这样弃用jQuery的
  18. p1465 Preface Numbering
  19. Python魔术世界 1 如何使用Visual Studio在WIN10中一键安装Python3入门编程环境并测试Django
  20. 算法---数组总结篇2——找丢失的数,找最大最小,前k大,第k小的数

热门文章

  1. [517]Kite 题解
  2. jquery ajax实现文件上传
  3. css3 clac()方法
  4. Redis高可用分布式
  5. Sign on Fence(连续的长为W的一段中最小的数字的最大值)
  6. 使用IDEA 创建Maven项目,外加SSM框架
  7. 学习C#20天有感
  8. 记一次odoo创建新的模块时,但是在odoo web界面找不到应用的案例
  9. VMware 虚拟化编程(7) — VixDiskLib 虚拟磁盘库详解之三
  10. 通过git新增、更新代码内容到github