zl程序教程

您现在的位置是:首页 >  后端

当前栏目

ASP.NET Core快速入门(第5章:认证与授权)

NetASPCore认证入门 快速 授权
2023-09-14 09:12:34 时间

引用网址:

https://blog.csdn.net/lixiaoer757/article/details/105302750?spm=1001.2101.3001.6650.3&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-3.pc_relevant_paycolumn_v3&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-3.pc_relevant_paycolumn_v3&utm_relevant_index=6

  • 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

  1.  
    using System;
  2.  
    using System.Collections.Generic;
  3.  
    using System.Diagnostics;
  4.  
    using System.Linq;
  5.  
    using System.Threading.Tasks;
  6.  
    using Microsoft.AspNetCore.Mvc;
  7.  
    using MvcCookieAuthSample.Models;
  8.  
     
  9.  
    namespace MvcCookieAuthSample.Controllers
  10.  
    {
  11.  
    public class AdminController : Controller
  12.  
    {
  13.  
    public IActionResult Index()
  14.  
    {
  15.  
    return View();
  16.  
    }
  17.  
    }
  18.  
    }

在Views文件夹新增Admin文件夹,在Admin文件夹新增Index.cshtml

  1.  
    @{
  2.  
    ViewData["Title"] = "Admin";
  3.  
    }
  4.  
    <h2>@ViewData["Title"]</h2>
  5.  
     
  6.  
    <p>Admin Page</p>

启动项目,浏览器访问https://localhost:5001/Admin

实际情况不应该直接让用户访问到Admin页面,所以应当跳转到登陆界面

AdminController.cs

  1.  
    using System;
  2.  
    using System.Collections.Generic;
  3.  
    using System.Diagnostics;
  4.  
    using System.Linq;
  5.  
    using System.Threading.Tasks;
  6.  
    using Microsoft.AspNetCore.Mvc;
  7.  
    using MvcCookieAuthSample.Models;
  8.  
    // 添加引用
  9.  
    using Microsoft.AspNetCore.Authorization;
  10.  
     
  11.  
    namespace MvcCookieAuthSample.Controllers
  12.  
    {
  13.  
    public class AdminController : Controller
  14.  
    {
  15.  
    [Authorize]
  16.  
    public IActionResult Index()
  17.  
    {
  18.  
    return View();
  19.  
    }
  20.  
    }
  21.  
    }

startup.cs

  1.  
    using System;
  2.  
    using System.Collections.Generic;
  3.  
    using System.Linq;
  4.  
    using System.Threading.Tasks;
  5.  
    using Microsoft.AspNetCore.Builder;
  6.  
    using Microsoft.AspNetCore.Hosting;
  7.  
    using Microsoft.AspNetCore.Http;
  8.  
    using Microsoft.AspNetCore.HttpsPolicy;
  9.  
    using Microsoft.AspNetCore.Mvc;
  10.  
    using Microsoft.Extensions.Configuration;
  11.  
    using Microsoft.Extensions.DependencyInjection;
  12.  
    // 添加引用
  13.  
    using Microsoft.AspNetCore.Authorization;
  14.  
    using Microsoft.AspNetCore.Authentication.Cookies;
  15.  
     
  16.  
    namespace MvcCookieAuthSample
  17.  
    {
  18.  
    public class Startup
  19.  
    {
  20.  
    public Startup(IConfiguration configuration)
  21.  
    {
  22.  
    Configuration = configuration;
  23.  
    }
  24.  
     
  25.  
    public IConfiguration Configuration { get; }
  26.  
     
  27.  
    // This method gets called by the runtime. Use this method to add services to the container.
  28.  
    public void ConfigureServices(IServiceCollection services)
  29.  
    {
  30.  
    services.Configure<CookiePolicyOptions>(options =>
  31.  
    {
  32.  
    // This lambda determines whether user consent for non-essential cookies is needed for a given request.
  33.  
    options.CheckConsentNeeded = context => true;
  34.  
    options.MinimumSameSitePolicy = SameSiteMode.None;
  35.  
    });
  36.  
     
  37.  
    // Addmvc之前AddAuthentication,AddCookie
  38.  
    services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
  39.  
    .AddCookie();
  40.  
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
  41.  
    }
  42.  
     
  43.  
    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
  44.  
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  45.  
    {
  46.  
    if (env.IsDevelopment())
  47.  
    {
  48.  
    app.UseDeveloperExceptionPage();
  49.  
    }
  50.  
    else
  51.  
    {
  52.  
    app.UseExceptionHandler("/Home/Error");
  53.  
    app.UseHsts();
  54.  
    }
  55.  
     
  56.  
    app.UseHttpsRedirection();
  57.  
    app.UseStaticFiles();
  58.  
    app.UseCookiePolicy();
  59.  
     
  60.  
    // UseMvc之前UseAuthentication,添加Middleware
  61.  
    app.UseAuthentication();
  62.  
    app.UseMvc(routes =>
  63.  
    {
  64.  
    routes.MapRoute(
  65.  
    name: "default",
  66.  
    template: "{controller=Home}/{action=Index}/{id?}");
  67.  
    });
  68.  
    }
  69.  
    }
  70.  
    }

再次访问https://localhost:5001/Admin,跳转到登陆界面https://localhost:5001/Account/Login?ReturnUrl=%2FAdmin

在Controllers文件夹新增AccountController.cs

  1.  
    using System;
  2.  
    using System.Collections.Generic;
  3.  
    using System.Diagnostics;
  4.  
    using System.Linq;
  5.  
    using System.Threading.Tasks;
  6.  
    using Microsoft.AspNetCore.Mvc;
  7.  
    using MvcCookieAuthSample.Models;
  8.  
    // 添加引用
  9.  
    using Microsoft.AspNetCore.Authorization;
  10.  
    using Microsoft.AspNetCore.Authentication;
  11.  
    using Microsoft.AspNetCore.Authentication.Cookies;
  12.  
    using System.Security.Claims;
  13.  
     
  14.  
    namespace MvcCookieAuthSample.Controllers
  15.  
    {
  16.  
    [Authorize]
  17.  
    public class AccountController : Controller
  18.  
    {
  19.  
    public IActionResult MakeLogin()
  20.  
    {
  21.  
    var claims = new List<Claim>()
  22.  
    {
  23.  
    new Claim(ClaimTypes.Name,"Mingson"),
  24.  
    new Claim(ClaimTypes.Role,"admin")
  25.  
    };
  26.  
     
  27.  
    var claimIdentity = new ClaimsIdentity(claims,CookieAuthenticationDefaults.AuthenticationScheme);
  28.  
     
  29.  
    HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,new ClaimsPrincipal(claimIdentity));
  30.  
     
  31.  
    return Ok();
  32.  
    }
  33.  
     
  34.  
    public IActionResult Logout()
  35.  
    {
  36.  
    HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
  37.  
     
  38.  
    return Ok();
  39.  
    }
  40.  
    }
  41.  
    }

启动项目

登出: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

  1.  
    dotnet new webapi --name JwtAuthSample
  2.  
    dotnet watch run

打开postman调用
http://localhost:5000/api/values

ValuesController.cs

  1.  
    // 添加引用
  2.  
    using Microsoft.AspNetCore.Authorization;
  3.  
     
  4.  
    // 添加特性
  5.  
    [Authorize]
  6.  
    [Route("api/[controller]")]
  7.  
    [ApiController]
  8.  
    public class ValuesController : ControllerBase

新增一个Models文件夹,在文件夹中新增JwtSettings.cs

  1.  
    namespace JwtAuthSample
  2.  
    {
  3.  
    public class JwtSettings
  4.  
    {
  5.  
    // token颁发者
  6.  
    public string Issure{get;set;}
  7.  
    // token使用的客户端
  8.  
    public string Audience{get;set;}
  9.  
    // 加密Key
  10.  
    public string SecretKey="hellokey";
  11.  
    }
  12.  
    }

appsettings.json

  1.  
    {
  2.  
    "Logging": {
  3.  
    "LogLevel": {
  4.  
    "Default": "Warning"
  5.  
    }
  6.  
    },
  7.  
    "AllowedHosts": "*",
  8.  
    "JwtSettings":{
  9.  
    "Audience":"http://localhost:5000",
  10.  
    "Issuer":"http://localhost:5000",
  11.  
    "SecretKey":"Hello-key"
  12.  
    }
  13.  
    }

Startup.cs

  1.  
    // 添加引用
  2.  
    using Microsoft.AspNetCore.Authentication.JwtBearer;
  3.  
    using Microsoft.IdentityModel.Tokens;
  4.  
    using System.Text;
  5.  
     
  6.  
    // 添加在services.AddMvc()之前
  7.  
    services.Configure<JwtSettings>(Configuration);
  8.  
    var JwtSettings = new JwtSettings();
  9.  
    Configuration.Bind("JwtSettings",JwtSettings);
  10.  
    // 认证MiddleWare配置
  11.  
    services.AddAuthentication(options=>{
  12.  
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
  13.  
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
  14.  
    })
  15.  
    // Jwt配置
  16.  
    .AddJwtBearer(o=>{
  17.  
    o.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters{
  18.  
    ValidIssuer = JwtSettings.Issure,
  19.  
    ValidAudience = JwtSettings.Audience,
  20.  
    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtSettings.SecretKey))// 对称加密
  21.  
    };
  22.  
    });
  23.  
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
  24.  
     
  25.  
    app.UseHttpsRedirection();
  26.  
    // 添加在app.UseMvc()之前
  27.  
    app.UseAuthentication();
dotnet watch run

postman调用
http://localhost:5000/api/values
返回401,未授权

任务37:生成 JWT Token

新建文件夹ViewModels,在文件夹中新建LoginViewModel.cs

  1.  
    using System.ComponentModel.DataAnnotations;
  2.  
     
  3.  
    namespace JwtAuthSample
  4.  
    {
  5.  
    public class LoginViewModel
  6.  
    {
  7.  
    [Required]
  8.  
    public string User{get;set;}
  9.  
    [Required]
  10.  
    public string Password{get;set;}
  11.  
    }
  12.  
    }

AuthorizeController.cs

  1.  
    using System;
  2.  
    using System.Collections.Generic;
  3.  
    using System.Linq;
  4.  
    using System.Threading.Tasks;
  5.  
    using Microsoft.AspNetCore.Mvc;
  6.  
    // 添加引用
  7.  
    using System.Security.Claims;
  8.  
    using Microsoft.IdentityModel.Tokens;
  9.  
    using Microsoft.Extensions.Options;
  10.  
    using System.Text;
  11.  
    using System.IdentityModel.Tokens.Jwt;
  12.  
     
  13.  
    namespace JwtAuthSample.Controllers
  14.  
    {
  15.  
    [Route("api/[controller]")]
  16.  
    [ApiController]
  17.  
    public class AuthorizeController : ControllerBase
  18.  
    {
  19.  
    private JwtSettings _jwtSettings;
  20.  
     
  21.  
    public AuthorizeController(IOptions<JwtSettings> _jwtSettingsAccesser)
  22.  
    {
  23.  
    _jwtSettings = _jwtSettingsAccesser.Value;
  24.  
    }
  25.  
     
  26.  
    public IActionResult Token(LoginViewModel viewModel)
  27.  
    {
  28.  
    if (ModelState.IsValid)
  29.  
    {
  30.  
    if (!(viewModel.User == "mingson" && viewModel.Password == "123456"))
  31.  
    {
  32.  
    return BadRequest();
  33.  
    }
  34.  
     
  35.  
    var claims = new Claim[]
  36.  
    {
  37.  
    new Claim(ClaimTypes.Name, "mingson"),
  38.  
    new Claim(ClaimTypes.Role, "admin")
  39.  
    };
  40.  
     
  41.  
    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSettings.SecretKey));// 对称加密算法
  42.  
    var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
  43.  
     
  44.  
    // VSCode安装扩展NuGet Package Manager
  45.  
    // ctrl + shift + p
  46.  
    // NuGet Package Manager:Add Pcakage
  47.  
    // Microsoft.AspNetCore.Authentication.JwtBearer
  48.  
    // 需要FQ才能添加
  49.  
    // 2.0.0
  50.  
    // 安装到csproj
  51.  
    // 安装成功后csproj中出现<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="2.0.0" />
  52.  
    // dotnet restore
  53.  
     
  54.  
    var token = new JwtSecurityToken(
  55.  
    _jwtSettings.Issure,
  56.  
    _jwtSettings.Audience,
  57.  
    claims,
  58.  
    DateTime.Now,
  59.  
    DateTime.Now.AddMinutes(30),
  60.  
    creds);
  61.  
     
  62.  
    return Ok(new {token = new JwtSecurityTokenHandler().WriteToken(token)});
  63.  
    }
  64.  
     
  65.  
    return BadRequest();
  66.  
    }
  67.  
    }
  68.  
    }

Startup.cs

  1.  
    // 添加在services.AddMvc()之前
  2.  
    //services.Configure<JwtSettings>(Configuration);// 获取不到JwtSettings配置
  3.  
    services.Configure<JwtSettings>(Configuration.GetSection("JwtSettings"));// 获取appsettings.json中的配置

appsettings.json

  1.  
    {
  2.  
    "Logging": {
  3.  
    "LogLevel": {
  4.  
    "Default": "Warning"
  5.  
    }
  6.  
    },
  7.  
    "AllowedHosts": "*",
  8.  
    "JwtSettings":{
  9.  
    "Audience":"http://localhost:5000",
  10.  
    "Issuer":"http://localhost:5000",
  11.  
    "SecretKey长度必须大于128bit=16字符":"",
  12.  
    "SecretKey":"Hello-key.jessetalk"
  13.  
    }
  14.  
    }
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

  1.  
    using System;
  2.  
    using System.Collections.Generic;
  3.  
    using System.IO;
  4.  
    using System.Linq;
  5.  
    using System.Threading.Tasks;
  6.  
    using Microsoft.AspNetCore;
  7.  
    using Microsoft.AspNetCore.Hosting;
  8.  
    using Microsoft.Extensions.Configuration;
  9.  
    using Microsoft.Extensions.Logging;
  10.  
    // 添加引用
  11.  
    using Microsoft.AspNetCore.Authentication.JwtBearer;
  12.  
    using System.Security.Claims;
  13.  
    using Microsoft.IdentityModel.Tokens;
  14.  
     
  15.  
    namespace JwtAuthSample
  16.  
    {
  17.  
    public class MyTokenValidator : ISecurityTokenValidator
  18.  
    {
  19.  
    bool ISecurityTokenValidator.CanValidateToken => true;
  20.  
     
  21.  
    int ISecurityTokenValidator.MaximumTokenSizeInBytes { get;set; }
  22.  
     
  23.  
    bool ISecurityTokenValidator.CanReadToken(string securityToken)
  24.  
    {
  25.  
    return true;
  26.  
    }
  27.  
     
  28.  
    ClaimsPrincipal ISecurityTokenValidator.ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken)
  29.  
    {
  30.  
    validatedToken = null;
  31.  
    var identity = new ClaimsIdentity(JwtBearerDefaults.AuthenticationScheme);
  32.  
     
  33.  
    if (securityToken == "abcdefg")
  34.  
    {
  35.  
    identity.AddClaim(new Claim("name", "mingson"));
  36.  
    identity.AddClaim(new Claim("SuperAdminOnly", "true"));
  37.  
    identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, "user"));
  38.  
    }
  39.  
     
  40.  
    var principal = new ClaimsPrincipal(identity);
  41.  
     
  42.  
    return principal;
  43.  
    }
  44.  
    }
  45.  
    }

Startup.cs

  1.  
    // 认证MiddleWare配置
  2.  
    services.AddAuthentication(options=>{
  3.  
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
  4.  
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
  5.  
    })
  6.  
    // Jwt配置
  7.  
    .AddJwtBearer(o=>{
  8.  
    // o.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters{
  9.  
    // ValidIssuer = JwtSettings.Issure,
  10.  
    // ValidAudience = JwtSettings.Audience,
  11.  
    // IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtSettings.SecretKey))// 对称加密
  12.  
    // };
  13.  
     
  14.  
    // 修改token来源
  15.  
    o.SecurityTokenValidators.Clear();// 一个包含验证的数组,先清除
  16.  
    o.SecurityTokenValidators.Add(new MyTokenValidator());
  17.  
     
  18.  
    // 修改token验证方式
  19.  
    o.Events = new JwtBearerEvents(){
  20.  
    OnMessageReceived = context => {
  21.  
    var token = context.Request.Headers["mytoken"];
  22.  
    context.Token = token.FirstOrDefault();
  23.  
    return Task.CompletedTask;
  24.  
    }
  25.  
    };
  26.  
    });
  27.  
     
  28.  
    services.AddAuthorization(Options=>{
  29.  
    Options.AddPolicy("SuperAdminOnly", policy => policy.RequireClaim("SuperAdminOnly"));
  30.  
    });

AuthorizeController.cs

  1.  
    // var claims = new Claim[]
  2.  
    // {
  3.  
    // new Claim(ClaimTypes.Name, "mingson"),
  4.  
    // new Claim(ClaimTypes.Role, "admin")
  5.  
    // };
  6.  
    var claims = new Claim[]
  7.  
    {
  8.  
    new Claim(ClaimTypes.Name, "mingson"),
  9.  
    new Claim(ClaimTypes.Role, "user"),
  10.  
    new Claim("SuperAdminOnly", "true")
  11.  
    };

ValuesController.cs

  1.  
    // [Authorize]// 添加标签
  2.  
    [Authorize(Policy="SuperAdminOnly")]
dotnet run

输入一个错误的mytoken,返回403 Forbidden,禁止访问

输入一个正确的mytoken,返回200 OK

任务39:Role以及Claims授权

Role授权

AuthorizeController.cs

  1.  
    var claims = new Claim[]
  2.  
    {
  3.  
    new Claim(ClaimTypes.Name, "mingson"),
  4.  
    new Claim(ClaimTypes.Role, "admin")
  5.  
    };

ValuesController.cs

    [Authorize(Roles="user")]
dotnet run

带着token访问,返回403 Forbidden,禁止访问

AuthorizeController.cs修改为user,可访问

  1.  
    var claims = new Claim[]
  2.  
    {
  3.  
    new Claim(ClaimTypes.Name, "mingson"),
  4.  
    new Claim(ClaimTypes.Role, "user")
  5.  
    };

Claims授权

Startup.cs

  1.  
    // 认证MiddleWare配置
  2.  
    services.AddAuthentication(options=>{
  3.  
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
  4.  
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
  5.  
    })
  6.  
    // Jwt配置
  7.  
    .AddJwtBearer(o=>{
  8.  
    o.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters{
  9.  
    ValidIssuer = JwtSettings.Issure,
  10.  
    ValidAudience = JwtSettings.Audience,
  11.  
    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtSettings.SecretKey))// 对称加密
  12.  
    };
  13.  
    });
  14.  
     
  15.  
    services.AddAuthorization(Options=>{
  16.  
    Options.AddPolicy("SuperAdminOnly", policy => policy.RequireClaim("SuperAdminOnly"));
  17.  
    });

ValuesController.cs

    [Authorize(Policy="SuperAdminOnly")]

AuthorizeController.cs

  1.  
    var claims = new Claim[]
  2.  
    {
  3.  
    new Claim(ClaimTypes.Name, "mingson"),
  4.  
    new Claim(ClaimTypes.Role, "user"),
  5.  
    new Claim("SuperAdminOnly", "true")
  6.  
    };
dotnet run

带着token访问,返回200 Ok