NET8中WebAPI使用JWT入门教程

news2024/9/24 5:29:07

目录

  • 1、JWT
  • 2、具体实现
  • 3、代码下载

1、JWT

现在在各类API的开发中,token已经是必备了。例如:微信公众号开发中,第一个方法就是获取token。JWT具体的定义及组成部分大家可以到网上找找,这儿给一个简单的描述:JWT 令牌是紧凑的 URL 安全令牌,易于在各方之间转移。它们是自包含的,这意味着它们自身内部携带信息,从而减少了对服务器端会话存储的需求。
定义可以从网上找到,但网上入门的例子,要么很简单、要么很复杂,反而不知道如何入门。因此这儿记录一下,在net8的webapi中如何使用JWT的入门教程。

2、具体实现

首先创建NET8环境下WebApi的项目,通过nuget引用包 Microsoft.AspNetCore.Authentication.JwtBearer
appsettings.json中添加配置信息

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",

  /**JWT的配置信息,这几个信息都是测试数据,需要根据实际业务自行调整**/
  "JwtSettings": {
    "SecretKey": "bAafd@A7d9#@F4*V!LHZs#ebKQrkE6pad2f3kj34c3dXy@", /**存放加密的秘钥**/
    "Issuer": "ZhengLinTest", /**存放发布者信息**/
    "Audience": "AllUseAPI", /**存放受众者信息**/
    "AccessTokenExpirationMinutes": 30,
    "RefreshTokenExpirationDays": 7
  }
}

为了能够将配置文件中JwtSettings强转换为一个类,需要提前定义一个Model类。

namespace JWTWebApplication.Models
{
    /// <summary>
    /// 这个类主要是用于解析appsettings.json里的配置信息,也可以使用其他方式,获取及保存配置信息
    /// </summary>
    public class JwtSettings
    {
        public string SecretKey { get; set; }
        public string Issuer { get; set; }
        public string Audience { get; set; }
        public int AccessTokenExpirationMinutes { get; set; }
        public int RefreshTokenExpirationDays { get; set; }

    }
}

JWT是一加密的符合JSON格式的字符串,那我们就需要定义,到底要加密哪些信息。在本例中我们会加密:姓名、密码、角色、邮箱等信息。因此我们创建一个,用于自定义需要加密到JWT中的信息。具体的Model如下

namespace JWTWebApplication.Models
{
    /// <summary>
    /// 用于存储到token中的数据
    /// </summary>
    public class User
    {
        public int Id { get; set; }
        public string Username { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
        public string Password { get; set; }
        public string[] Roles { get; set; }
    }
}

下面我们会创建一个用于生成JWTService类,并添加一个生成jwt的方法Crete

namespace JWTWebApplication.Services
{
    public class AuthService
    {
	    //通过依赖注入的方式,将配置参数带入到类中。后面会在program.cs文件中,进行注册。
			private readonly JwtSettings _jwtSettings;
			
			public AuthService(IOptions<JwtSettings> jwtSettings)
			{
			    _jwtSettings = jwtSettings.Value;
			}

			/// <summary>
			/// 用于令牌的生成
			/// </summary>
			/// <param name="user"></param>
			/// <returns></returns>
			public string Create(User user)
			{
			}
    }
}

Create方法中,先实例化JwtSecurityTokenHandler,它负责生成token(令牌)

var handler = new JwtSecurityTokenHandler();

下一步是生成令牌的信息并进行签名,因此我们需要刚才配置信息的秘钥,并使用SigningCredentials 完成签名,SigningCredentials 需要两个参数:秘钥和算法

var privateKey = Encoding.UTF8.GetBytes(_jwtSettings.SecretKey);

var credentials = new SigningCredentials(
            new SymmetricSecurityKey(privateKey),
            SecurityAlgorithms.HmacSha256);

下一步,就是将我们需要加密到token中的数据,通过方法实现。该如何添加呢?它的代码是这样的:

new Claim(ClaimTypes.Name, user.Username)  //可以理解为键/值结构

为了简化操作,我将创建一个方法来返回我们将保存在令牌中的 ClaimsIdentity(所有令牌声明的列表),该方法会自动添加到令牌的有效负载中。

//准备给Token中的值
private static ClaimsIdentity GenerateClaims(User user)
{
    var ci = new ClaimsIdentity();

    ci.AddClaim(new Claim("id", user.Id.ToString()));
    ci.AddClaim(new Claim(ClaimTypes.Name, user.Username));
    ci.AddClaim(new Claim(ClaimTypes.GivenName, user.Name));
    ci.AddClaim(new Claim(ClaimTypes.Email, user.Email));

    foreach (var role in user.Roles)
        ci.AddClaim(new Claim(ClaimTypes.Role, role));

    return ci;
}

下一步操作是创建 SecurityTokenDescriptor 的实例,以便在令牌中包含基本信息

var tokenDescriptor = new SecurityTokenDescriptor
{
    SigningCredentials = credentials,
    Expires = DateTime.UtcNow.AddMinutes(_jwtSettings.AccessTokenExpirationMinutes),
    Subject = GenerateClaims(user)
};

然后我使用handler.CreateToken()方法生成令牌,并且使用handler.WriteToken(token)方法,将JwtSecurityToken序列化为紧凑序列化格式JWT并返回。

var token = handler.CreateToken(tokenDescriptor);
return handler.WriteToken(token);

最终,生成完成的代码如下:

using JWTWebApplication.Models;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace JWTWebApplication.Services
{
    public class AuthService
    {
        //通过依赖注入的方式,将配置参数带入到类中
        private readonly JwtSettings _jwtSettings;

        public AuthService(IOptions<JwtSettings> jwtSettings)
        {
            _jwtSettings = jwtSettings.Value;
        }



        /// <summary>
        /// 用于令牌的生成
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public string Create(User user)
        {
            var handler = new JwtSecurityTokenHandler();
            var privateKey = Encoding.UTF8.GetBytes(_jwtSettings.SecretKey);

            var credentials = new SigningCredentials(
                        new SymmetricSecurityKey(privateKey),
                        SecurityAlgorithms.HmacSha256);


            var tokenDescriptor = new SecurityTokenDescriptor
            {
                SigningCredentials = credentials,
                Expires = DateTime.UtcNow.AddMinutes(_jwtSettings.AccessTokenExpirationMinutes),
                Subject = GenerateClaims(user)
            };

            var token = handler.CreateToken(tokenDescriptor);
            return handler.WriteToken(token);

        }

        //准备给Token中的值
        private static ClaimsIdentity GenerateClaims(User user)
        {
            var ci = new ClaimsIdentity();

            ci.AddClaim(new Claim("id", user.Id.ToString()));
            ci.AddClaim(new Claim(ClaimTypes.Name, user.Username));
            ci.AddClaim(new Claim(ClaimTypes.GivenName, user.Name));
            ci.AddClaim(new Claim(ClaimTypes.Email, user.Email));

            foreach (var role in user.Roles)
                ci.AddClaim(new Claim(ClaimTypes.Role, role));

            return ci;
        }
    }
}

有了生成token的方法,那我们就需要进行配置,准备使用了。具体来说,就是在program.cs中进行配置
首先添加开启授权和认证功能的代码

builder.Services.AddAuthentication();//启用身份验证功能--认证主要是指,用户米、密码是否正确
builder.Services.AddAuthorization();//启用授权功能---授权主要是看有没有权限

app.UseAuthentication(); //启用认证功能
app.UseAuthorization(); //启用授权功能

其次,要指定使用 JWT 进行身份验证,需要进行配置调整。这涉及设置 DefaultChallengeScheme 以定义如何检查每个传入请求以确定适当的身份验证方法。这可确保应用程序收到的每个请求都被视为 JWT 身份验证

builder.Services.AddAuthentication(x =>  
{  
    x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;  
    x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;  
});

此外,可以通过 AddJwtBearer()方法进行验证令牌。在本例中,将使用私钥,并且为了简单起见,排除了对颁发者和受众的验证

//收到的每个请求都被视为 JWT 身份验证
builder.Services.AddAuthentication(x =>
{
    x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(x =>
{
    x.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
    {
        ValidateIssuer = false,
        ValidateAudience = false,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.SecretKey))
    };
});

因为有些类,用到了依赖注入的方式实现,因此在配置文件中加了一下依赖注入的声明

//依赖注入
builder.Services.AddTransient<AuthService>();
builder.Services.AddOptions();
builder.Services.Configure<JwtSettings>(builder.Configuration.GetSection("JwtSettings"));

因此,完成的配置文件如下:

using JWTWebApplication.Models;
using JWTWebApplication.Services;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using Microsoft.Extensions.Options;
using System.Text;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

//依赖注入
builder.Services.AddTransient<AuthService>();
builder.Services.AddOptions();
builder.Services.Configure<JwtSettings>(builder.Configuration.GetSection("JwtSettings"));

//启用功能
builder.Services.AddAuthentication();//启用身份验证功能--认证主要是指,用户米、密码是否正确
builder.Services.AddAuthorization();//启用授权功能---授权主要是看有没有权限

//读取配置文件的数据
//这儿自定义了一个JwtSettings类,类里面的属性要与配置文件中的一致
var jwtSettings = builder.Configuration.GetSection("JwtSettings").Get<JwtSettings>();

//收到的每个请求都被视为 JWT 身份验证
builder.Services.AddAuthentication(x =>
{
    x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(x =>
{
    x.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
    {
        ValidateIssuer = false,
        ValidateAudience = false,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.SecretKey))
    };
});

//声明一个指定名称的认证策略
builder.Services.AddAuthorization(x =>
{
    x.AddPolicy("rolePolicy", p => p.RequireRole("developer"));
});


var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseAuthentication(); //启用认证功能
app.UseAuthorization(); //启用授权功能

app.MapControllers();

app.Run();

至此,基本的配置已经完成,让我们开始使用吧
首先,先创建一个api的Controller,并写下如下的代码

namespace JWTWebApplication.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class JWTTestController : ControllerBase
    {
	    //依赖注入。在program文件中的依赖注入,这儿就用到了
			private readonly AuthService _authService;
			public JWTTestController(AuthService authService)
			{
			    _authService = authService;
			}

			//具体的三个方法实现
    }
}

在类里面,我们将会创建三个方法:Logintestroletest。这三个方法分别用于:根据传入的用户米/密码,生成tokentestroletest分别用于测试权限认证和测试指定认证名称(就是在program中的x.AddPolicy("rolePolicy", p => p.RequireRole("developer"));),完整的代码如下:

namespace JWTWebApplication.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class JWTTestController : ControllerBase
    {
        //依赖注入
        private readonly AuthService _authService;
        public JWTTestController(AuthService authService)
        {
            _authService = authService;
        }

        [HttpGet]
        public string Login(string username,string password)
        {
            //获取前台传过来的用户名、密码的数据
            var user = new User();
            user.Username = username;
            user.Password = password;

            //从后台进行身份验证,并获取该登录人的其他信息(例如,角色、邮箱等各类信息)
            user.Name = "zhenglin";
            user.Id = 1;
            user.Email = "zhenglin@163.com";
            user.Roles = new string[] { "developer" };

            //返回token
            return _authService.Create(user);
        }

        [Authorize]
        [HttpGet]
        public StatusCodeResult test()
        {
            return StatusCode(200);
        }

        [Authorize("rolePolicy")]
        [HttpGet]
        public StatusCodeResult roletest()
        {
            return StatusCode(200);
        }
    }
}

至此,全部代码完成,准备验证
首先测试一下Login,看能否返回token
在这里插入图片描述其次,测试一下携带tokentest方法
在这里插入图片描述
最后测试一下,指定名称的认证
在这里插入图片描述

3、代码下载

代码还在审核中,待审核后,将免费下载

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

yaml语法+yaml配置文件

yaml语法 k:(空格)v > 表示一对键值对空格必须有 yaml拥有严格的空格缩进格式控制&#xff0c;以空格的缩进来控制层级关系&#xff1b;只要是左对齐的一列数据&#xff0c;都是同一个层级的 spring:thymeleaf:cache: true# 检查模板是否存在&#xff0c;然后再呈现check…

通义灵码-阿里云推出的AI智能编码助手

通义灵码体验地址 标题通义灵码是什么&#xff1f; 通义灵码是由阿里巴巴推出的基于通义大模型的智能编码辅助工具&#xff0c;提供行级/函数级实时续写、自然语言生成代码、单元测试生成、代码注释生成、代码解释、研发智能问答、异常报错排查等能力&#xff0c;并针对阿里云…

Bug 解决 | 前端无法正确请求后端接口并得到响应?

目录 1、配置问题 2、代码问题 3、网络问题 前端请求后端接口发现得到的响应不对&#xff0c;或者通过 f12 明明看到了后端的响应&#xff0c;但是前端页面无法正常的展示出来。 这种情况该怎么排查呢&#xff1f;这篇我们就来好好的理一理&#xff01; 1、配置问题 1&am…

浅谈取样器插件之jp@gc - UDP Request

浅谈取样器插件之jpgc - UDP Request JPgc - UDP Request允许用户在性能测试中发送UDP&#xff08;User Datagram Protocol&#xff09;数据包。这对于测试那些依赖UDP协议进行通信的应用程序和服务特别有用&#xff0c;比如某些物联网&#xff08;IoT&#xff09;设备、在线游…

我在高职教STM32——I2C通信入门(2)

大家好,我是老耿,高职青椒一枚,一直从事单片机、嵌入式、物联网等课程的教学。对于高职的学生层次,同行应该都懂的,老师在课堂上教学几乎是没什么成就感的。正是如此,才有了借助CSDN平台寻求认同感和成就感的想法。在这里,我准备陆续把自己花了很多心思设计的教学课件分…

QT输入组、QT显示组

目录 QT输入组 ​编辑 Combo Box&#xff08;下拉菜单部件&#xff09; Font Combo Box&#xff08;显示系统中可用的字体&#xff09; Line Edit&#xff08;行编辑器&#xff09; Text Edit&#xff08;文本编辑器&#xff09; Plain Text Edit&#xff08;纯文本编辑…

干货实操分享:6个禁用外来u盘的方法

禁用外来U盘是保护计算机系统和数据安全的重要措施之一。以下是六个禁用外来U盘的方法&#xff0c;旨在帮助您有效防止未经授权的U盘接入计算机&#xff1a; 1. 使用组策略编辑器&#xff08;Windows系统&#xff09; 步骤&#xff1a; 打开“运行”对话框&#xff0c;输入g…

Covalent(CXT)与Sei合作,为扩展以太坊应用提供数据解决方案

Covalent Network&#xff08;CXT&#xff09;是领先的模块化数据基础设施层&#xff0c;致力于解决长期数据可用性&#xff0c;并为 AI 提供可验证的结构化数据。目前 Covalent Network&#xff08;CXT&#xff09;已经与首个并行化 EVM 区块链——Sei 达成了新的合作&#xf…

cf 练习3

cf 955 div.2 D (二维前缀和 裴蜀定理) 设原本 有雪帽的点&#xff08;设为1&#xff09; 和 没有学帽&#xff08;设为0&#xff09;的点 差值为 dif 当边长为k的矩阵覆盖后 &#xff0c; 设矩阵中有x1个有雪帽的点和 x2个没有雪帽的点 &#xff0c;那么此时的dif 值 就会减…

【建议收藏】AI大模型学习资源大全,免费分享

前言 马斯克旗下的AI大模型企业xAI&#xff0c;官宣拿到巨额融资60亿美元。 估值冲向240亿美元&#xff08;约1304亿&#xff09;&#xff0c;一举跃升为AI大模型“最猛独角兽”&#xff01; 资本大佬Valor Equity Partners、红杉资本、国王控股、沙特王子-Bin Talal、Vy Cap…

同态加密和SEAL库的介绍(四)CKKS 方案

写在前面&#xff1a; 上篇介绍了 BFV 的 Batch Encoder&#xff0c;其虽然充分利用了槽空间&#xff0c;但是每个槽只包含一个模 plain_modulus 的整数&#xff0c;除非 plain_modulus 非常大&#xff0c;否则我们可能会很快遇到数据类型溢出并在需要进行整数计算时得到意外的…

【Docker安装】Ubuntu系统下离线部署Docker环境教程

【Docker安装】Ubuntu系统下离线部署Docker环境教程 前言一、本次实践介绍1.1 本次实践规划1.2 本次实践简介二、检查本地环境2.1 检查操作系统版本2.2 检查内核版本2.3 更新软件源三、卸载Docker四、下载安装包4.1 创建目录4.2 官网下载五、部署Docker环境5.1 解压安装包5.2 复…

北京青蓝智慧科技:160个项目通过“数据要素×”大赛湖北分赛初赛

近日&#xff0c;2024年“数据要素”大赛的湖北分赛在武汉热烈开幕。 八个赛道的参赛队伍齐聚一堂&#xff0c;共同争夺数据创新先锋的殊荣。 经过激烈的角逐&#xff0c;初赛评审专家团最终评选出了160个入围项目&#xff0c;每个赛道分别有20个项目脱颖而出&#xff0c;其中…

Unity物理模块 之 2D效应器

本文仅作笔记学习和分享&#xff0c;不用做任何商业用途 本文包括但不限于unity官方手册&#xff0c;unity唐老狮等教程知识&#xff0c;如有不足还请斧正​ 1.什么是效应器 2D 效应器 - Unity 手册 2D 效应器是与 2D 碰撞器一起使用的组件&#xff0c;相当于预先编写好的插…

8月8日笔记

8月8日笔记 msf常见命令 启动MSF控制台 msfconsole: 启动MSF控制台。msfconsole -h: 显示帮助菜单。msfconsole -q: 启动MSF控制台并立即退出。 导航和管理 back: 返回上一级菜单。exit: 退出MSF控制台。banner: 显示MSF的横幅。cd: 更改工作目录。color: 开启或关闭彩色输…

深度学习任务中的 Zero-shot、One-shot 和 Few-shot 是什么?

深度学习任务中的 Zero-shot、One-shot 和 Few-shot 是什么&#xff1f; 在深度学习的任务中&#xff0c;Zero-shot、One-shot 和 Few-shot 学习是处理有限数据的三种重要方法。这些方法尤其在计算机视觉领域表现得非常突出。接下来&#xff0c;我们将详细探讨这三种学习方式&…

【ML】self-supervised Learning for speech and Image

【ML】self-supervised Learning for speech and Image 1. self-supervised Learning for speech and Image1.1 自监督学习在语音处理领域的方法及其特点1.2 自监督学习在图像处理领域的方法及其特点 2. Predictive Approach2.1 特点2.2 适用场景 3. contrastive Learning4. 语…

鸿蒙开发5.0【Debug调试】运维

Debug 介绍 本示例通过使用ohos.hidebug接口来获取当前应用内存使用情况。 )效果预览 使用说明 1.点击界面右上方Debug图标&#xff0c;弹出Debug信息界面&#xff0c;显示当前应用内存使用情况&#xff1b; 2.再次点击右上方Debug图标&#xff0c;Debug信息界面消失。 具…

Zed : 一款不容错过的编码神器

简介 “Code at the speed of thought“ — 用过之后都说好&#xff0c;名副其实&#xff5e; 不过&#xff0c;请记住它的定位是“编辑器、编辑器、编辑器”&#xff08;重要的事情说三遍&#xff09; 一切皆可配置 步入正题&#xff0c;开始配置&#xff5e;&#xff01; 配…

嵌入式学习之文件IO和标准IO

IO概述 I/O是Input/Output的缩写&#xff0c;指的是输入/输出。在计算机科学和工程领域&#xff0c;I/O是指计算机系统与外部环境或内部组件之间进行数据交换的过程和机制。 用户I/O 用户通过输入设备与计算机交互。例如&#xff0c;通过键盘输入文字、通过鼠标点击界面等。…