首页 > 编程语言 >ASP.NET Core 鉴权授权四(自定义Session)

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

时间:2024-08-07 17:08:20浏览次数:17  
标签:Core ASP string 自定义 cache sessionId session context public

实体模型

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;
            // 配置ClaimsIdentity
            ClaimsIdentity 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.把数据库录入的路径改为错误的路径

标签:Core,ASP,string,自定义,cache,sessionId,session,context,public
From: https://www.cnblogs.com/leafroc/p/18347413

相关文章

  • Docker部署.netCore6
    Docker部署.netCore6第一步:在项目添加Docker支持第二步:选择Windows(如果是linx系统就选择linx)和Dockerfile第三步:生成Docker默认文件 把默认代码修改第四步:修改Dockerfile文件属性(如果不修改则会导致发布的时候Docker文件没有一起发布)第五步:把项目发布到文件夹在发......
  • Java 自定义注解笔记总结(油管)
    Java系列文章目录Java抽象相关知识笔记文章目录Java系列文章目录一、前言二、学习内容:三、问题描述四、解决方案:4.1自定义注解引入4.2自定义注解使用4.2.1自定义注解概念4.2.2自定义注解内部的属性五、总结:5.1学习总结:一、前言目的:学习自定义注解相关内......
  • EF Core连接PostgreSQL数据库
    PostgreSQL数据库介绍PostgreSQL是一个功能强大的开源对象关系型数据库管理系统(RDBMS)。最初于1986年在加州大学伯克利分校的POSTGRES项目中诞生,PostgreSQL以其稳定性、灵活性和扩展性而著称。它支持丰富的数据类型、复杂的查询、事务完整性、多版本并发控制(MVCC)、存储过程等高级......
  • 处理程序“aspx”在其模块列表中有一个错误模块“ManagedPipelineHandler”
    原文链接:https://www.cnblogs.com/mingcaoyouxin/p/3926800.html开发web项目时需要安装IIS,在安装好IIS的Windows7本上发布asp.net网站时,web程序已经映射到了本地IIS上,但运行如下错误提示“处理程序“PageHandlerFactory-Integrated”在其模块列表中有一个错误模块“ManagedPip......
  • 保存/加载自定义 tf.keras.Model 时出现问题
    我正在构建一个作为自定义tf.keras.Model实现的自动编码器。虽然训练后的模型表现良好,但我无法正确保存并重新加载它。我已经尝试过model.save()方法和save_weights()但在这两种情况下,模型完全无法执行其任务。此自动编码器正在调用另外两个tf.keras.Model,即编码器和......
  • 通过go自定义alertmanager 发送通知的webhook
    本文主要是大体介绍webhook的代码以及涉及到的服务部署,详细配置需要自己弄Prometheus、alertmanager部署先创建alertmanager、Prometheus的docker-composeyaml文件,下面只是把服务运行起来,具体功能需要自己配置,如果有就跳过version:'3'services:prometheus:ima......
  • k8s学习笔记之CoreDNS
    一、CoreDNSconfigMap配置参数及说明主要讲解CoreDNSconfigMap及其他关键配置部署文件(需要替换其中一些变量):https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/dns/coredns/coredns.yaml.base1.configMap配置apiVersion:v1kind:ConfigMapmetadat......
  • 笔记:从Aurora 8b/10b 到Aurora 64b/66b (三):自定义PHY层收发
    相较于8/10来说没那么复杂,需要考虑的情况只有八种;但是gearbox的控制需要额外的心思:每三十二周期所有操作都需要停止;这一点在收发都需要注意;RX:核心思想是利用header做检测,将夹杂在数据流中的控制包滤除掉;modulegt_phy_rx(inputwirei_rx_clk......
  • golang sliver二次开发自定义命令(格式乱后面再调)
    准备工作sliver客户端和服务端之间命令的通信采用的grpc,服务端和和植入程序通信使用的protobuf,所以在开发之前需要了解grpc和protobuf,相关文档:https://jergoo.gitbooks.io/go-grpc-practice-guide/content/chapter2/hello-grpc.htmlhttps://jergoo.gitbooks.io/go-grpc-pra......
  • netcore webapi部署到docker容器,api调用后显示中文乱码
    vs2022webapi部署到docker容器,api调用后显示中文乱码。原因是:源代码文件不是utf-8编码(用vscode打开是乱码,在vscode修改后,再提交,正常)解决方法一:在中文环境下用过微软家Visualstudio的都知道,新建文件的保存编码都默认为当前系统语言,所以你的文件编码永远都是GB2312,非常令人......