.NET & JWT

Wesley13
• 阅读 863

使用 JWT 库

JWT,a JWT(JSON Web Token) implementation for .NET

该库支持生成和解析JSON Web Token

你可以直接通过Nuget获取,也可以自己下载和编译源码.

// 不要忘了 using
using JWT;
using JWT.Algorithms;
using JWT.Builder;

// 自定义秘钥
// jwt 的生成和解析都需要使用
const string secret = "GQDstcKsx0NHjPOuXOYg5MbeJ1XT0uFiwDVvVBrk";

创建 JWT

// 使用 JwtBuilder 来生成 token
string token = new JwtBuilder()
    .WithAlgorithm(new HMACSHA256Algorithm()) // 使用算法
    .WithSecret(secret) // 使用秘钥
    .AddClaim("exp", DateTimeOffset.UtcNow.AddHours(1).ToUnixTimeSeconds())
    .AddClaim("claim2", "claim2-value")
    .Build();

Console.WriteLine(token);

生成的 token 如下:

// 注意:是通过.符号分隔成3段,分别对应的是header.payload.signature
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1Mjg3MjA2NTEsImNsYWltMiI6ImNsYWltMi12YWx1ZSJ9.56xcZALlJuwROe3qssCbe_DDjpQShk-Ik7kWAzONWFU

生成后可以分发出去, 别人拿着 token 来请求接口的时候, 我们需要解析验证

// 使用 JwtBuilder 来解析 token
try
{
    string json = new JwtBuilder()
        .WithSecret(secret)
        .MustVerifySignature()
        .Decode(token);
    
    Console.WriteLine(json);
}
catch (TokenExpiredException)
{
    Console.WriteLine("token 已过期");
}
catch (SignatureVerificationException)
{
    Console.WriteLine("token 签名无效");
}

解析后得到的 json 字符串如下:

{    
    "exp": 1528721303,
    "claim2": "claim2-value"
}

使用 Microsoft.IdentityModel.Tokens 库

  • 新建一个 ASP.NET Core API 项目
  • 新增一个控制器 AuthController

生成 JWT

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace WebApplication1.Controllers
{
    [ApiController]
    [Route("[controller]/[action]")]
    public class AuthController : Controller
    {
        private readonly IConfiguration _configuration;

        public AuthController(IConfiguration configuration)
        {
            _configuration = configuration;
        }
        
        [HttpGet]
        public IActionResult Token()
        {
            var claims = new[]
            {
                new Claim(type: ClaimTypes.Name, value: "username")
            };

            var issuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["IssuerSigningKey"]));
            var creds = new SigningCredentials(issuerSigningKey, SecurityAlgorithms.HmacSha256);
            //.NET Core’s JwtSecurityToken class takes on the heavy lifting and actually creates the token.
            /**
             * Claims (Payload)
                Claims 部分包含了一些跟这个 token 有关的重要信息。 JWT 标准规定了一些字段,下面节选一些字段:
                iss: The issuer of the token,token 是给谁的
                sub: The subject of the token,token 主题
                exp: Expiration Time。 token 过期时间,Unix 时间戳格式
                iat: Issued At。 token 创建时间, Unix 时间戳格式
                jti: JWT ID。针对当前 token 的唯一标识
                除了规定的字段外,可以包含其他任何 JSON 兼容的字段。
             * */
            var token = new JwtSecurityToken(
                issuer: "test.com", // 
                audience: "test.com",
                claims: claims,
                expires: DateTime.Now.AddMinutes(1),
                signingCredentials: creds);

            return Ok(new
            {
                access_token = new JwtSecurityTokenHandler().WriteToken(token: token)
            });
        }
    }
}

生成的 JWT 可以放到 jwt.io 里验证一下.

使用 IdentityServer4 库

IdentityServerTools 是 IdentityServer4 中的一个工具类, 封装了 JWT 生成方法, 以便使用.

按照套路, 注入 IdentityServer4 服务, 这里我们仅使用工具类来生成 JWT, 所以不需要配置其他东西.

public void ConfigureServices(IServiceCollection services)
{
    services.AddIdentityServer()
        .AddDeveloperSigningCredential();
    // 省略其他
}

在控制器中构造函数注入使用

using IdentityServer4;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Security.Claims;
using System.Threading.Tasks;

// For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860

namespace WebApplication1.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class AuthController : ControllerBase
    {
        private readonly IdentityServerTools _identityServerTools;

        public AuthController(IdentityServerTools identityServerTools)
        {
            _identityServerTools = identityServerTools;
        }

        [HttpGet]
        public async Task<IActionResult> TokenAsync()
        {
            // 完整的场景, 应该验证用户密码
            Claim[] claims = new Claim[]
            {
                new Claim(type: ClaimTypes.NameIdentifier, value: Guid.NewGuid().ToString("N")),
                new Claim(type: ClaimTypes.Name, value: "admin"),
                new Claim(type: ClaimTypes.Gender, value: "man"),
                new Claim(type: ClaimTypes.Email, value: "xxx@xxx.com"),
                new Claim(type: "custom", value: "value"),
            };            
            
            // 可以按自己需求, 返回指定结构的数据
            return Ok(value: await _identityServerTools.IssueJwtAsync(lifetime: 3600, claims: claims));            
        }
    }
}

这个时候访问 /api/auth 应该就能看到一段老长老长的 JWT 了, 可以扔到 jwt.io 里验证下.

身份认证

上面介绍了几种不同库生成 JWT 的方法, 当别人拿着我们分发出去的 JWT 来访问我们的接口时, 需要对其进行身份认证

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;

namespace WebApplication1
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = false, // 是否验证 Issuer
                    ValidIssuer = "test.com",
                    ValidateAudience = false, // 是否验证 Audience
                    ValidAudience = "",
                    ValidateIssuerSigningKey = true, // 是否验证签名秘钥
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["IssuerSigningKey"])),
                    ValidateLifetime = true, // 是否验证失效时间
                };
            });
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseAuthentication(); // 使用身份验证
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseMvc();
        }
    }
}

参考

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Easter79 Easter79
3年前
springboot结合jwt实现基于restful接口的身份认证
基于restful接口的身份认证,可以采用jwt的方式实现,想了解jwt,可以查询相关资料,这里不做介绍~下面直接看如何实现1、首先添加jwt的jar包,pom.xml中添加依赖包:<dependency<groupIdio.jsonwebtoken</groupId
Stella981 Stella981
3年前
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解2016年09月02日00:00:36 \牧野(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fme.csdn.net%2Fdcrmg) 阅读数:59593
Stella981 Stella981
3年前
JWT的优点和实现Token认证的安全问题
JWT的优点和实现Token认证的安全问题一、什么是JWTJWT——Jsonwebtoken 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准,可实现无状态、分布式的Web应用授权。二、我们为什么需要JWT?
Stella981 Stella981
3年前
JSON Web Token 入门教程
JWT是什么?JSONWebToken(缩写JWT)是目前最流行的跨域认证解决方案。它是有三部分组成,示例如下,具体的讲解如下(jwt是不会有空行的,下面只是为了显示,便使用了换行看着比较方便)。1.eyJhbGciOiJIUzI1NiIsInR5cCI6I
Stella981 Stella981
3年前
Django REST framework JWT学习
1.JWT学习在用户注册或登录后,我们想记录用户的登录状态,或者为用户创建身份认证的凭证。我们不再使用Session认证机制,而使用JsonWebToken认证机制。Jsonwebtoken(JWT),是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC7519).该token被设计为紧凑且安全的,
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这