|
开发环境
系统版本: win10
.NET SDK: NET8
开发工具:vscode
参考引用:使用 dotnet user-jwts 管理开发中的 JSON Web 令牌
注意:以下示例中的端口、token等需替换成你的环境中的信息
创建项目
运行以下命令来创建一个空的 Web 项目,并添加 Microsoft.AspNetCore.Authentication.JwtBearer NuGet 包:- dotnet new web -o MyJWT
- cd MyJWT
- dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
复制代码 将 Program.cs 的内容替换为以下代码(略微改动):- using System.Security.Claims;
- var builder = WebApplication.CreateBuilder(args);
- builder.Services.AddAuthorization();
- // 默认的Scheme是Bearer
- // builder.Services.AddAuthentication("Bearer").AddJwtBearer();
- builder.Services.AddAuthentication().AddJwtBearer();
- var app = builder.Build();
- app.UseAuthorization();
- app.MapGet("/", () => "Hello, World!");
- app.MapGet("/secret", (ClaimsPrincipal user) => $"Hello {user.Identity?.Name}. My secret")
- .RequireAuthorization();
- app.Run();
复制代码 运行项目并访问接口返回以下内容- PS D:\Learn\MyJWT> curl.exe -i http:///localhost:5276
- HTTP/1.1 200 OK
- Content-Type: text/plain; charset=utf-8
- Date: Mon, 04 Dec 2023 00:43:03 GMT
- Server: Kestrel
- Transfer-Encoding: chunked
- Hello, World!
复制代码 创建 JWT
- PS D:\Learn\MyJWT> dotnet user-jwts create
- New JWT saved with ID 'c28b968'.
- Name: Lingpeng
- Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6IkxpbmdwZW5nIiwic3ViIjoiTGluZ3BlbmciLCJqdGkiOiJjMjhiOTY4IiwiYXVkIjpbImh0dHA6Ly9sb2NhbGhvc3Q6Mjk3NTQiLCJodHRwczovL2xvY2FsaG9zdDo0NDM2MCIsImh0dHA6Ly9sb2NhbGhvc3Q6NTI3NiIsImh0dHBzOi8vbG9jYWxob3N0OjcyNTMiXSwibmJmIjoxNzAxNjQ5Nzk2LCJleHAiOjE3MDk1MTIxOTYsImlhdCI6MTcwMTY0OTc5NiwiaXNzIjoiZG90bmV0LXVzZXItand0cyJ9.l52s9_7oNjIKL96TysgdE0k970fUS9FoLTu2xRs-IPo
复制代码 这个命令做了3件事:
- 更新项目的 appsettings.Development.json,添加了Authentication节点
- 更新项目的 MyJWT.csproj,添加了UserSecretsId 配置
- 创建了机密文件 %APPDATA%\Microsoft\UserSecrets\\user-jwts.json与%APPDATA%\Microsoft\UserSecrets\\secrets.json,机密管理参考
我们看下这两个机密文件
user-jwts.json- {
- "c28b968": {
- "Id": "c28b968",
- "Scheme": "Bearer",
- "Name": "Lingpeng",
- "Audience": "http://localhost:29754, https://localhost:44360, http://localhost:5276, https://localhost:7253",
- "NotBefore": "2023-12-04T00:29:56+00:00",
- "Expires": "2024-03-04T00:29:56+00:00",
- "Issued": "2023-12-04T00:29:56+00:00",
- "Token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6IkxpbmdwZW5nIiwic3ViIjoiTGluZ3BlbmciLCJqdGkiOiJjMjhiOTY4IiwiYXVkIjpbImh0dHA6Ly9sb2NhbGhvc3Q6Mjk3NTQiLCJodHRwczovL2xvY2FsaG9zdDo0NDM2MCIsImh0dHA6Ly9sb2NhbGhvc3Q6NTI3NiIsImh0dHBzOi8vbG9jYWxob3N0OjcyNTMiXSwibmJmIjoxNzAxNjQ5Nzk2LCJleHAiOjE3MDk1MTIxOTYsImlhdCI6MTcwMTY0OTc5NiwiaXNzIjoiZG90bmV0LXVzZXItand0cyJ9.l52s9_7oNjIKL96TysgdE0k970fUS9FoLTu2xRs-IPo",
- "Scopes": [],
- "Roles": [],
- "CustomClaims": {}
- }
- }
复制代码 secrets.json- {
- "Authentication:Schemes:Bearer:SigningKeys": [
- {
- "Id": "ff20683d",
- "Issuer": "dotnet-user-jwts",
- "Value": "lDOFmIuEDelFKU0zAaLoT2qYOFDRZGDDTv5FyTa36V8=",
- "Length": 32
- }
- ]
- }
复制代码 测试JWT
我们重新运行程序,用直接访问与携带token两种方式访问/secret接口- PS D:\Learn\MyJWT> curl.exe -i http://localhost:5276/secret
- HTTP/1.1 401 Unauthorized
- Content-Length: 0
- Date: Mon, 04 Dec 2023 00:43:25 GMT
- Server: Kestrel
- WWW-Authenticate: Bearer
- PS D:\Learn\MyJWT>
- PS D:\Learn\MyJWT>
- PS D:\Learn\MyJWT> curl.exe -i -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6IkxpbmdwZW5nIiwic3ViIjoiTGluZ3BlbmciLCJqdGkiOiJjMjhiOTY4IiwiYXVkIjpbImh0dHA6Ly9sb2NhbGhvc3Q6Mjk3NTQiLCJodHRwczovL2xvY2FsaG9zdDo0NDM2MCIsImh0dHA6Ly9sb2NhbGhvc3Q6NTI3NiIsImh0dHBzOi8vbG9jYWxob3N0OjcyNTMiXSwibmJmIjoxNzAxNjQ5Nzk2LCJleHAiOjE3MDk1MTIxOTYsImlhdCI6MTcwMTY0OTc5NiwiaXNzIjoiZG90bmV0LXVzZXItand0cyJ9.l52s9_7oNjIKL96TysgdE0k970fUS9FoLTu2xRs-IPo" http://localhost:5276/secret
- HTTP/1.1 200 OK
- Content-Type: text/plain; charset=utf-8
- Date: Mon, 04 Dec 2023 00:45:42 GMT
- Server: Kestrel
- Transfer-Encoding: chunked
- Hello Lingpeng. My secret
复制代码 至此我们已经实现了JwtBearer的初步使用
一点点改动
示例采用了机密管理,我们也可以把机密文件中的内容迁移至项目中(推荐用机密管理),我们修改MyJWT.csproj与appsettings.Development.json如下- <Project Sdk="Microsoft.NET.Sdk.Web">
- <PropertyGroup>
- <TargetFramework>net8.0</TargetFramework>
- <Nullable>enable</Nullable>
- <ImplicitUsings>enable</ImplicitUsings>
-
- </PropertyGroup>
- <ItemGroup>
- <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.0" />
- </ItemGroup>
- </Project>
复制代码- {
- "Logging": {
- "LogLevel": {
- "Default": "Information",
- "Microsoft.AspNetCore": "Warning"
- }
- },
- "Authentication": {
- "Schemes": {
- "Bearer": {
- "ValidAudiences": [
- "http://localhost:29754",
- "https://localhost:44360",
- "http://localhost:5276",
- "https://localhost:7253"
- ],
- "ValidIssuer": "dotnet-user-jwts",
- "SigningKeys": [
- {
- "Id": "ff20683d",
- "Issuer": "dotnet-user-jwts",
- "Value": "lDOFmIuEDelFKU0zAaLoT2qYOFDRZGDDTv5FyTa36V8=",
- "Length": 32
- }
- ]
- }
- }
- }
- }
复制代码 修改完成后实现相同的功能
JWT Token生成示例
- app.MapGet("/login", (string UserName, string Password, [FromServices] IOptionsMonitor<JwtBearerOptions> optionsMonitor) =>
- {
- // 1. 密码验证
- // TODO
- // 2. 生成
- var parameters = optionsMonitor.Get(JwtBearerDefaults.AuthenticationScheme).TokenValidationParameters;
- var signingKey = parameters.IssuerSigningKeys.First();
- var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256Signature);
- var header = new JwtHeader(signingCredentials);
- var payload = new JwtPayload {
- { JwtRegisteredClaimNames.UniqueName, UserName },
- { JwtRegisteredClaimNames.Iss, parameters.ValidIssuers.First() },
- { JwtRegisteredClaimNames.Aud, parameters.ValidAudiences },
- { JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds() },
- { JwtRegisteredClaimNames.Nbf, DateTimeOffset.UtcNow.ToUnixTimeSeconds() },
- { JwtRegisteredClaimNames.Exp, DateTimeOffset.UtcNow.AddMinutes(30).ToUnixTimeSeconds() }
- };
- var jwtSecurityToken = new JwtSecurityToken(header, payload);
- var jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
- var token = jwtSecurityTokenHandler.WriteToken(jwtSecurityToken);
- return token;
- });
复制代码 进行一下验证- PS D:\Learn\MyJWT> curl.exe -i "http://localhost:5276/login?username=admin&password=1111"
- HTTP/1.1 200 OK
- Content-Type: text/plain; charset=utf-8
- Date: Mon, 04 Dec 2023 05:03:36 GMT
- Server: Kestrel
- Transfer-Encoding: chunked
- eyJhbGciOiJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNobWFjLXNoYTI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6ImFkbWluIiwiaXNzIjoiZG90bmV0LXVzZXItand0cyIsImF1ZCI6WyJodHRwOi8vbG9jYWxob3N0OjI5NzU0IiwiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzNjAiLCJodHRwOi8vbG9jYWxob3N0OjUyNzYiLCJodHRwczovL2xvY2FsaG9zdDo3MjUzIl0sImlhdCI6MTcwMTY2NjIxNiwibmJmIjoxNzAxNjY2MjE2LCJleHAiOjE3MDE2NjgwMTZ9.P9t7vIFfM7cddRPs4OQUTVVdo57nWTLt_ea2UynGUpo
- PS D:\Learn\MyJWT>
- PS D:\Learn\MyJWT>
- PS D:\Learn\MyJWT> curl.exe -i -H "Authorization: Bearer eyJhbGciOiJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNobWFjLXNoYTI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6ImFkbWluIiwiaXNzIjoiZG90bmV0LXVzZXItand0cyIsImF1ZCI6WyJodHRwOi8vbG9jYWxob3N0OjI5NzU0IiwiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzNjAiLCJodHRwOi8vbG9jYWxob3N0OjUyNzYiLCJodHRwczovL2xvY2FsaG9zdDo3MjUzIl0sImlhdCI6MTcwMTY2NjIxNiwibmJmIjoxNzAxNjY2MjE2LCJleHAiOjE3MDE2NjgwMTZ9.P9t7vIFfM7cddRPs4OQUTVVdo57nWTLt_ea2UynGUpo" http://localhost:5276/secret
- HTTP/1.1 200 OK
- Content-Type: text/plain; charset=utf-8
- Date: Mon, 04 Dec 2023 05:03:50 GMT
- Server: Kestrel
- Transfer-Encoding: chunked
- Hello admin. My secret
复制代码 来源:https://www.cnblogs.com/lludcmmcdull/archive/2023/12/04/17874175.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
|