• .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<string> NoLoginAsync()
            {
                return "您还没有登录!";
            }
        }
    }
    
    

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

    点击查看代码
            [HttpPost]
            public async Task<string> 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;
            /// <summary>
            /// 鉴权初始化
            /// </summary>
            /// <param name="scheme">鉴权架构名称</param>
            /// <param name="context">HttpContext</param>
            /// <returns></returns>
            public async Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
            {
                _scheme = scheme;
                _httpContext = context;
            }
            /// <summary>
            /// 鉴权
            /// </summary>
            /// <returns></returns>
            public async Task<AuthenticateResult> AuthenticateAsync()
            {
                string token = _httpContext.Request.Headers["Authorization"];
                if (token=="jaden")
                {
                    ClaimsIdentity claimsIdentity = new("ctm");
                    claimsIdentity.AddClaims(new List<Claim>
                    {
                        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错误,请重新登录"));
            }
            /// <summary>
            /// 未登录操作
            /// </summary>
            /// <param name="properties"></param>
            /// <returns></returns>
            public async Task ChallengeAsync(AuthenticationProperties? properties)
            {
                _httpContext.Response.Redirect("/Login/NoLogin");
            }
            /// <summary>
            /// 鉴权失败的操作
            /// </summary>
            /// <param name="properties"></param>
            /// <returns></returns>
            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<TokenAuthenticationHandler>("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<WeatherForecastController> _logger;
    
            public WeatherForecastController(ILogger<WeatherForecastController> logger)
            {
                _logger = logger;
            }
            [Authorize(AuthorizationConts.MyPolicy)]
            [HttpGet(Name = "GetWeatherForecast")]
            public IEnumerable<WeatherForecast> 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分界线-----------------------------------
    ---------------------------------2022-04-02分界线-----------------------------------

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

    合起来的方案
    1.创建一个CtmAuthorizations文件夹,创建一个MyAuthorizationHandler类,
    MyAuthorizationHandler继承于AuthorizationHandler泛型抽象类
    代码如下

    点击查看代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Security.Claims;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Authorization;
    
    namespace AuthDemo.Api.CtmAuthorizations
    {
    	public class MyAuthorizationHandler : AuthorizationHandler<MyAuthorizationHandler>, IAuthorizationRequirement
    	{
    		private readonly string userId;
    
    		public MyAuthorizationHandler(string userId)
    		{
    			this.userId = userId;
    		}
    		/// <summary>
    		/// 重写 AuthorizationHandler 父类中的 HandleRequirementAsync 方法
    		/// </summary>
    		/// <param name="context"></param>
    		/// <param name="requirement"></param>
    		/// <returns></returns>
    		protected override async Task HandleRequirementAsync(
    			AuthorizationHandlerContext context,
    			MyAuthorizationRequirement requirement)
    		{
    			if (context.User.HasClaim(c => c.Type == ClaimTypes.NameIdentifier)
    			&& context.User.Claims.First(c => c.Type.Equals(ClaimTypes.NameIdentifier)).Value == userId)
    			{
    				context.Succeed(requirement);
    			}
    		}
    	}
    }
    

    2.program中的代码为:

    点击查看代码
    using System.Security.Claims;
    using AuthDemo.Api.Consts;
    using AuthDemo.Api.CtmAuthentication;
    using AuthDemo.Api.CtmAuthorizations;
    
    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<TokenAuthenticationHandler>("token", "ctmToken");
    	op.DefaultAuthenticateScheme = "token";
    	op.DefaultChallengeScheme = "token";
    	op.DefaultForbidScheme = "token";
    });
    /*
     自定义授权时,
     控制器上加的Authorize授权,
     后面记得加当前名称'MyPolicy',
     才能匹配到当前的授权方案(一般配置为常量)
     */
    //自定义授权
    // 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"
    // 	));
    // });
    
    //自定义授权
    builder.Services.AddAuthorization(op =>
    {
    	op.AddPolicy(AuthorizationConts.MyPolicy, p => p.Requirements.Add(new MyAuthorizationHandler("6")));
    });
    #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();
    
    

    ---------------------------------2022-04-04分界线-----------------------------------
    分开的方案
    在使用双授权方案时,这两个策略必须同事通过才可以,否则授权失败
    双授权方案与单授权方案基本一致,唯一不一样的就是注册policy的时候,注册两次,控制器的鉴权验证也写两次,将MyAuthorizationHandler复制一次即可,
    将自定义授权方式换了一个

    六.多鉴权架构

    下午写这段
    多鉴权架构下,只要成功一个,那么鉴权即认为成功
    在控制器下加这段,并且打开program中cookie鉴权的注释
    [Authorize(AuthenticationSchemes = $"token,Cookies")]
    持续更新

    七.授权和鉴权的绑定

    1.修改program中的代码

    点击查看代码
    using System.Security.Claims;
    using AuthDemo.Api.Consts;
    using AuthDemo.Api.CtmAuthentication;
    using AuthDemo.Api.CtmAuthorizations;
    
    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<TokenAuthenticationHandler>("token", "ctmToken");
    	// op.DefaultAuthenticateScheme = "token";
    	op.DefaultChallengeScheme = "token";
    	op.DefaultForbidScheme = "token";
    });
    /*
     自定义授权时,
     控制器上加的Authorize授权,
     后面记得加当前名称'MyPolicy',
     才能匹配到当前的授权方案(一般配置为常量)
     */
    //自定义授权
    // 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"
    // 	));
    // });
    
    //自定义授权
    builder.Services.AddAuthorization(op =>
    {
    	op.AddPolicy(AuthorizationConts.MyPolicy,
    	p => p.AddAuthenticationSchemes("token").Requirements.Add(new MyAuthorizationHandler("6")));
    	// op.AddPolicy(AuthorizationConts.MyPolicy, p => p.Requirements.Add(new MyAuthorizationHandler("6")));
    	op.AddPolicy(AuthorizationConts.MyPolicy2, p => p.AddAuthenticationSchemes("Cookies").Requirements.Add(new MyAuthorizationHandler2("Ace")));
    });
    #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();
    
    

    将poliy中添加schemes,为token,并注释默认scheme即可
    2.注意scheme策略名称需要一直,鉴权和授权策略名称是一致的
    修改控制器中的代码,输入你要鉴权的方案

    点击查看代码
                    [Authorize(AuthorizationConts.MyPolicy2)]
    		public IEnumerable<WeatherForecast> 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();
    		}
    

    这里我用的是mypolicy2的鉴权方案,当你用哪个鉴权方案时,它就用哪个鉴权,并且对它进行授权
    --------------------------------------2022-04-05分界线--------------------------------------------

    八.session授权绑定鉴权

    session本身是个字典,并且是个作用域生命周期,session存在缓存中,并可以设置过期时间
    key:sessionId,value:Dictonary<sessionKey,SessionValue>(字符串字典)
    1.首先要想实现seesion自定义实现,必须用到缓存(MemoryCache),并且新增一个文件夹Core,新增一个MySession及IMySession接口,MySession继承于IMySession
    program类代码如下:

    点击查看代码
    using System.Security.Claims;
    using AuthDemo.Api.Consts;
    using AuthDemo.Api.Core;
    using AuthDemo.Api.CtmAuthentication;
    using AuthDemo.Api.CtmAuthorizations;
    using Microsoft.Extensions.Caching.Memory;
    
    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();
    // builder.Services.AddSingleton<IMemoryCache, MemoryCache>();
    builder.Services.AddMemoryCache();
    builder.Services.AddScoped<IMySession, MySession>();
    #region 注册鉴权架构
    //cookie
    // builder.Services.AddAuthentication("Cookies").AddCookie(o =>
    // {
    // 	o.LoginPath = "/Login/NoLogin";//鉴权不通过就跳到以下路径
    // });
    
    //自定义token验证 鉴权策略
    builder.Services.AddAuthentication(op =>
    {
    	//把自定义的鉴权方案添加到鉴权架构中
    	//token是个名字,下面的代表Scheme name方案名字
    
    	op.AddScheme<SessionAuthenicationHandler>("session", "ctmSession");
    	op.DefaultAuthenticateScheme = "session";
    	op.DefaultChallengeScheme = "session";
    	op.DefaultForbidScheme = "session";
    });
    /*
     自定义授权时,
     控制器上加的Authorize授权,
     后面记得加当前名称'MyPolicy',
     才能匹配到当前的授权方案(一般配置为常量)
     */
    //自定义授权
    // 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"
    // 	));
    // });
    
    //自定义授权
    // builder.Services.AddAuthorization(op =>
    // {
    // 	op.AddPolicy(AuthorizationConts.MyPolicy,
    // 	p => p.AddAuthenticationSchemes("token").Requirements.Add(new MyAuthorizationHandler("6")));
    // 	// op.AddPolicy(AuthorizationConts.MyPolicy, p => p.Requirements.Add(new MyAuthorizationHandler("6")));
    // 	op.AddPolicy(AuthorizationConts.MyPolicy2, p => p.AddAuthenticationSchemes("Cookies").Requirements.Add(new MyAuthorizationHandler2("Ace")));
    // });
    #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();
    
    

    具体的思路,在代码中已经详细标明了
    2.MySession和IMySession接口代码如下:

    IMySession
    using Microsoft.Extensions.Caching.Memory;
    
    namespace AuthDemo.Api.Core
    {
    	public interface IMySession
    	{
    		string GetString(string key);
    		void InitSession(string sessionId, IMemoryCache memoryCache);
    		void SetString(string key, string value);
    	}
    }
    
    MySession
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.Extensions.Caching.Memory;
    
    namespace AuthDemo.Api.Core
    {
    
    	public class MySession : IMySession
    	{
    		/*
    			1.session是这样去保存数据的,每个用户都有一个sessionId,
    			2.根据sessionId去获取用户的数据
    			3.每个用户的数据保存在内存中,这样可以让session更短(就是浏览器的缓存中)
    			4.sessionId是唯一的,每个用户的sessionId是不一样的
    			5.sessionId是在第一次访问的时候生成的,第一次访问后,sessionId就会被保存在cookie中
    			6.所以我们需要在我们设计的session类中,定义一个私有sessionId,并定义一个缓存
    			7.这样在初始化Session的时候,将初始化Session的方法调用一下,把SessionId和缓存传进去
    			8.在获取数据的时候,根据sessionId去缓存中获取数据
    			9.在设置数据的时候,根据sessionId去缓存中设置数据
    		*/
    		private string sessionId;
    		private IMemoryCache memoryCache;
    		/// <summary>
    		/// 初始化Session,在鉴权验证方法中被调用
    		/// </summary>
    		/// <param name="sessionId"></param>
    		/// <param name="memoryCache"></param>
    		public void InitSession(string sessionId, IMemoryCache memoryCache)
    		{
    			this.memoryCache = memoryCache;
    			this.sessionId = sessionId;
    
    		}
    		/// <summary>
    		/// 通过key获取存储的值
    		/// </summary>
    		/// <param name="key"></param>
    		/// <returns></returns>
    		public string GetString(string key)
    		{
    			// 获取SeesionId 并根据SeesionId拿到当前用户存储的键值对
    			if (memoryCache.TryGetValue(sessionId, out Dictionary<string, string> dic))
    			{
    				return dic[key];
    			}
    			else
    			{
    				return default;
    			}
    
    		}
    
    		public void SetString(string key, string value)
    		{
    			// 获取SeesionId 并根据SeesionId拿到当前用户存储的键值对
    			if (memoryCache.TryGetValue(sessionId, out Dictionary<string, string> dic))
    			{
    				dic[key] = value;
    			}
    		}
    	}
    }
    

    3.SessionAuthenicationHandler代码如下:

    SessionAuthenicationHandler
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Security.Claims;
    using System.Threading.Tasks;
    using AuthDemo.Api.Core;
    using Microsoft.AspNetCore.Authentication;
    using Microsoft.Extensions.Caching.Memory;
    
    namespace AuthDemo.Api.CtmAuthentication
    {
    	public class SessionAuthenicationHandler : IAuthenticationHandler
    	{
    		/// <summary>
    		/// 定义一个缓存
    		/// </summary>
    		private readonly IMemoryCache _cache;
    		/// <summary>
    		/// 定义一个自定义的Session
    		/// </summary>
    		private readonly IMySession _session;
    		/// <summary>
    		/// 定义一个SessionId
    		/// </summary>
    		private string _sessionId;
    		/// <summary>
    		/// 定义上下文
    		/// </summary>
    		private HttpContext _context;
    		/// <summary>
    		/// 定义鉴权策略
    		/// </summary>
    		public AuthenticationScheme _scheme;
    		/// <summary>
    		/// 构造函数传入缓存,及session
    		/// </summary>
    		/// <param name="cache"></param>
    		/// <param name="session"></param>
    		public SessionAuthenicationHandler(IMemoryCache cache, IMySession session)
    		{
    			this._session = session;
    			this._cache = cache;
    		}
    		/// <summary>
    		///
    		/// </summary>
    		/// <param name="scheme"></param>
    		/// <param name="context"></param>
    		/// <returns></returns>
    		public async Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
    		{
    			//1.初始化时将策略赋值,将上下文赋值
    			this._scheme = scheme;
    			this._context = context;
    			//从上下文中的cookie取值,没有则创建一个
    			//判断当前缓存没有seesionid并且实际的数据也没有,则创建一个新的sessionid
    			if (!TryGetSession(out string id) || !_cache.TryGetValue(_sessionId, out Dictionary<string, string> value))
    			{
    				//创建一个sessionid,为guid
    				var sessionId = Guid.NewGuid().ToString();
    				_sessionId = sessionId;
    				//将上下文中的返回值的cookie,设置一个sessionid
    				_context.Response.Cookies.Append(".AspNetCore.Session", sessionId);
    				//将sessionid当作键值,将空的字典当作值,并设置过期时间
    				_cache.Set<Dictionary<string, string>>(sessionId, new Dictionary<string, string>(), TimeSpan.FromMinutes(20));
    			}
    		}
    		/// <summary>
    		/// 从上下文中的cookie中取值,输出sessionId
    		/// 将sesionid赋值到当前私有变量sessionId中,
    		/// 如果能获取到值则返回true,否则返回false
    		/// </summary>
    		/// <param name="sessionId"></param>
    		/// <returns></returns>
    		private bool TryGetSession(out string sessionId)
    		{
    			var hasSession = _context.Request.Cookies.TryGetValue(".AspNetCore.Session", out sessionId);
    			_sessionId = sessionId;
    			return hasSession;
    		}
    		/// <summary>
    		/// 鉴权方法
    		/// </summary>
    		/// <returns></returns>
    		public async Task<AuthenticateResult> AuthenticateAsync()
    		{
    			//从缓存中获取sessionid,如果没有则返回false
    			if (_cache.TryGetValue(_sessionId, out Dictionary<string, string> value))
    			{
    				//将当前sessionId和键值对组成新的键值对,存入缓存中,并设置过期时间为20分钟
    				_cache.Set<Dictionary<string, string>>(_sessionId, value, TimeSpan.FromMinutes(20));
    				//调用session的初始化方法,将sessionId和缓存中的键值对传入
    				_session.InitSession(_sessionId, _cache);
    				//将当前sessionId赋值给ClaimsPrincipal
    				ClaimsIdentity claimsIdentity = new("ctm");
    				claimsIdentity.AddClaims(new List<Claim>
    				{
    					new Claim(ClaimTypes.NameIdentifier,_sessionId)
    				});
    				//最终返回成功的结果
    				return await Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(claimsIdentity), null, _scheme.Name)));
    			}
    			else
    			{
    				return await Task.FromResult(AuthenticateResult.Fail("Session已经过期"));
    			}
    		}
    
    		public async Task ChallengeAsync(AuthenticationProperties properties)
    		{
    			_context.Response.Redirect("/Login/NoLogin");
    		}
    
    		public async Task ForbidAsync(AuthenticationProperties properties)
    		{
    			_context.Response.StatusCode = 403;
    		}
    	}
    
    
    
    }
    

    小一周完成了

  • 相关阅读:
    Windows 2003安全配置最佳方法(转)
    令人十分怨念的tomcat注册成windows服务(转)
    AMR开源编码jrtplib中与int系统重定义问题解决
    由系统熵转移的思考
    此男因为什么被送进医院?
    [转]风水师的郁闷
    飞盘奇门局例我能顺利办好护照拿到签证出国参加会议吗?
    最近工作方面发生了一些大事情,所以特地为此摇了一挂,请高手进来断一断。
    概率面前的错误
    杜新会一个精彩占例之反推
  • 原文地址:https://www.cnblogs.com/humblexwang/p/16073067.html
Copyright © 2020-2023  润新知