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

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 Core中的Action的返回值类型实现

    在ASP.NET Core中,Action是一种处理HTTP请求的机制。Action可以返回不同类型的结果,例如视图、JSON数据、文件等。在本文中,我们将详细讲解ASP.NET Core中Action的返回值类型实现的完整攻略,包括返回值类型的概念、使用方法和示例。 返回值类型的概念 在ASP.NET Core中,Action的返回值类型可以是以下类型之一…

    C# 2023年5月16日
    00
  • asp.net web api2设置默认启动登录页面的方法

    以下是“ASP.NET Web API 2设置默认启动登录页面的方法”的完整攻略: 什么是ASP.NET Web API 2 ASP.NET Web API 2是一种用于构建RESTful Web服务的框架。它是ASP MVC框架的一部分,可以帮助开发人员构建可扩展的Web API。 ASP.NET Web API 2设置默认启动登录页面方法 ASP.NET…

    C# 2023年5月12日
    00
  • .net的序列化与反序列化实例

    . 什么是序列化和反序列化 序列化(Serialization)指将对象转化为可以存储或传输的格式的过程。在此过程中,对象中的属性值被提取并打包为一组二进制数据,可以被序列化为XML、JSON、二进制等格式。在.NET中,序列化包含了 Binary serialization,XML serialization和 JSON serialization几种方式…

    C# 2023年5月31日
    00
  • 浅谈AjaxPro.dll,asp.net 前台js调用后台方法

    让我们来详细讲解一下“浅谈AjaxPro.dll,asp.net 前台js调用后台方法”的完整攻略。 什么是AjaxPro.dll AjaxPro.dll 是一个开源的 asp.net AJAX 库,可以帮助我们轻松地实现前台 js 和后台方法的调用,简化了前后台的交互。它特别适用于需要频繁异步交互、需要处理大量数据量的 web 应用程序。 AjaxPro.…

    C# 2023年6月3日
    00
  • C# 动态输出Dos命令执行结果的实例(附源码)

    下面是对主题“C# 动态输出Dos命令执行结果的实例(附源码)”的详细讲解攻略。 1. 背景介绍 在C#中执行DOS命令并输出执行结果,通常采用Process类来实现。但如果要及时输出命令执行结果,我们需要借助于StandardOutput和BeginOutputReadLine两个属性和方法。 2. 具体步骤 2.1 创建Process实例 首先,我们需要…

    C# 2023年6月7日
    00
  • C#通过DataSet读写xml文件的方法

    下面是详细讲解C#通过DataSet读写XML文件的方法的完整攻略: 准备工作 在开始之前,需要使用C#项目创建好一个XML文件,并且设置好文件的格式和数据。 读取XML文件 创建DataSet对象,并读取XML文件 DataSet ds = new DataSet(); ds.ReadXml("文件路径及名称.xml"); 查找特定节点…

    C# 2023年6月1日
    00
  • 如何使用C# Stopwatch 测量微秒级精确度

    使用C# Stopwatch测量微秒级精确度的完整攻略如下: 步骤 1:导入命名空间 首先,在代码文件的顶部,添加System.Diagnostics 命名空间,以便使用 Stopwatch 类: using System.Diagnostics; 步骤 2:初始化 Stopwatch 创建 Stopwatch 类示例,并调用 Start 方法(或 Rest…

    C# 2023年5月15日
    00
  • C#用表达式树构建动态查询的方法

    下面是C#用表达式树构建动态查询的完整攻略。 什么是表达式树 表达式树(Expression Tree)是将操作表达式按照层级结构组成的一种数据结构,类似于抽象语法树(AST)。在C#中,表达式树可以动态表示Lambda表达式的结构。 为何要用表达式树构建动态查询 在很多情况下,我们需要设计一个通用的、可扩展的查询条件表达式,比如一个动态搜索框,用户可以在其…

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