标签:管理 get isp 代码 需要 丢失 生成 配置 services
原文:Microsoft.AspNetCore.Authentication.Cookies从入门到精通 (一)
? Microsoft.AspNetCore.Authentication.Cookies
是一个存储组件,它的主要作用是通过Cookie机制将授权认证的回话信息保存到客户端中,这与我之前的文章AspNetCore中基于session的身份认证中的HttpSession原理相同,只不过在AspNetCore中基于session的身份认证这篇文章中我们是自己做的一套验证方案,而篇文章使用的是Asp.Net Core提供的认证方案而已。
1.创建一个Razor Page
项目:dotnet new razor -n CookieSample
2.打开Startup.cs文件,添加认证代码
public void ConfigureServices(IServiceCollection services)
{
.......
services.AddAuthentication()
.AddCookie();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
......
app.UseAuthentication();
......
}
只需要几行代码我们就在项目中添加了授权认证功能,下面我们看如何在页面中使用授权认证
3.打开Index.cshtml.cs文件,添加我们的认证代码
[Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)]
public class IndexModel : PageModel
{
public void OnGet()
}
只需要一行代码,我的页面就成了一个需要授权认证后才能访问的页面,运行项目访问该页面查看效果。
4.添加Login页面,并在该页面实现登陆认证
当你打开Index
页面的时候你会发现被重定向了到了/Account/Login
,此时我们的项目中还没有这个页面,现在我们创建Login
页面并添加一些登陆代码,这里所谓登陆并不是真正的从数据库里面验证用户信息,当然从数据验证的过程应该在该操作之前,这里的登陆是将我们希望保存在Cookie中的信息传递给Asp.Net Core认证组件,并由该组件将信息序列化到Cookie中,由此可见Microsoft.AspNetCore.Authentication.Cookies只是为了存储
public class LoginModel : PageModel
{
public void OnPost()
{
//这里可能需要去数据验证一些信息
......
//数据库验证通过后,我们需要将部分信息保存到Cookie中
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name,"Tst")
};
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity));
}
}
这就是我们Demo的全部代码,是不是很简单。
通常我们的网站会区分前台与后台,普通用户可以访问的我们叫前台,管理员可以访问的我们叫后台。
1. 我们将基于之前的Demo
进行改造,现在我们的项目分为两类用户而且每类用户访问的页面还不相同。
2. 我们来创建管理员可以访问的页面:/Admin/Index,现在我们有了两个页面分别供两类用户访问,但是我们只有一个Login
页面那么怎么才能让两类用户公用也一个登陆页面呢?
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
......
services.AddAuthentication()
.AddCookie()
.AddCookie("Admin","Admin",options=>{});
......
}
上面代码我添加一个了一个Admin
认证方案用于管理员访问并在/Admin/Index
页面中显式设置认证方案:
/Admin/Index
[Authorize(AuthenticationSchemes = "Admin")]
public class IndexModel : PageModel{}
3. 现在我们来修改Login页面代码,我们需要根据认证方案来做不同的认证登录,目的是为了生成认证的cookie信息
public class LoginModel : PageModel
{
//保存认证方案以及友好显示名称
[BindProperty]
public IDictionary<string, string> Schemes { get; set; } = new Dictionary<string, string>();
//认证后我们要跳转到的页面
[BindProperty]
public string RedirectToUrl { get; set; }
IAuthenticationSchemeProvider _authenticationSchemeProvider;
//构造函数注入方式获取IAuthenticationSchemeprovider实例
public LoginModel(IAuthenticationSchemeProvider authenticationSchemeProvider)
{
//也可以通过从服务中查找的方式获取IAuthenticationSchemeprovider实例
//_authenticationSchemeProvider = (IAuthenticationSchemeProvider)HttpContext.RequestServices.GetService(typeof(IAuthenticationSchemeProvider));
_authenticationSchemeProvider = authenticationSchemeProvider;
}
public async Task OnGetAsync(string ReturnUrl)
{
RedirectToUrl = ReturnUrl;
var authenticationSchemes = await _authenticationSchemeProvider.GetAllSchemesAsync();
foreach (var item in authenticationSchemes)
{
//如果我们没有设置DisplayName,就是用认证方案名称替换
Schemes.Add(item.Name, item.DisplayName??item.Name);
}
}
public IActionResult OnPost(string scheme,string redirectUrl)
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name,scheme)
};
//生成不同认证方案的身份信息
var claimsIdentity = new ClaimsIdentity(claims, scheme);
//将认证信息保存到cookie中
HttpContext.SignInAsync(scheme, new ClaimsPrincipal(claimsIdentity));
return LocalRedirect(redirectUrl);
}
}
我们来回顾一下代码做了什么事:
首先,我们在构造函数中注入了IAuthenticationSchemeProvider
的实例,该实例主要用来获取认所有的证方案。
然后,我们将选择的认证方案以及认证后要跳转的地址Post到Login页面(这里也需要你提交用户名密码等从数据验证),验证后并将一些信息写入Cookie中。
插播一点个人的想法:有人可能会想我们分两个项目不行吗?我们搞成微服务不行吗?我的回答是不行:因为这里的一切教程都是围绕Microsoft.AspNetCore.Authentication.Cookies
的功能进行讲解,实现认证的方式有很多种,每个人都会有自己的想法和实现,但我们只讲Asp.Net Core提供的东西,这样有利于统一,也有利于减少学习成本,学习成本少了才有时间去创新。
? 要求普通用户认证信息在最后一次访问的10分钟后过期,而管理员需要在最后一次访问的1天后过期。
public void ConfigureServices(IServiceCollection services)
{
......
services.AddAuthentication()
.AddCookie(options=>{
options.SlidingExpiration = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(10);
})
.AddCookie("Admin","Admin",options=>{
options.SlidingExpiration = true;
options.ExpireTimeSpan = TimeSpan.FromDays(1);
});
......
}
我们通过两个属性实现了授权过期
SlidingExpiration:通过设置这个参数为Ture可以将过期时间变成滚动(滑动)过期,也就是按最后一次访问重新计算过期时间,只有设置了滑动Cookie我们的认证信息才更像一个回话状态。
ExpireTimeSpan:设置过期时间
在上面的需求中,每当我们关闭浏览器,Cookie的状态就丢失了,这不符合我们的要求,现在我们来修改让Cookie持久的保存在客户端。在之前的文章理解cookies中我们介绍了如何让cookie持久化,原理就是显式设置Expires
和MaxAge
。
public void ConfigureServices(IServiceCollection services)
{
......
services.AddAuthentication()
.AddCookie(options=>{
options.SlidingExpiration = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(10);
//这里我们将Cookie过期时间设置成了365天,你也可以通过MaxAge属性来设置,不过这里有点需要注意的是,MaxAge会替代Expiration的值
options.Cookie.Expiration = TimeSpan.FromDays(365);
//options.Cookie.MaxAge = TimeSpan.FromDays(365);
})
.AddCookie("Admin","Admin",options=>{
options.SlidingExpiration = true;
options.ExpireTimeSpan = TimeSpan.FromDays(1);
options.Cookie.Expiration = TimeSpan.FromDays(365);
});
......
}
只需要一行代码我们就让Cookie变成了持久化Cookie,但有个问题,我们将普通用户的认证Cookie设置为10分钟过期,但却将Cookie设置为365天(这里的认证Cookie与Cookie是一个东西,认证Cookie的过期是认证服务验证的,而Cookie本身是浏览器验证的,如果浏览器认为Cookie过期则认证服务根本获取不到Cookie信息),当访问页面的间隔大于10分钟时,Cookie依然会失效,此时虽然Cookie值还在但已经是无意义的一段数据了,所以我们将这三个值options.ExpireTimeSpan
,options.Cookie.Expiration
,options.Cookie.MaxAge
设置为相同似乎更合理点。
Microsoft.AspNetCore.Authentication.Cookies从入门到精通 (一)
标签:管理 get isp 代码 需要 丢失 生成 配置 services
原文地址:https://www.cnblogs.com/lonelyxmas/p/12988995.html