.NET鉴权授权


gitee仓储地址
---------------------------------2022-03-30分界线-----------------------------------
一种是cookie鉴权授权,一种是token鉴权授权,先把权限授予它,才能鉴定它的权限是否符合我的权限校验

一.鉴权cookie方式

1.在program中添加鉴权授权中间件
2.在控制器某个方法上添加鉴权特性
3.在program中添加

点击查看代码
builder.Services.AddAuthentication("Cookies").AddCookie(o =>
{
    o.LoginPath = "/Login/NoLogin";//鉴权不通过就跳到以下路径
});

4.添加一个控制器LoginController

点击查看代码
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace AuthDemo.Api.Controllers
{
    [Route("[controller]/[action]")]
    [ApiController]
    public class LoginController : ControllerBase
    {
        [HttpGet]
        public async Task NoLoginAsync()
        {
            return "您还没有登录!";
        }
    }
}

5.在login控制器中添加一个方法

点击查看代码
        [HttpPost]
        public async Task LoginSucess(string userName,string password)
        {
            //判断当前的用户名和密码
            if (userName=="Ace"&&password=="666")
            {
                //如果符合当前条件,则实例化一个实体,保存当前数据
                ClaimsIdentity claimsIdentity = new ClaimsIdentity("Ctm");
                claimsIdentity.AddClaim(new ( ClaimTypes.Name, userName));
                claimsIdentity.AddClaim(new(ClaimTypes.NameIdentifier, "1"));
                //cookies与program添加的鉴权架构一致
                await HttpContext.SignInAsync("Cookies",new ClaimsPrincipal(claimsIdentity));
                return "登录成功!";
            }
            else
            {
                return "登录失败!";
            }
        }

二.自定义token鉴权 自定义鉴权策略

1.新增一个文件夹CtmAuthentication,新增一个类文件TokenAuthenticationHandler,继承于IAuthenticationHandler接口,实现接口
2.TokenAuthenticationHandler类里的代码如下

点击查看代码
using Microsoft.AspNetCore.Authentication;
using System.Security.Claims;

namespace AuthDemo.Api.CtmAuthentication
{
    public class TokenAuthenticationHandler : IAuthenticationHandler
    {
        private AuthenticationScheme _scheme;
        private HttpContext _httpContext;
        /// 
        /// 鉴权初始化
        /// 
        /// 鉴权架构名称
        /// HttpContext
        /// 
        public async Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
        {
            _scheme = scheme;
            _httpContext = context;
        }
        /// 
        /// 鉴权
        /// 
        /// 
        public async Task AuthenticateAsync()
        {
            string token = _httpContext.Request.Headers["Authorization"];
            if (token=="jaden")
            {
                ClaimsIdentity claimsIdentity = new("ctm");
                claimsIdentity.AddClaims(new List
                {
                    new Claim(ClaimTypes.Name,"jaden"),
                    new Claim(ClaimTypes.NameIdentifier,"6")
                });
                var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
                return await Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(claimsPrincipal,_scheme.Name)));
            }
            return await Task.FromResult(AuthenticateResult.Fail("token错误,请重新登录"));
        }
        /// 
        /// 未登录操作
        /// 
        /// 
        /// 
        public async Task ChallengeAsync(AuthenticationProperties? properties)
        {
            _httpContext.Response.Redirect("/Login/NoLogin");
        }
        /// 
        /// 鉴权失败的操作
        /// 
        /// 
        /// 
        public async Task ForbidAsync(AuthenticationProperties? properties)
        {
            _httpContext.Response.StatusCode = 403;
        }

        
    }
}


3.修改program中的代码,如下

点击查看代码
using AuthDemo.Api.CtmAuthentication;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
#region 注册鉴权架构
//cookie
//builder.Services.AddAuthentication("Cookies").AddCookie(o =>
//{
//    o.LoginPath = "/Login/NoLogin";//鉴权不通过就跳到以下路径
//});
//自定义token验证
builder.Services.AddAuthentication(op =>
{
    //把自定义的鉴权方案添加到鉴权架构中
    //token是个名字,下面的代表Scheme name方案名字
    op.AddScheme("token","ctmToken");
    op.DefaultAuthenticateScheme = "token";
    op.DefaultChallengeScheme = "token";
    op.DefaultForbidScheme = "token";
});
#endregion
var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}
//鉴权
app.UseAuthentication();
//授权
app.UseAuthorization();

app.MapControllers();

app.Run();


4.然后用postman或者apipost中测试,token中输入一些字符,发现token中存在这些字符,下面让我们继续改造,其实token就是存在我们发送请求的head文件里的

三.授权策略

1.在program中的鉴权策略下添加如下代码

点击查看代码
/*
 自定义授权时,
 控制器上加的Authorize授权,
 后面记得加当前名称'MyPolicy',
 才能匹配到当前的授权方案(一般配置为常量)
 */
//自定义授权
builder.Services.AddAuthorization(op =>
{
    //判断当前的授权方案的
    op.AddPolicy(AuthorizationConts.MyPolicy, p => p.RequireClaim(ClaimTypes.NameIdentifier, "6"));
});

新增一个常量类AuthorizationConts,存放一个常量MyPolicy,值也是这个
2.在WeatherForecastController控制器中的Authorize鉴权特性中添加常量,代表的意思是鉴权时匹配我们自定义的鉴权
代码如下:

点击查看代码
using AuthDemo.Api.Consts;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace AuthDemo.Api.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

        private readonly ILogger _logger;

        public WeatherForecastController(ILogger logger)
        {
            _logger = logger;
        }
        [Authorize(AuthorizationConts.MyPolicy)]
        [HttpGet(Name = "GetWeatherForecast")]
        public IEnumerable Get()
        {
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }
}

经过以上改造就完成了自定义授权

四.授权断言

1.什么叫授权断言?
首先判定你当前用户有没有这个身份,比如说你的name有没有,有我则继续判断匹配不匹配,没有则直接报错
2.program中的自定义授权改为如下代码

点击查看代码
//自定义授权
builder.Services.AddAuthorization(op =>
{
    //判断当前的授权方案的
    //op.AddPolicy(AuthorizationConts.MyPolicy, p => p.RequireClaim(ClaimTypes.NameIdentifier, "6"));

    //授权断言
    //先判断user的类型是不是NameIdentifier,如果是,则判断当前值匹配不匹配
    //如果不是则直接报错
    op.AddPolicy(AuthorizationConts.MyPolicy,p=>
    p.RequireAssertion(
        a=>a.User.HasClaim(c=>c.Type==ClaimTypes.NameIdentifier) &&
        a.User.Claims.First(c=>c.Type.Equals(ClaimTypes.NameIdentifier)).Value=="6"
    ));
});

---------------------------------2022-03-31分界线-----------------------------------

五.自定义授权与双授权策略(多scheme)

持续更新