点击蓝字关注我们
课程链接:/course/explore
良心课程,大家一起来学习哈!
任务31:课时介绍
1.Cookie-based认证与授权
2.Cookie-based认证实现
3.Jwt认证与授权介绍
4.Jwt认证与授权实现
5.Jwt认证与授权
6.Role based授权
7.Claims-based授权
任务32:Cookie-based认证介绍
任务34:Cookie-based认证实现
dotnet new mvc --name MvcCookieAuthSample
在Controllers文件夹新增AdminController.cs
using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using MvcCookieAuthSample.Models; namespace MvcCookieAuthSample.Controllers { public class AdminController : Controller { public IActionResult Index() { return View(); } } }using System;
在Views文件夹新增Admin文件夹,在Admin文件夹新增Index.cshtml
ViewData["Title"] = "Admin"; } <h2>@ViewData["Title"]</h2> <p>Admin Page</p>@{
启动项目,浏览器访问https://localhost:5001/Admin
实际情况不应该直接让用户访问到Admin页面,所以应当跳转到登陆界面
AdminController.cs
using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using MvcCookieAuthSample.Models; // 添加引用 using Microsoft.AspNetCore.Authorization; namespace MvcCookieAuthSample.Controllers { public class AdminController : Controller { [Authorize] public IActionResult Index() { return View(); } } }using System;
startup.cs
using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; // 添加引用 using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authentication.Cookies; namespace MvcCookieAuthSample { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } 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) { services.Configure<CookiePolicyOptions>(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); // Addmvc之前AddAuthentication,AddCookie services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseCookiePolicy(); // UseMvc之前UseAuthentication,添加Middleware app.UseAuthentication(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); } } }using System;
再次访问https://localhost:5001/Admin,跳转到登陆界面https://localhost:5001/Account/Login?ReturnUrl=%2FAdmin
在Controllers文件夹新增AccountController.cs
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using MvcCookieAuthSample.Models; // 添加引用 using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using System.Security.Claims; namespace MvcCookieAuthSample.Controllers { [Authorize] public class AccountController : Controller { public IActionResult MakeLogin() { var claims = new List<Claim>() { new Claim(ClaimTypes.Name,"Mingson"), new Claim(ClaimTypes.Role,"admin") }; var claimIdentity = new ClaimsIdentity(claims,CookieAuthenticationDefaults.AuthenticationScheme); HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,new ClaimsPrincipal(claimIdentity)); return Ok(); } public IActionResult Logout() { HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); return Ok(); } } }
启动项目
登出:localhost:5000/account/logout
访问admin:localhost:5000/admin,跳转到account/login
登陆:localhost:5000/account/makelogin
再次访问admin:localhost:5000/admin,登陆成功访问admin
任务35:JWT 认证授权介绍
可在官网解密:https://jwt.io
任务36:应用Jwtbearer Authentication
dotnet watch rundotnet new webapi --name JwtAuthSample
打开postman调用
http://localhost:5000/api/values
ValuesController.cs
using Microsoft.AspNetCore.Authorization; // 添加特性 [Authorize] [Route("api/[controller]")] [ApiController] public class ValuesController : ControllerBase// 添加引用
新增一个Models文件夹,在文件夹中新增JwtSettings.cs
{ public class JwtSettings { // token颁发者 public string Issure{get;set;} // token使用的客户端 public string Audience{get;set;} // 加密Key public string SecretKey="hellokey"; } }namespace JwtAuthSample
appsettings.json
"Logging": { "LogLevel": { "Default": "Warning" } }, "AllowedHosts": "*", "JwtSettings":{ "Audience":"http://localhost:5000", "Issuer":"http://localhost:5000", "SecretKey":"Hello-key" } }{
Startup.cs
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; using System.Text; // 添加在services.AddMvc()之前 services.Configure<JwtSettings>(Configuration); var JwtSettings = new JwtSettings(); Configuration.Bind("JwtSettings",JwtSettings); // 认证MiddleWare配置 services.AddAuthentication(options=>{ options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) // Jwt配置 .AddJwtBearer(o=>{ o.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters{ ValidIssuer = JwtSettings.Issure, ValidAudience = JwtSettings.Audience, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtSettings.SecretKey))// 对称加密 }; }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); app.UseHttpsRedirection(); // 添加在app.UseMvc()之前 app.UseAuthentication();// 添加引用
dotnet watch run
postman调用
http://localhost:5000/api/values
返回401,未授权
任务37:生成 JWT Token
新建文件夹ViewModels,在文件夹中新建LoginViewModel.cs
namespace JwtAuthSample { public class LoginViewModel { [Required] public string User{get;set;} [Required] public string Password{get;set;} } }using ponentModel.DataAnnotations;
AuthorizeController.cs
using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; // 添加引用 using System.Security.Claims; using Microsoft.IdentityModel.Tokens; using Microsoft.Extensions.Options; using System.Text; using System.IdentityModel.Tokens.Jwt; namespace JwtAuthSample.Controllers { [Route("api/[controller]")] [ApiController] public class AuthorizeController : ControllerBase { private JwtSettings _jwtSettings; public AuthorizeController(IOptions<JwtSettings> _jwtSettingsAccesser) { _jwtSettings = _jwtSettingsAccesser.Value; } public IActionResult Token(LoginViewModel viewModel) { if (ModelState.IsValid) { if (!(viewModel.User == "mingson" && viewModel.Password == "123456")) { return BadRequest(); } var claims = new Claim[] { new Claim(ClaimTypes.Name, "mingson"), new Claim(ClaimTypes.Role, "admin") }; var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSettings.SecretKey));// 对称加密算法 var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); // VSCode安装扩展NuGet Package Manager // ctrl + shift + p // NuGet Package Manager:Add Pcakage // Microsoft.AspNetCore.Authentication.JwtBearer // 需要FQ才能添加 // 2.0.0 // 安装到csproj // 安装成功后csproj中出现<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="2.0.0" /> // dotnet restore var token = new JwtSecurityToken( _jwtSettings.Issure, _jwtSettings.Audience, claims, DateTime.Now, DateTime.Now.AddMinutes(30), creds); return Ok(new {token = new JwtSecurityTokenHandler().WriteToken(token)}); } return BadRequest(); } } }using System;
Startup.cs
//services.Configure<JwtSettings>(Configuration);// 获取不到JwtSettings配置 services.Configure<JwtSettings>(Configuration.GetSection("JwtSettings"));// 获取appsettings.json中的配置// 添加在services.AddMvc()之前
appsettings.json
"Logging": { "LogLevel": { "Default": "Warning" } }, "AllowedHosts": "*", "JwtSettings":{ "Audience":"http://localhost:5000", "Issuer":"http://localhost:5000", "SecretKey长度必须大于128bit=16字符":"", "SecretKey":"Hello-key.jessetalk" } }{
dotnet watch run
postman调用
http://localhost:5000/Authorize/Token
返回Token
加上token调用
http://localhost:5000/api/values
token可在官网解密:https://jwt.io
输入正确的SecretKey:Hello-key.jessetalk
任务38:JWT 设计解析及定制
新建文件MyTokenValidator.cs
using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; // 添加引用 using Microsoft.AspNetCore.Authentication.JwtBearer; using System.Security.Claims; using Microsoft.IdentityModel.Tokens; namespace JwtAuthSample { public class MyTokenValidator : ISecurityTokenValidator { bool ISecurityTokenValidator.CanValidateToken => true; int ISecurityTokenValidator.MaximumTokenSizeInBytes { get;set; } bool ISecurityTokenValidator.CanReadToken(string securityToken) { return true; } ClaimsPrincipal ISecurityTokenValidator.ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken) { validatedToken = null; var identity = new ClaimsIdentity(JwtBearerDefaults.AuthenticationScheme); if (securityToken == "abcdefg") { identity.AddClaim(new Claim("name", "mingson")); identity.AddClaim(new Claim("SuperAdminOnly", "true")); identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, "user")); } var principal = new ClaimsPrincipal(identity); return principal; } } }using System;
Startup.cs
services.AddAuthentication(options=>{ options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) // Jwt配置 .AddJwtBearer(o=>{ // o.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters{ //ValidIssuer = JwtSettings.Issure, //ValidAudience = JwtSettings.Audience, //IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtSettings.SecretKey))// 对称加密 // }; // 修改token来源 o.SecurityTokenValidators.Clear();// 一个包含验证的数组,先清除 o.SecurityTokenValidators.Add(new MyTokenValidator()); // 修改token验证方式 o.Events = new JwtBearerEvents(){ OnMessageReceived = context => { var token = context.Request.Headers["mytoken"]; context.Token = token.FirstOrDefault(); return pletedTask; } }; }); services.AddAuthorization(Options=>{ Options.AddPolicy("SuperAdminOnly", policy => policy.RequireClaim("SuperAdminOnly")); });// 认证MiddleWare配置
AuthorizeController.cs
// { //new Claim(ClaimTypes.Name, "mingson"), //new Claim(ClaimTypes.Role, "admin") // }; var claims = new Claim[] { new Claim(ClaimTypes.Name, "mingson"), new Claim(ClaimTypes.Role, "user"), new Claim("SuperAdminOnly", "true") };// var claims = new Claim[]
ValuesController.cs
[Authorize(Policy="SuperAdminOnly")]// [Authorize]// 添加标签
dotnet run
输入一个错误的mytoken,返回403 Forbidden,禁止访问
输入一个正确的mytoken,返回200 OK
任务39:Role以及Claims授权
Role授权
AuthorizeController.cs
{ new Claim(ClaimTypes.Name, "mingson"), new Claim(ClaimTypes.Role, "admin") };var claims = new Claim[]
ValuesController.cs
[Authorize(Roles="user")]
dotnet run
带着token访问,返回403 Forbidden,禁止访问
AuthorizeController.cs修改为user,可访问
{ new Claim(ClaimTypes.Name, "mingson"), new Claim(ClaimTypes.Role, "user") };var claims = new Claim[]
Claims授权
Startup.cs
services.AddAuthentication(options=>{ options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) // Jwt配置 .AddJwtBearer(o=>{ o.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters{ ValidIssuer = JwtSettings.Issure, ValidAudience = JwtSettings.Audience, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtSettings.SecretKey))// 对称加密 }; }); services.AddAuthorization(Options=>{ Options.AddPolicy("SuperAdminOnly", policy => policy.RequireClaim("SuperAdminOnly")); });// 认证MiddleWare配置
ValuesController.cs
[Authorize(Policy="SuperAdminOnly")]
AuthorizeController.cs
{ new Claim(ClaimTypes.Name, "mingson"), new Claim(ClaimTypes.Role, "user"), new Claim("SuperAdminOnly", "true") };var claims = new Claim[]
dotnet run
带着token访问,返回200 Ok
点“在看”给我一朵小黄花