以往做授权的时候,自己并不清楚什么样的体系才叫授权,记得在摸索的时候,在不明觉厉的情况下,采用的是通过重写在每个Action执行之前的OnActionExecuting方法来对Session判断是否存储当前用户的登录状态,来进行授权策略分配,但微软推出了一套完整的Identity授权体系,门槛的确很高,但使用起来相当方便,让我们告别OnActionExecuting的重写,一起去探索更丰富的代码世界吧!
首先,创建一个类库项目,命名为Sys.Model
Nuget引用的第三方包如下:
1、Microsoft.AspNetCore.Identity.EntityFrameworkCore
2、Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
3、Microsoft.EntityFrameworkCore.Design
4、Microsoft.EntityFrameworkCore.Tools
5、 Microsoft.EntityFrameworkCore.SqlServer
编写SysUser类用于扩展IdentityUser作数据文上下类
public class SysUser:IdentityUser
{
[PersonalData]
public string Name { get; set; }
[PersonalData]
public DateTime DOB { get; set; }
}
编写SysContext继承IdentityDbContext
public class SysContext:IdentityDbContext<SysUser>
{
public SysContext(DbContextOptions<SysContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
}
}
创建一个Web项目,同样Nuget和上述一样的包,鼠标右击Web项目引用Model层,用于注入和获取数据库上下文类SysContext
鼠标右击Web项目向现有项目添加授权的基架,
选择要重构的部分
> 在Web层的appsettings.json里添加SqlServer连接字符串
"ConnectionStrings": {
"SysContext": "Server=.;Database=Sys;uid=sa;pwd=T@123;Trusted_Connection=True;MultipleActiveResultSets=true"
},
在Startup.cs的ConfigureServices进行注入和配置
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
//注入SqlServer连接字符串
services.AddDbContext<SysContext>(options =>
{
options.UseSqlServer(Configuration.GetConnectionString("SysContext"));
});
//注入授权策略
services.AddDefaultIdentity<SysUser>(options =>
options.SignIn.RequireConfirmedAccount = true)
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<SysContext>();
//属性设置
services.Configure<IdentityOptions>(options =>
{
//密码
options.Password.RequireDigit = true;//数字
options.Password.RequireLowercase = true;//小写字母
options.Password.RequireNonAlphanumeric = true;//特殊字符
options.Password.RequireUppercase = true;//大写字母
options.Password.RequiredLength = 6;//长度
options.Password.RequiredUniqueChars = 1;//包含大写ASCII字符位数
//锁
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);//过期时间
options.Lockout.MaxFailedAccessAttempts = 5;//失败次数
options.Lockout.AllowedForNewUsers = true;//允许新用户使用
//用户
options.User.AllowedUserNameCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";//允许的用户名字符
options.User.RequireUniqueEmail = false;//要求电子邮件
});
//Cookie配置
services.ConfigureApplicationCookie(options =>
{
options.Cookie.HttpOnly = true;//仅Http
options.ExpireTimeSpan = TimeSpan.FromMinutes(5);//Cookie过期时间
options.LoginPath = "/Identity/Account/Login";//登录路径
options.AccessDeniedPath = "/Identity/Account/AccessDenied";//访问拒绝路径
options.SlidingExpiration = true;//滑动过期
});
//注入自启动
services.AddControllersWithViews().AddRazorRuntimeCompilation();
//注入Razor
services.AddRazorPages();
}
在Startup.cs的Configure添加授权中间件的引用,并注入Razor访问路径的匹配,因为微软授权体系默认是Razor布局
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseRouting();
//使用Authorize
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
//Razor
endpoints.MapRazorPages();
});
}
执行以下命令生成数据库:
Add-Migration IdentitySchema
Update-Database
在Shared文件夹中_Layout.cshtml导航部分布局代码更改如下:
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
<partial name="_LoginPartial" />
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" href="/Test/Index">Test</a>
</li>
</ul>
</div>
此时运行,则基架搭建成功,但授权仍待进一步完成!
编写一个Controller,并添加相应的视图,并用AuthorIze作授权标识,其中Role代表的是所属角色才具有访问权限
[Authorize(Roles = "Admin")]
public class TestController : Controller
{
public IActionResult Index()
{
return View();
}
}
我们做一个简单的数据分配,也就是说:当前只有1@qq.com是拥有Admin角色权限的,2@qq.com,是不具有的
验证如下,可以清楚的看到拥有Admin角色的1@qq.com用户正常访问,未拥有Admin角色的用户2@qq.com,是不具有访问权限的:
到此,我们的ASP.NET Core的Identity授权基架基于角色的授权已圆满完成,当然有官网传送门:ASP.NET Core身份认证,再接再厉!