身份认证是网站最基本的功能,最近因为业务部门的一个需求,需要对一个已经存在很久的小工具网站进行改造,因为在逐步的将一些离散的系统迁移至 .NET Core,所以趁这个机会将这个老的 .NET Framework 4.0 的项目进行升级
老的项目是一个 MVC 的项目并且有外网访问的需求,大部门的微服务平台因为和内部的业务执行比较密切,介于资安要求与外网进行了隔离,因此本次升级就不会迁移到该平台上进行前后端分离改造
使用频次不高,不存在高并发,实现周期短,所以就没有必要为了用某些组件而用,因此这里还是选择沿用 MVC 框架,对于网站的身份认证则采用单体应用最常见的 Cookie 认证来实现,本篇文章则是如何实现的一个基础的教程,仅供参考
Step by Step在涉及到系统权限管理的相关内容时,必定会提到两个长的很像的单词,authentication(认证) 和 authorization(授权)
authentication:用一些数据来证明你就是你,登录系统、指纹、面部解锁就是一种认证的过程
authorization:授予一些用户去访问一些特殊资源或功能的过程,系统包含管理员和普通用户两种角色,只有管理员才可以执行某些操作,赋予管理员角色某些操作的过程就是授权
只有认证和授权一起配合,才可以完成对于整个系统的权限管控
2.1、前期准备假定现在已经存在了一个 ASP.NET Core MVC 应用,这里以 VS 创建的默认项目为例,对于一个 MVC or Web API 应用,要求用户必须登录之后才能进行访问,最简单的方式,在需要认证的 Controller 或 Action 上添加 Authorize 特性,然后在 Startup.Configure 方法中通过 UseAuthorization 添加中间件即可
[Authorize] public class HomeController : Controller { public IActionResult Index() { return View(); } } public class Startup { public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( "default", "{controller=Home}/{action=Index}/{id?}"); }); } }当然,当系统只包含一个两个 Controller 时还好,当系统比较复杂的时候,再一个个的添加 Authorize 特性就比较麻烦了,因此这里我们可以通过在 Startup.ConfigureServices 中添加全局的 AuthorizeFilter 过滤器,实现对于全局的认证管控
public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews() .AddMvcOptions(options => { options.Filters.Add(new AuthorizeFilter()); }); } }此时,对于一些不需要进行认证就可以访问的页面,只需要添加 AllowAnonymous 特性即可
public class AuthenticationController : Controller { [AllowAnonymous] public IActionResult Login() { return View(); } } 2.2、配置认证策略当然,如果只是这样修改的话,其实是有问题的,可以看到,当添加上全局过滤器后,系统已经无法正常的进行访问
对于 authorization(授权) 来说,它其实是在 authentication(认证)通过之后才会进行的操作,也就是说这里我们缺少了对于系统认证的配置,依据报错信息的提示,我们首先需要通过使用 AddAuthentication 方法来定义系统的认证策略
AddAuthentication 方法位于 Microsoft.AspNetCore.Authentication 类库中,通过在 Nuget 中搜索就可以发现,.NET Core 已经基于业界通用的规范实现了多个认证策略
因为这里使用的 Cookie 认证已经包含在默认的项目模板中了,所以就不需要再引用了
基于 .NET Core 标准的服务使用流程,首先,我们需要在 Startup.ConfigureServices 方法来中通过 AddAuthentication 来定义整个系统所使用的一个授权策略,以及,基于我们采用 Cookie 授权的方式,结合目前互联网针对跨站点请求伪造 (CSRF) 攻击的防范要求,我们需要对网站的 Cookie 进行一些设定
public class Startup { public void ConfigureServices(IServiceCollection services) { // 定义授权策略 services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { // 无权访问的页路径 options.AccessDeniedPath = new PathString("/permission/forbidden"); // 登录路径 options.LoginPath = new PathString("/authentication/login"); // 登出路径 options.LogoutPath = new PathString("/authentication/logout"); // Cookie 过期时间(20 分钟) options.ExpireTimeSpan = TimeSpan.FromMinutes(20); }); // 配置 Cookie 策略 services.Configure<CookiePolicyOptions>(options => { // 默认用户同意非必要的 Cookie options.CheckConsentNeeded = context => true; // 定义 SameSite 策略,Cookies允许与顶级导航一起发送 options.MinimumSameSitePolicy = SameSiteMode.Lax; }); } }