asp.net core 中的Jwt(Json Web Token)的使用详解

yizhihongxing

ASP.NET Core 中的 JWT (Json Web Token) 的使用详解

什么是 JWT?

JWT 是一种轻量级的身份验证和授权解决方案,它是为 Web 应用程序设计的,基于 JSON 形式的轻量级开放标准(RFC 7519)。

其特点在于:

  • 可以使用一个 token 进行身份验证和授权,避免了复杂的 Sessions 或者 Cookies 的管理。
  • Token 能够被服务器解密和验证签名,防止黑客入侵。
  • Token 可以包含一些用户信息,可以可靠地完成身份验证,并授权服务器访问受保护的资源。

JWT 的结构

JWT 由三部分组成:头部,载荷和签名。

头部,Header

头部的格式是一个 JSON 对象,由两个属性组成:alg(algorithm) 和 typ (type)。

alg 指定了签名和加密的算法,例如 HMAC SHA256 和 RSA,以及对应的密匙。

{
  "alg": "HS256",
  "typ": "JWT"
}

载荷,Payload

载荷也是一个 JSON 对象,它包含了用户的身份信息、授权相关信息和其他额外的参数。它并不是加密的,任何人都可以读取它,因此不应该包含敏感信息。 JWT 的官方规定了一些预定义的声明,在对象中使用这些声明即可:

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}

签名,Signature

签名使用了加密机制,它需要服务器的密钥才能时做到正常解密和验证。将头部和载荷都用 Base64 编码后,在它们之间加上字符串类型的密钥进行 HMAC SHA256 串行化后的值尾部添加后即可。

头部与载荷的 Base64 的编码后的字符串格式:

eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJzdWIiOiAiMTIzNDU2Nzg5MCIsICJuYW1lIjogIkpvaG4gRG9lIiwgImlhdCI6IDE1MTYyMzkwMjJ9

加了密的字符串格式:

eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJzdWIiOiAiMTIzNDU2Nzg5MCIsICJuYW1lIjogIkpvaG4gRG9lIiwgImlhdCI6IDE1MTYyMzkwMjJ9.4l8SXMIzawtS2OUTxDiXamPLHY0pRHChDNdUnlN0Qv8

ASP.NET Core 中 JWT 的使用

ASP.NET Core 提供了一个 JWT 包,可以通过 NuGet 安装使用,这个包包含了 JWToken 中的完整实现。

添加 JWT 依赖包

为了使用 JWT,需要在项目中添加 Microsoft.AspNetCore.Authentication.JwtBearer 包的依赖,这个包是 ASP.NET Core 中处理 JWT 的核心包。

dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer

注册 JWT 中间件

在 Startup.cs 文件中注册 JWT 中间件,它会拦截进入应用程序的 HTTP 请求:

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
    options.RequireHttpsMetadata = false;
    options.SaveToken = true;
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration.GetSection("Jwt:Key").Value)),
        ValidateIssuer = false,
        ValidateAudience = false
    };
});

其中,件保存了几个配置信息,包括:

  • 需要 HTTPS
  • 需要保存 Token
  • Token 认证参数
    • ValidateIssuerSigningKey: 是否需要验证签名
    • IssuerSigningKey: 签名密钥
    • ValidateIssuer: 是否需要验证签发者
    • ValidateAudience: 是否需要验证观众

配置 JWT 配置文件

在应用中,我们可以设置一些固定变量或者不能随意变更的信息,如 HttpsMetaData, TokenValidation Parameters 等等。

可以设置一个 appsettings.json 文件来定义 JWT 中间件所需的必要信息:

{
  "Jwt": {
    "Key": "this_is_my_super_secure_key_123",
    "Issuer": "acnodesoft.com"
  }
}

需要注册配置文件:

services.Configure<JwtSettings>(Configuration.GetSection("Jwt"));

生成 JWT

使用 NuGet 的 System.IdentityModel.Tokens.Jwt pakcage 来生成 JWT。

private string GenerateToken(User user)
{
    var tokenHandler = new JwtSecurityTokenHandler();
    var key = Encoding.ASCII.GetBytes(_jwtSettings.Key);
    var tokenDescriptor = new SecurityTokenDescriptor
    {
        Subject = new ClaimsIdentity(new Claim[] 
        {
            new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
            new Claim(ClaimTypes.Name, user.Username)
        }),
        Expires = DateTime.UtcNow.AddDays(7),
        SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
    };
    var token = tokenHandler.CreateToken(tokenDescriptor);
    return tokenHandler.WriteToken(token);
}

其中,CreateToken 方法将两个参数串联在一起并使用对设置好的 Secret 指定的算法生成了最终的 JWT。经过 Base64 编码 (不是加密!) 后 JWT 可以被发送到客户端来使用。

这些配置可以灵活的修改和适配项目需求,然后利用 JWT 类中的方法即可实现 Token 的生成。

验证和使用 JWT

验证 JWT 的过程很简单:

[Authorize]
[HttpGet("profiles/{id}")]
public async Task<IActionResult> GetProfileById(int id)
{
    var user = await _userRepository.GetUserWithProfile(id);
    if (user == null) return NotFound();

    var profile = user.Profile;
    return Ok(new { profile.DisplayName, profile.Headline, profile.Location });
}

这时,需要所定义的 Authorization 机制,使用 [Authorize] 属性。

如果请求里有一个正确格式的 JWT,它会被拦截,否则请求返回 401。

示例1: 使用 JWT 单点登录

示例1,假设有A网站和B网站,它们的用户是相互独立的,但是它们共享相同的用户。例如,同一家公司的员工在两个不同的应用中使用相同的用户配置。

为了实现这个实例,需要创建一个单独的用户身份验证系统,这个系统产生的 JWT 将会被 A 和 B 网站共享。

步骤:

  • 每次用户通过我们单独的认证系统进行身份验证、授权时,该系统都会颁发一个 JWT
  • A、B 网站不再使用本地的身份验证机制,而是转移到调用单独的认证系统。
  • 当客户端访问 A 网站时,客户端带着 JWT 访问单独的认证系统,认证系统检查 JWT 的签名、有效期,并验证用户信息。如果所有条件都符合,就颁发一个新的 JWT 给客户端。
  • 客户端再从 B 网站请求数据时,带着它从单独的认证系统获取的 JWT。

相对于原来的方案而言,SSO大大简化了应用程序的身份验证和授权流程,使应用程序编写工作更简便,轻松和快速地实现各种身份验证和授权功能。本方案是一个非常棒的示例,展示了使用 JWT 实现身份验证的最佳实践,特别是在使用多个网站进行 SSO 的情况下。

示例2:使用 JWT 保护 API

API 为企业提供了一个通用的服务实例,比如向外部调用者提供数据或者向设备提供命令,因此 API 的安全性显得尤为重要。可以使用 JWT 保护 Web API。

步骤:

  1. 在 API 控制器上添加 JWT 身份验证机制。添加 [Authorize] 属性。
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class TodoController : ControllerBase
{
    private readonly TodoContext _context;

    public TodoController(TodoContext context)
    {
        _context = context;
    }

    // GET: api/Todo
    [HttpGet]
    public async Task<ActionResult<IEnumerable<TodoItem>>> GetTodoItems()
    {
        return await _context.TodoItems.ToListAsync();
    }

    // GET: api/Todo/5
    [HttpGet("{id}")]
    public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
    {
        var todoItem = await _context.TodoItems.FindAsync(id);

        if (todoItem == null)
        {
            return NotFound();
        }

        return todoItem;
    }

    // PUT: api/Todo/5
    [HttpPut("{id}")]
    public async Task<IActionResult> PutTodoItem(long id, TodoItem todoItem)
    {
        if (id != todoItem.Id)
        {
            return BadRequest();
        }

        _context.Entry(todoItem).State = EntityState.Modified;
        await _context.SaveChangesAsync();

        return NoContent();
    }

    // POST: api/Todo
    [HttpPost]
    public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem)
    {
        _context.TodoItems.Add(todoItem);
        await _context.SaveChangesAsync();

        return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem);
    }

    // DELETE: api/Todo/5
    [HttpDelete("{id}")]
    public async Task<IActionResult> DeleteTodoItem(long id)
    {
        var todoItem = await _context.TodoItems.FindAsync(id);

        if (todoItem == null)
        {
            return NotFound();
        }

        _context.TodoItems.Remove(todoItem);
        await _context.SaveChangesAsync();

        return NoContent();
    }
}
  1. 生成和发送 JWT
     services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(options =>
        {
            options.RequireHttpsMetadata = false;
            options.SaveToken = true;
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration.GetSection("Jwt:Key").Value)),
                ValidateIssuer = false,
                ValidateAudience = false,
                ClockSkew = TimeSpan.Zero
            };
        });

    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthentication();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }

在 Controller 使用原代码即可。

以上就是 ASP.NET Core 中 JWT 使用的全部步骤了。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:asp.net core 中的Jwt(Json Web Token)的使用详解 - Python技术站

(0)
上一篇 2023年6月3日
下一篇 2023年6月3日

相关文章

  • ASP.NET.4.5.1+MVC5.0设置系统角色与权限(一)

    ASP.NET 4.5.1 + MVC 5.0设置系统角色与权限(一) 在ASP.NET MVC应用程序中,设置系统角色和权限是非常重要的。本文将介绍如何使用ASP.NET 4.5.1和MVC 5.0设置系统角色和权限。 步骤1:创建角色 首先,我们需要创建系统角色。可以在Global.asax.cs文件中的Application_Start方法中添加以下代…

    C# 2023年5月15日
    00
  • Vue.js学习示例分享

    Vue.js是一种流行的JavaScript框架,用于构建交互式Web界面。本文将分享一些Vue.js学习示例,包括Vue.js的基本用法、组件、路由和状态管理等。 示例一:Vue.js的基本用法 以下是一个简单的Vue.js示例代码,用于显示一个计数器: <!DOCTYPE html> <html> <head> &lt…

    C# 2023年5月15日
    00
  • C#如何快速释放内存的大数组详解

    标题:C#如何快速释放内存的大数组详解 介绍:在C#编程开发中,如何高效地释放内存是一个非常实际的问题。本文主要探讨C#如何快速释放内存的大数组的方法和技巧,希望能够帮助大家更好地掌握C#编程语言。 一、使用Dispose方法释放内存 在C#编程开发中,释放内存的一种常见方式是通过使用Dispose方法。Dispose方法可以释放任何继承自IDisposab…

    C# 2023年6月6日
    00
  • C# 泛型的约束

    下面是详细讲解 “C# 泛型的约束” 的完整攻略,包括概念、使用方法和示例说明等: 概念 在 C# 中,泛型是一种让类或方法可以支持多种数据类型的技术。泛型的优点是能够让程序更加灵活、可扩展,同时也避免了大量的重复代码。而泛型的约束则是用来限制泛型类型参数的类型或属性的限制条件,以确保泛型类型参数符合特定需求,比如实现某种接口、具有某种属性等。 使用方法 泛…

    C# 2023年5月31日
    00
  • 详解 c# 克隆

    详解 C# 克隆 在 C# 中,克隆指的是创建一个新对象,这个新对象和旧对象具有相同的属性和值。为了实现克隆,我们需要使用ICloneable接口。在本文中,我们将详细讲解如何使用 C# 克隆。 ICloneable 接口 ICloenable 是 C# 中用来定义克隆能力的接口,它只包含一个方法 Clone()。当实现这个接口时,需要实现 Clone 方法…

    C# 2023年6月1日
    00
  • asp.net 添加水印的代码(已测试)

    根据您提供的主题,我将为您详细讲解如何在ASP.NET中添加水印的代码(已测试)。 简介 添加水印是网站开发中的常见需求之一。本篇攻略将帮助您实现一个简单的ASP.NET添加水印功能,并且已经过测试,代码经过了验证和校验,可以在常规的web应用程序中运行。 前置条件 在使用本文中的代码示例之前,请确保您已经满足以下前置条件: 拥有一个ASP.NET Web …

    C# 2023年5月31日
    00
  • c#(Socket)异步套接字代码示例

    让我来为您详细讲解一下“C#(Socket)异步套接字代码示例”的完整攻略。 什么是异步套接字 为了更好的理解这个示例,我们先来简单介绍一下异步套接字。 异步套接字(Asynchronous Socket)是一种非阻塞式的网络编程模型,通过异步套接字可以避免使用线程等多线程编程方式。异步套接字允许应用程序调用发送和接收函数,而不用等待这些函数完成,这样就可以…

    C# 2023年6月7日
    00
  • ASP.NET Core实现文件上传和下载

    一、ASP.NET Core实现文件上传的完整攻略 设置文件上传的API接口 要实现文件上传,首先需要在ASP.NET Core的API接口中设置文件上传的路由路径和它所用的http请求方式。例如,下面的代码演示了如何在API接口中设置文件上传的路由路径和它所用的http请求方式。 [HttpPost] [Route("api/uploadfile…

    C# 2023年6月3日
    00
合作推广
合作推广
分享本页
返回顶部