ASP.NET Core 鉴权授权四(自定义Session)

news/2024/11/19 19:21:41/文章来源:https://www.cnblogs.com/leafroc/p/18347413

实体模型

public class BaseModel
{public int Id { get; set;}
}
public class Authorization : BaseModel
{public string Route { get; set; }public string AuthorizationName { get; set; }
}
public class User : BaseModel
{public string UserName { get; set; }public string Password { get; set; }
}
public class UserAuthorizationMapping : BaseModel
{public int UserId { get; set; }public int AuthorizationId { get; set; }
}

自定义Session

public interface IMySession
{void InitSession(IMemoryCache memoryCache, string sessionId);string? GetString(string key);void SetString(string key, string value);
}public class MySession : IMySession
{private IMemoryCache _memoryCache;private string _sessionId;public void InitSession(IMemoryCache memoryCache, string sessionId){_sessionId = sessionId;_memoryCache = memoryCache;}public string? GetString(string key){// 获取SessionId,并根据这个拿到当前用户存储的键值对if(_memoryCache.TryGetValue(_sessionId,out Dictionary<string,string>? dic)){if(dic == null){return null;}if(dic.TryGetValue(key,out string? dicValue)){return dicValue;}}return null;}public void SetString(string key,string value){if (_memoryCache.TryGetValue(_sessionId, out Dictionary<string, string>? dic)){if (dic != null){dic[key] = value;}}}
}

自定义鉴权架构

public class SessionAuthenicationHandler : IAuthenticationHandler
{private readonly IMemoryCache _cache;private readonly IMySession _session;private AuthenticationScheme _scheme;private HttpContext _context;private string _sessionId;public SessionAuthenicationHandler(IMemoryCache cache, IMySession session){_cache = cache;_session = session;}/// <summary>/// 初始化身份验证处理程序。 作为此方法的一部分,处理程序应从请求和方案中初始化它所需的任何内容/// </summary>/// <param name="scheme"></param>/// <param name="context"></param>/// <returns></returns>public async Task InitializeAsync(AuthenticationScheme scheme, HttpContext context){_scheme = scheme;_context = context;if (!TryGetSession(out string id) || !_cache.TryGetValue(_sessionId, out var cookie)){var sessionId = Guid.NewGuid().ToString();_sessionId = sessionId;context.Response.Cookies.Append(".AspNetCore.Sessions", sessionId);_cache.Set<Dictionary<string, string>>(_sessionId, new Dictionary<string, string>(), TimeSpan.FromMinutes(1));}}/// <summary>/// 对当前请求进行身份验证。/// </summary>/// <returns></returns>/// <exception cref="NotImplementedException"></exception>public Task<AuthenticateResult> AuthenticateAsync(){// 尝试从缓存中获取数据if(_cache.TryGetValue(_sessionId,out Dictionary<string,string> value)){// 重新滑动配置缓存过期_cache.Set<Dictionary<string,string>>(_sessionId,value,TimeSpan.FromMinutes(1));// 初始化Session_session.InitSession(_cache,_sessionId);// 注意,这里存储到HttpContext.Items中_context.Items["session"] = _session;// 配置ClaimsIdentityClaimsIdentity claimsIdentity = new ClaimsIdentity("Ctm");claimsIdentity.AddClaims(new List<Claim>{new Claim(ClaimTypes.NameIdentifier,_sessionId)});return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(new  ClaimsPrincipal(claimsIdentity),null,_scheme.Name)));}else{return Task.FromResult(AuthenticateResult.Fail("Session过期,请重新登录"));}}/// <summary>/// 质询当前请求。/// </summary>/// <param name="properties"></param>/// <returns></returns>/// <exception cref="NotImplementedException"></exception>public async Task ChallengeAsync(AuthenticationProperties? properties){_context.Response.Redirect("/Login/NoLogin");}/// <summary>/// 禁止当前请求/// </summary>/// <param name="properties"></param>/// <returns></returns>/// <exception cref="NotImplementedException"></exception>public async Task ForbidAsync(AuthenticationProperties? properties){_context.Response.StatusCode = 403;}private bool TryGetSession(out string id){var has = _context.Request.Cookies.TryGetValue(".AspNetCore.Sessions",out id);_sessionId = id;return has;}}

自定义授权

public class CtmAuthorizationFilter : Attribute, IAuthorizationFilter
{public void OnAuthorization(AuthorizationFilterContext context){var session = context.HttpContext.Items["session"] as IMySession;var route = context.HttpContext.Request.Path.Value;var auth = session.GetString("Auth");if(auth != null){var aurhorizations = JsonConvert.DeserializeObject<List<Authorization>>(auth);if(aurhorizations == null || aurhorizations.Count < 1){context.Result = new JsonResult("没有录入权限数据") { StatusCode = 403 };}if (aurhorizations.Any(x => x.Route != route)){context.Result = new JsonResult("无权限") { StatusCode = 403 };}}else{context.Result = new JsonResult("请先登录") { StatusCode = 403 };}}
}

注册

builder.Services.AddSingleton<IMemoryCache,MemoryCache>();
builder.Services.AddScoped<IMySession,MySession>();
builder.Services.AddAuthentication(opt =>
{opt.AddScheme<SessionAuthenicationHandler>("session","sessionScheme");opt.DefaultChallengeScheme = "session";opt.DefaultAuthenticateScheme = "session";opt.DefaultForbidScheme = "session";
});app.UseAuthentication();
app.UseAuthorization();

使用

public class LoginController : BaseController
{private readonly LoginBLL _loginBLL;public LoginController(LoginBLL loginBLL){_loginBLL = loginBLL;}[HttpGet("CheckLogin")]public async Task<bool> CheckLoginAsync(string userName, string password){var user = await _loginBLL.CheckLoginAsync(userName, password);if (user == null){return false;}var authorizations = await _loginBLL.GetAuthorizationsAsync(user.Id);Session.SetString("Auth", JsonConvert.SerializeObject(authorizations));return true;}
}public class TestController : BaseController
{[CtmAuthorizationFilter][HttpGet("GetTime")]public async Task<string> GetTimeAsync(){return await Task.FromResult(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));}   
}

结果

1.在不登录的情况下访问GetTime

2.先登录,再访问GetTime

3.把数据库录入的路径改为错误的路径

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/779314.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何利用 LNMP 搭建 WordPress 站点

在这个信息爆炸的时代,拥有一个能够迅速传达信息、展示个性、并能够与世界互动的在线平台,已成为企业和个人的基本需求。WordPress,以其无与伦比的易用性和强大的扩展性,成为了构建此类平台的首选工具。而LNMP,这个由Linux、Nginx、MySQL和PHP组成的强大组合,为WordPress…

Jmeter常见设置,启动默认设置为中文

1、设置启动Jmeter后显示内容语言为中文 未配置时打开Jmeter查看页面可手动设置语言为中文这种设置不好的地方在于每次重新启动后都需要设置一般有点烦 可以用另一种方法解决:修改jmeter.properties文件的配置 打开jmeter的目录,文件位于jmeter的bin目录下 打开文件后,增加l…

域名被墙如何查询检测?

在当今数字化的时代,域名是网站的重要标识,是用户访问网站的入口。然而,有时候域名可能会遭遇被墙的情况,这给网站所有者和用户带来了极大的困扰。 首先,我们需要了解什么是域名被墙。域名被墙,通常是指域名在国内无法正常访问,而在国外可以访问。这种情况可能是由于网站…

鸿蒙应用开发——更改应用的图标和名字

鸿蒙应用开发——更改应用的图标和名字鸿蒙应用开发——更改应用的图标和名字 一、更换应用默认图标 路径是AppScope/resources/base/media/app_icon.png 二、更改应用名字 路径是AppScope/resources/base/element/string.json"string": [{"name": "a…

EF Core连接PostgreSQL数据库

本文介绍了如何使用EF Core连接PostgreSQL数据库。PostgreSQL数据库介绍 PostgreSQL是一个功能强大的开源对象关系型数据库管理系统(RDBMS)。最初于1986年在加州大学伯克利分校的POSTGRES项目中诞生,PostgreSQL以其稳定性、灵活性和扩展性而著称。它支持丰富的数据类型、复杂…

js文字无限循环向上滚动轮播

<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="stylesheet"><title>滚动…

使用W外链平台免费创建活码+客服码

在当今数字化时代,无论是企业营销、个人品牌建设还是日常交流互动,线上工具的灵活运用都显得尤为重要。其中,外链平台作为连接不同网络空间的桥梁,其重要性不言而喻。今天,我们将深入探讨如何利用W外链平台这一强大工具,免费创建活码与客服码,以优化用户体验,提升运营效…

Django请求和响应

1. 请求获取请求方式 GET/POSTprint(requset.method) 通过url传递值 /something?n1=1234&n2=456print(requset.GET) 通过请求体获取数据print(requset.POST)【注】:获取的请求方式和传递的值和数据,可在终端后台看见2. 响应HttpResponse("返回内容") 将字符串…

B站基于Apache DolphinScheduler的一站式大数据集群管理平台(BMR)初窥

一、背景 大数据服务是数据平台建设的基座,随着B站业务的快速发展,其大数据的规模和复杂度也突飞猛进,技术的追求也同样不会有止境。 B站一站式大数据集群管理平台(BMR),在千呼万唤中孕育而生。本文简单介绍BMR的由来、面临的主要矛盾以及如何在变化中求得生存与发展。 下…

烧烤 题解

题目id:11063 题目描述 \(Snuke\)有一个烧烤聚会。 聚会上,他将制作\(N\)份串烧。$\ \ \ \ \ \ \ $一份串烧 他有\(2N\)根烤肉钎子,它们都将用于制作串烧。第i个烤肉钎子的长度为Li。此外,他有无限供应的原料。他将原料串在两根烤肉钎子上做成一份串烧。一份串烧可串起的原…

信创系统问题解决笔记

本文介绍了搭建信创环境,解决显示问题的全过程。本文记述解决信创系统显示问题过程经历,描述遇到的各种问题以及解决方法。 问题描述 测试反馈,在信创系统上,部分界面字体显示异常,表现为内容越界、文字区域显示为小空格,如下图所示:初步分析是字体原因,具体情况需要更…

文件包含的skill

关于文件包含 🚩php7 segment fault特性原理:php代码中使用php://filter的strip_tags过滤器,可以让php执行的时候直接出现Segment Fault,这样php的垃圾回收机制就不会继续执行,导致POST的文件会保存在系统的缓存目录下不会被删除,不像phpinfo上传的文件很快就会被删除,…