首页 > 编程语言 >ASP.NET Core 使用 Claim 认证详解

ASP.NET Core 使用 Claim 认证详解

时间:2023-07-27 17:01:51浏览次数:42  
标签:Core ASP 登录 Claim 认证 Controller Cookie Action

微软在早期 .NET Framework 时代,针对 ASP.NET 的用户登录身份认证,提供了 Forms 认证实现方案。后来在推出 ASP.NET Core 之后,采用 Claim 认证替代了 Forms 认证,两者本质上都是基于 Cookie 加解密的认证方式,学习和使用起来非常简单,比较适合在小型项目中使用,主要是方便。

假设我们现在已经创建好了一个基于 .NET5 模型-视图-控制器 的 ASP.NET Core Web 应用 (这里就不介绍创建过程了),下面我就基于 .NET5 网站,介绍一下 Claim 认证的具体实现方式:


1 修改 appsettings.json 配置文件,增加有关 Cookie 的相关配置

在实际开发场景中,我们一般将 Cookie 相关信息进行配置,所以我们增加以下配置信息:

{
  // 这里采用了两级嵌套的 json 配置方式
  "web": {
    // 用户未登录时,自动跳转的目标路由地址
    "loginUrl": "/Home/Login", 
    // Cookie 的名字
    "cookieName": "UserAuth",
    // Cookie 保存的路径,这里保存在根路径
    "cookiePath": "/",
    // Cookie 的所属的域名
    "cookieDomain": ".demo.com"
  }
}

其实上面的 json 配置中, Cookie 的保存路径,所属域名,都可以配置为空,这样不影响 Claim 认证的实现。

但是有一种情况例外,那就是万恶的 IE 浏览器。对于 IE 浏览器来说,上面的 json 配置中,必须配置好 Cookie 的保存路径和域名,否则无法生成 Cookie,无法实现 Claim 认证。

如果你实施的项目不考虑 IE 浏览器的话,那就很幸运了。但是目前国内的很多银行、政府、国企,未来很长一段时间仍然还在使用 IE 浏览器,所以有时候还得被迫考虑 IE 浏览器。


2 修改 Startup.cs 文件,增加 Claim 认证支持

需要修改两个地方 ConfigureServices 方法 和 Configure方法

在 ConfigureServices 方法 中添加 Cookie 认证方式,在 Configure方法 中使用认证和授权。

注意:Configure 方法每行代码的顺序位置很重要,新增加的两行代码(app.UseAuthentication 和 app.UseAuthorization 必须在 app.UseRouting 之后,app.UseEndpoints 之前)

public void ConfigureServices(IServiceCollection services, IConfiguration Config)
{
    services.AddControllersWithViews();

    //添加 Cookie 认证方式
    services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => 
    {
        //从配置节中读取配置的 Cookie 信息
        options.LoginPath = Config["web:loginUrl"];
        options.Cookie.Name = Config["web:cookieName"];
        options.Cookie.Path = Config["web:cookiePath"];
        options.Cookie.Domain = Config["web:cookieDomain"];
    });
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseStaticFiles();
    app.UseRouting();

    //使用认证和授权
    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>{
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Web}/{action=Index}");
    });
}

3 在相关 Controller 中的 Action 方法添加 Claim 认证的代码

假设我们在登录页面,输入了用户名密码,提交到后台的 Home/Login 中,该 Action 已经在数据库中验证了用户名和密码的正确性,接下来就要生成 Claim 认证的 Cookie,代码如下:

public IActionResult Login(string name, string pwd)
{
    //......此处省略了去数据库验证用户名和密码,以及获取用户的权限的相关代码

    //可以添加额外的信息存储在cookie中
    //这里把从数据库中获取的【用户角色】和【权限码】进行存储
    var claims = new[] { new Claim("Power", power), new Claim("Role", role) };

    //这里存储【用户名】
    //这样后面就可以通过 User.Identity.Name 获取到用户名了
    GenericIdentity gi = new GenericIdentity(name);
    ClaimsIdentity ci = new ClaimsIdentity(gi, claims, 
        CookieAuthenticationDefaults.AuthenticationScheme, "", "");
    ClaimsPrincipal cp = new ClaimsPrincipal(ci);

    Task.Run(async () =>
    {
        //生成 Cookie 并保存到硬盘中,指定 Cookie 的过期时间
        await HttpContext.SignInAsync(
        CookieAuthenticationDefaults.AuthenticationScheme,cp, new AuthenticationProperties()
        {
            IsPersistent = true,
            ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(60),
            AllowRefresh = true
        });
    }).Wait();
    return Content("login success");
}

前端通过 Ajax 调用后端登录方法后,如果成功,然后跳转到网站主页即可。


4 控制 Controller 和 Action 的访问

我们可以通过在 Controller 上或 Action 上增加 [Authorize] 标记 或 [AllowAnonymous] 标记,来控制用户对具体 Controller 或 Action 的访问,这跟以前的 Forms 认证的控制方式一模一样。

[Authorize] 标记:

表示必须拥有 Claim 的 Cookie 才能访问,否则就会跳转到指定的页面,我们一般指定跳转到登录页面。可以放到 Controller 或 Action 上。如果该标记添加到 Controller 上,则该 Controller 下的所有 Action 都会验证是否拥有 Claim 的 Cookie。

[AllowAnonymous] 标记:

表示允许匿名用户访问,没有登录也可以访问,也就是不需要 Claim 的 Cookie 就可以访问。可以放到 Controller 或 Action 上。通常的使用场景是:在 Controller 上放了 [Authorize] 之后,在该 Controller 下具体的一小部分 Action 上放 [AllowAnonymous] 标记。这样就保证 Controller 下只有一小部分 Action 允许未登录用户访问,其它的 Action 必须用户登录后才能访问。


5 获取 Claim 的 Cookie 中的信息以及退出登录

在上面第 3 步中,我们通过 GenericIdentity gi = new GenericIdentity(name) 这行代码存储登录的用户名,因此我们可以通过 User.Identity.Name 获取到登录的用户名。

下面列出获取 Cookie 中存储的其它信息,比如上面存储的 Power 和 Role

[Authorize]
public IActionResult Display()
{
    StringBuilder sb = new StringBuilder();

    // 遍历获取所有的存储信息
    foreach (var cl in HttpContext.User.Claims)
    {
        sb.AppendLine($"{cl.Type}|{cl.Value}");
    }

    // 通过便捷的方式获取登录的用户名
    sb.AppendLine(User.Identity.Name);

    // 想要获取到具体的一项存储信息,比如仅仅想获取权限码和角色
    sb.AppendLine(User.FindFirstValue("Power"));
    sb.AppendLine(User.FindFirstValue("Role"));

    return Content(sb.ToString());
}

如果想要用户退出登录,销毁 Cookie 的话,可以采用以下代码:

public IActionResult LogOut()
{
    if (User.Identity.IsAuthenticated)
    {
        Task.Run(async () => { await HttpContext.SignOutAsync(); }).Wait();
    }

    //销毁 Claim 的 Cookie 后,可以跳转到登录页面
    return RedirectToAction("Index", "Web");
}

6 优缺点闲谈

到此为止,ASP.NET Core 网站使用 Claim 认证,实现用户登录,访问时进行身份验证方案,已经介绍完了。如果你想要快速搭建轻量级网站应用的话,使用 Claim 认证方式是一种非常方便快速的方案。

但是不建议在大中型项目中使用,还是采用主流的 token + redis 的方案实现用户登录认证比较好,原因如下:

  • 后续项目肯定会涉及到各个系统之间的统一认证对接,以及与第三方的单点登录对接,这种情景使用 token + redis 的方案比较灵活简单,采用 Cookie 的实现方式比较麻烦。
  • 对于用户请求负载均衡分发的场景,token + redis 的方案是非常好的方案,因为其天然保证所有请求都是无状态的,不需要在负载均衡服务器上配置会话保持,这样负载均衡服务器就可以根据每台应用服务器的负载状况,随意使用任何负载请求分发策略。
  • 对于负载均衡来说, Claim 认证方案就不够灵活了,因为其 Cookie 只能在具体的服务器上进行加解密,从而识别登录用户。如果新的请求被负载均衡服务器分发到另一台应用服务器的话,那么就无法解密 Cookie 从而导致需要频繁重新登录,无法使用网站。只有在负载均衡服务器上配置会话保持,从而实现在一定的时间内将来自同一 ip 的请求分发到固定的应用服务器上,才能解决问题。(具体在各个不同的服务器之间,如何实现 Claim 的 Cookie 采用统一的加解密算法,我个人没有研究过。其实也没必要研究了,因为我们大部分情况下都会使用目前比较流行的 token + redis 方案,能够轻松解决任何问题)

标签:Core,ASP,登录,Claim,认证,Controller,Cookie,Action
From: https://www.cnblogs.com/Alex80/p/17585407.html

相关文章

  • ASP.NET Core 授权中间件 AuthorizationMiddleware
    ///<summary>///Amiddlewarethatenablesauthorizationcapabilities.///</summary>publicclassAuthorizationMiddleware{//AppContextswitchusedtocontrolwhetherHttpContextorendpointispassedasaresourcetoAuthZ......
  • .net core 调用打印机打印pdf文件 FreeSpire.PDF
    首先,参考了https://stackoverflow.com/questions/63941980/is-it-possible-to-print-documents-from-a-net-core-3-1-windows-service中的说明,声明:我用的是core3.1测试的先下载了FreeSpire.PDF的NuGet包,可以看出来简介上是支持print的: 然后我的测试直接在controller中:1[......
  • 使用ASP.NET Core Minimal API和MailKit发送电子邮件
    步骤1:创建新项目通过以下命令在终端中创建一个新的ASP.NETCoreWebAPI项目:dotnetnewwebapi-oSendingEmail由于我们正在使用MinimalAPIs,因此删除不必要的Controller文件夹和WeatherForecast类。步骤2:定义电子邮件数据传输对象(DTO)为了将数据从我们的API传递到邮件服务......
  • .NET Core依赖注入与Autofac注入介绍
    0前言本文主要介绍了ASP.NETCore自带的依赖注入框架的用法,然后针对原生框架的不足,介绍了更加完备的autofac框架的集成和使用。1.NETCore原生DI框架.NetCore自带一个依赖注入的框架,使用起来很是方便,不多说,先从简单示例做起。1.1简单示例以ASP.NETCoreweb的API项目为例......
  • asp.net core之Host
    Host简介在ASP.NETCore中,Host是一个托管应用程序的宿主环境。它提供了一种统一的方式来启动和运行应用程序,无论是在开发环境中还是在生产环境中。Host负责处理应用程序的生命周期、配置和依赖项管理等任务,使开发人员能够专注于应用程序的业务逻辑。Host是通过使用IHostBuilder......
  • ASP.NET Core Identity 系列之一
    ASP.NETCoreIdentity提供给我们一组工具包和API,它能帮助我们应用程序创建授权和认证功能,也可以用它创建账户并使用用户名和密码进行登录,同时也提供了角色和角色管理功能。ASP.NETCoreIdentity使用SQLServer/第三方数据库存储用户名和密码,角色和配置数据这系列中我们主要使用......
  • ASP.NET Core Identity 系列之一
    ASP.NETCoreIdentity提供给我们一组工具包和API,它能帮助我们应用程序创建授权和认证功能,也可以用它创建账户并使用用户名和密码进行登录,同时也提供了角色和角色管理功能。ASP.NETCoreIdentity使用SQLServer/第三方数据库存储用户名和密码,角色和配置数据这系列中我们主要使用VS......
  • Asp.Net 使用Log4Net (封装帮助类)
    Asp.Net使用Log4Net(封装帮助类)1.创建Log4Net帮助类首先,在你的项目中创建一个Log4Net帮助类,用于封装Log4Net的配置和日志记录逻辑。usinglog4net;usinglog4net.Config;publicclassLogHelper{privatestaticreadonlyILoglog=LogManager.GetLogger(typeof(......
  • Asp.Net 使用Log4Net (基础版)
    Asp.Net使用Log4Net(基础版)1.创建项目创建ASP.NETWebForms项目在VisualStudio中创建一个新的ASP.NETWebForms项目。命名为"Log4NetDemo"。2.安装Log4Net包打开NuGet包管理器控制台,并运行以下命令来安装Log4Net:mathematicaCopycodeInstall-Packagelog4net3.添......
  • Asp.Net 6中使用Log4Net
    Asp.Net6中使用Log4Net1.先新建一个ASP.NETCore空项目2.通过Nuget包管理器安装下面两个包log4netMicrosoft.Extensions.Logging.Log4Net.AspNetCore3.在项目根目录下新建log4net的配置文件log4net.config,并将其设置为始终复制。<?xmlversion="1.0"encoding="utf-......