1.从ASP.NET CORE 中启用Cookie身份认证功能
首先我们在Startup中的ConfigureServices方法中使用services.AddAuthentication注册Cookie认证服务:
//注册Cookie认证服务
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
然后在Startup中的Configure方法中使用app.UseAuthentication启用Cookie认证中间件(注意其中app.UseAuthentication和app.UseMvc的调用顺序不能反),如下代码所示:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//注意app.UseAuthentication方法一定要放在下面的app.UseMvc方法前面,否者后面就算调用HttpContext.SignInAsync进行用户登录后,使用
//HttpContext.User还是会显示用户没有登录,并且HttpContext.User.Claims读取不到登录用户的任何信息。
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
app.UseAuthentication会启用Authentication中间件,该中间件会根据当前Http请求中的Cookie信息来设置HttpContext.User属性,所以只有在app.UseAuthentication方法之后注册的中间件才能够从HttpContext.User中读取到值,这也是为什么上面强调app.UseAuthentication方法一定要放在下面的app.UseMvc方法前面。
ASP.NET Core 3.0
由于在ASP.NET Core 3.0中,app.UseMvc被app.UseRouting和app.UseEndpoints替代,所以app.UseAuthentication和app.UseAuthorization,要放在app.UseRouting、app.UseCors之后,并且在app.UseEndpoints之前
2.登录用户
在ASP.NET CORE中使用Cookie认证登录大致步骤如下:
- 创建Claim类型的数组,将登录用户的所有信息(比如用户名)存储在Claim类型的字符串键值对中
- 将上面创建的Claim类型的数组传入ClaimsIdentity中,用来构造一个ClaimsIdentity对象
- 将上面创建的ClaimsIdentity对象传入ClaimsPrincipal中,用来构造一个ClaimsPrincipal对象
- 调用HttpContext.SignInAsync方法,传入上面创建的ClaimsPrincipal对象,完成用户登录
Login方法的代码如下:
/// <summary>
/// 该Action登录用户Wangdacui到Asp.Net Core
/// </summary>
public IActionResult Login()
{
//不过要注意这些信息都是加密后存储在客户端浏览器cookie中的,所以最好不要存储太多特别敏感的信息,这里我们只存储了用户名到claims数组,
//表示当前登录的用户是谁
var claims = new[] { new Claim("UserName", "Wangdacui") };
var claimsIdentity = new ClaimsIdentity(
claims,
CookieAuthenticationDefaults.AuthenticationScheme);
ClaimsPrincipal user = new ClaimsPrincipal(claimsIdentity);
//登录用户,相当于ASP.NET中的FormsAuthentication.SetAuthCookie
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, user);
//可以使用HttpContext.SignInAsync方法的重载来定义持久化cookie存储用户认证信息,例如下面的代码就定义了用户登录后60分钟内cookie都会保留在客户端计算机硬盘上,
//注意其中的AllowRefresh属性,如果为true,表示如果用户登录后在超过50%的ExpiresUtc时间间隔内又访问了站点,就延长登录时间,
//因为ASP.NET Core有个硬性要求,是用户在超过50%的ExpiresUtc时间间隔内又访问了站点,才延长用户的登录时间。
/*
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
user, new AuthenticationProperties()
{
IsPersistent = true,
ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(60),
AllowRefresh = true
});
*/
return View();
}
如果当前Http请求本来登录了用户A,现在调用HttpContext.SignInAsync方法登录用户B,那么相当于注销用户A,登录用户B
3.读取登录用户信息
/// <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.注销用户
/// <summary> /// 该Action从Asp.Net Core中注销登录的用户 /// </summary> public IActionResult Logout() { Task.Run(async () => { //注销登录的用户,相当于ASP.NET中的FormsAuthentication.SignOut await HttpContext.SignOutAsync(); }).Wait(); return View(); }