JWT介绍

参考文章 https://www.cnblogs.com/cjsblog/p/9277677.html

一、.NET 中使用

1. NuGet包

搜索JWT,下载安装(本人用的是8.2.3版本)

2. 自定义帮助类

2.1 新建 IHttpResponseResult interface接口

    public interface IHttpResponseResult
{
} /// <summary>
/// 响应数据输出泛型接口
/// </summary>
/// <typeparam name="T"></typeparam>
// ReSharper disable once UnusedTypeParameter
public interface IHttpResponseResult<T> : IHttpResponseResult
{
}

2.2 新建 HttpResponseResult 数据响应类

    public class HttpResponseResult<T> : IHttpResponseResult<T>
{
/// <summary>
/// 状态码
/// </summary>
public int Code { get; set; } /// <summary>
/// 消息
/// </summary>
public string Message { get; set; } /// <summary>
/// 数据
/// </summary>
public T Data { get; set; } /// <summary>
/// 成功
/// </summary>
/// <param name="data">数据</param>
/// <param name="msg">消息</param>
public HttpResponseResult<T> Success(T data = default, string msg = null)
{
Code = 0;
Data = data;
Message = msg;
return this;
} /// <summary>
/// 失败
/// </summary>
/// <param name="code">状态码</param>
/// <param name="msg">消息</param>
/// <param name="data">数据</param>
/// <returns></returns>
public HttpResponseResult<T> Fail(T data = default, int code = -1, string msg = null)
{
Code = code;
Message = msg;
Data = data;
return this;
}
} /// <summary>
/// 响应数据静态输出
/// </summary>
public static class HttpResponseResult
{
/// <summary>
/// 成功
/// </summary>
/// <param name="data">数据</param>
/// <param name="msg">消息</param>
/// <returns></returns>
public static IHttpResponseResult Success<T>(T data, string msg = "message")
{
return new HttpResponseResult<T>().Success(data, msg);
} /// <summary>
/// 失败
/// </summary>
/// <param name="data">数据</param>
/// <param name="msg">消息</param>
/// <param name="code">状态码</param>
/// <returns></returns>
public static IHttpResponseResult Fail<T>(T data, string msg = null, int code = -1)
{
return new HttpResponseResult<T>().Fail(data, code, msg);
}
}

3.生成JWT Token

3.1 新建Conteoller

新建 LoginController 并且新建一个生成 Token 的方法 Login

    /// <summary>
/// JWT授权
/// </summary>
[RoutePrefix("api/login")]
public class LoginController : ApiController
{
private readonly string secretKey = "JwtSecretKey";//Jwt密钥,自定义
private readonly int tokenExpire = 2;//Token过期时间 /// <summary>
/// 授权登录获取Token
/// </summary>
/// <param name="loginModel"></param>
/// <returns></returns>
[HttpPost, Route("GetToken")]
public IHttpResponseResult Login([FromBody] Login loginModel)
{
dynamic obj = new ExpandoObject();
try
{
var userName = loginModel.UserName;
var userPwd = loginModel.UserPwd;
//var loginRes = ChatUserDao.GetJwtUser(userName, userPwd).IsNull(); //自己的数据库验证
var loginRes = "Dennis".Equals(userName) && "123".Equals(userPwd);
if (loginRes)
{
return HttpResponseResult.Fail(obj, "The user is not found or password is error.");
} var expireTime = DateTime.Now.AddHours(tokenExpire);
//身份验证信息,这里存放的就是payload信息
var jwtToken = new JwtToken { AuthUserName = userName, ExpireTime = expireTime };
var key = Encoding.UTF8.GetBytes(secretKey);
IJwtAlgorithm algorithm = new HMACSHA256Algorithm(); //加密方式
IJsonSerializer serializer = new JsonNetSerializer(); //序列化Json
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder(); //base64加解密
IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder); //JWT编码
var token = encoder.Encode(jwtToken, key); //生成令牌 obj.Token = token;
obj.ExpireTime = expireTime; return HttpResponseResult.Success(obj, "Get Token Success.");
}
catch (Exception e)
{
LogFileHelper.WriteLog("GetToken", e.ToExceptionString());
return HttpResponseResult.Fail(obj, e.ToExceptionString());
}
}
}

3.2 新建JwtToken 模型类

    /// <summary>
/// Jwt Token
/// </summary>
public class JwtToken
{
/// <summary>
/// 授权者
/// </summary>
public string AuthUserName { get; set; } /// <summary>
/// Token过期时间
/// </summary>
public DateTime ExpireTime { get; set; }
}

4. 新建Attribute类验证Token

App_Start项目文件加中新建一个ApiAuthAttribute类,继承自AuthorizeAttribute

    /// <summary>
/// Jwt 授权验证
/// </summary>
public class ApiAuthAttribute : AuthorizeAttribute
{
private readonly string secretKey = "JwtSecretKey";//加密秘钥,与生成Token时的密钥相同
private const string authHeader = "Authorization";//请求头Header中存放JwtToken的Key名称 /// <summary>
/// 判断授权
/// </summary>
/// <param name="httpContext"></param>
/// <returns></returns>
protected override bool IsAuthorized(HttpActionContext httpContext)
{
try
{
var httpHeader = httpContext.Request.Headers;
var token = string.Empty;//获取token foreach (var keyHeader in httpHeader)
{
if (authHeader.Equals(keyHeader.Key))
{
token = keyHeader.Value.FirstOrDefault();
}
} if (token.IsEmpty())
{
return false;
} var key = Encoding.UTF8.GetBytes(secretKey);
IJwtAlgorithm algorithm = new HMACSHA256Algorithm(); //加密方式
IJsonSerializer serializer = new JsonNetSerializer();//序列化Json
IDateTimeProvider provider = new UtcDateTimeProvider();
IJwtValidator validator = new JwtValidator(serializer, provider);
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();//base64加解密
IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, algorithm); //解密
var json = decoder.DecodeToObject<JwtToken>(token, key, true);
if (json.IsNull()) return false;
return json.ExpireTime >= DateTime.Now;
}
catch (Exception e)
{
LogFileHelper.WriteLog(authHeader, e.ToExceptionString());
return false;
}
} /// <summary>
/// 授权失败时调用
/// </summary>
/// <param name="httpContext"></param>
protected override void HandleUnauthorizedRequest(HttpActionContext httpContext)
{
//Token过期时,响应头添加过期标识
httpContext.Response = httpContext.ControllerContext.Request.CreateResponse(
HttpStatusCode.Unauthorized, HttpResponseResult.Fail(false, "Token is not found or expired, authorization failed."));
httpContext.Response.Headers.Add("Token-Expired", "true");
}
}

5. 测试Token验证

    /// <summary>
/// 测试接口
/// </summary>
[RoutePrefix("api/test")]
public class TestController : ApiController
{
/// <summary>
/// Token认证测试
/// </summary>
/// <returns></returns>
[HttpGet, Route("TokenAuth")]
[ApiAuth]
public IHttpResponseResult TokenAuth()
{
return HttpResponseResult.Success(true, "Auth Passed");
}
}

二、.NET Core 中使用

1. NuGet包

搜索JwtBearer,下载安装(本人安装的是5.0.7)

2. 配置Startup

注册JWT中间件,我是单独写了一个类然后引用,你也可以直接写在Startup的ConfigureServices方法中

    /// <summary>
/// JWT授权中间件
/// </summary>
public static class AuthorizationMiddleware
{
/// <summary>
/// 注册授权服务
/// </summary>
/// <param name="services"></param>
public static void AddAuthorizationService(this IServiceCollection services)
{
// 开启Bearer认证
services.AddAuthentication(options =>
{
// 设置默认使用jwt验证方式
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
// 添加JwtBearer服务
.AddJwtBearer(o =>
{
// 令牌验证参数
o.TokenValidationParameters = new TokenValidationParameters
{
// 设置生成token的秘钥
//IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(AppConfig.SecretKey)),
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(AppConfig.SecretKey)),
// 验证秘钥
ValidateIssuerSigningKey = true,
// 验证发布者
ValidateIssuer = true,
// 验证Issure
ValidIssuer = AppConfig.Issuer,//发行人
// 验证接收者
ValidateAudience = true,
// 读配置Audience
ValidAudience = AppConfig.Audience,//订阅人
// 验证过期时间
ValidateLifetime = true,
ClockSkew = TimeSpan.FromSeconds(30),
RequireExpirationTime = true
};
o.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
// 如果过期,则把<是否过期>添加到,返回头信息中
if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
{
context.Response.Headers.Add("Token-Expired", "true");
} return Task.CompletedTask;
}
};
}); //如果没有角色控制到Action则注释下列代码
services.AddAuthorization(options =>
{
options.AddPolicy("User", policy => policy.RequireRole("User").Build());
options.AddPolicy("SystemOrAdmin", policy => policy.RequireRole("Admin", "System")); });
}
}

然后在Startup的ConfigureServices方法中添加引用

services.AddAuthorizationService();

在Startup的Configure方法中使用授权

app.UseRouting()之后和app.UseEndpoints之前添加代码

app.UseAuthentication();//身份验证
app.UseAuthorization();//身份授权

3. JWT自定义帮助类

3.1 JWTHelper

    /// <summary>
/// JWT 帮助类
/// </summary>
public static class JWTHelper
{
/// <summary>
/// 颁发JWT字符串
/// </summary>
/// <param name="tokenModel"></param>
/// <returns></returns>
public static string IssueJwt(UserModel tokenModel)
{
//获取Appsetting配置
var iss = AppConfig.Issuer;
var aud = AppConfig.Audience;
var secret = AppConfig.SecretKey;
var expire = AppConfig.Expire; // 这里存放的是payload信息
var claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.Jti, tokenModel.UserId),
new Claim(JwtRegisteredClaimNames.Iss, iss),
new Claim(JwtRegisteredClaimNames.Aud, aud)
}; // 可以将一个用户的多个角色全部赋予,比如参数System,Admin,那么该token即拥有两个角色;
claims.AddRange(tokenModel.UserName.Split(',').Select(s => new Claim(ClaimTypes.Role, s))); //秘钥 (SymmetricSecurityKey 对安全性的要求,密钥的长度太短会报出异常)
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var jwt = new JwtSecurityToken(
issuer: iss,
claims: claims,
expires: DateTime.Now.AddMinutes(expire),
signingCredentials: credentials);
var jwtHandler = new JwtSecurityTokenHandler();
var encodedJwt = jwtHandler.WriteToken(jwt); return encodedJwt;
} /// <summary>
/// 解析
/// </summary>
/// <param name="jwtStr"></param>
/// <returns></returns>
public static UserModel SerializeJwt(string jwtStr)
{
var jwtHandler = new JwtSecurityTokenHandler();
var jwtToken = jwtHandler.ReadJwtToken(jwtStr);
object role;
try
{
jwtToken.Payload.TryGetValue(ClaimTypes.Role, out role);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
var tm = new UserModel
{
UserId = jwtToken.Id,
UserRole = role != null ? role.ToString() : "",
};
return tm;
}
}

密钥等相关配置动态配置在appsettings.json文件中

  "JwtSetting": {
"Issuer": "DennisDong",
"Audience": "https://www.dennisdong.top",
"SecretKey": "D@1#n$n%i&s.D*0n!g",
"Expire": "2"
}

3.2 UserModel

    /// <summary>
/// 用户Model
/// </summary>
public class UserModel
{
/// <summary>
/// UserId
/// </summary>
public string UserId { get; set; } /// <summary>
/// 角色
/// </summary>
public string UserRole { get; set; } /// <summary>
/// 姓名
/// </summary>
public string UserName { get; set; } /// <summary>
/// 生日
/// </summary>
public DateTime UserBirthDay { get; set; }
}

4. 生成和测试Token

    /// <summary>
/// 登录
/// </summary>
[Route("api/login/[action]")]
[ApiController]
public class LoginController : ControllerBase
{
/// <summary>
/// 登录获取Token
/// </summary>
/// <param name="role"></param>
/// <returns></returns>
[HttpGet]
public IActionResult Login(string role)
{
string token;
var result = false;
if (role.NotNull())
{
//这里只是测试,具体数据验证根据自己需要来即可
token = JWTHelper.IssueJwt(new UserModel
{
UserId = Guid.NewGuid().ToString(),
UserRole = role,
UserName = role,
UserBirthDay = DateTime.Now
});
result = true;
}
else
{
token = " Login Fail.";
} return Ok(new { Status = result, Token = token });
} /// <summary>
/// 解析Token
/// </summary>
/// <returns></returns>
[HttpGet]
//该接口限制只有System 或 Admin 角色(中间件中AddAuthorization方法的配置决定)的Token可以访问
[Authorize("SystemOrAdmin")]
//如果中间件中没有配置AddPolicy,直接使用Authorize即可
//[Authorize]
public IActionResult ParseToken()
{
//需要截取Bearer
var tokenHeader = HttpContext.Request.Headers["Authorization"].ToString().Replace("Bearer ", "");
var user = JWTHelper.SerializeJwt(tokenHeader);
return Ok(user);
}
}

三、Swagger配合JWT使用

请参考文章 https://www.cnblogs.com/dennisdong/p/15719616.html

四、WebAPI 跨域问题

请参考文章 https://www.cnblogs.com/dennisdong/p/15719873.html

.NET 和 .NET Core 使用 JWT 授权验证的更多相关文章

  1. 【从零开始搭建自己的.NET Core Api框架】(四)实战!带你半个小时实现接口的JWT授权验证

    系列目录 一.  创建项目并集成swagger 1.1 创建 1.2 完善 二. 搭建项目整体架构 三. 集成轻量级ORM框架——SqlSugar 3.1 搭建环境 3.2 实战篇:利用SqlSuga ...

  2. .Net Core官方的 JWT 授权验证

    什么是JWT? JSON Web令牌(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间安全地传输信息作为JSON对象.由于此信息是经过数字签名的,因此可以被验 ...

  3. ASP.NET Core 中jwt授权认证的流程原理

    目录 1,快速实现授权验证 1.1 添加 JWT 服务配置 1.2 颁发 Token 1.3 添加 API访问 2,探究授权认证中间件 2.1 实现 Token 解析 2.2 实现校验认证 1,快速实 ...

  4. .Net Core之JWT授权

    一.什么是JWT 文章参考:https://www.leo96.com/article/detail/55 JSON Web令牌(JWT)是一个开放标准(RFC 7519),它定义 了一种紧凑且自包含 ...

  5. NetCoreApi框架搭建三、JWT授权验证)

    1.首先还是粘贴大神的链接 虽然说大神的博客已经讲得很详细了,但是此处还是自己动手好点. 首先配置Startup Swagger的验证 2.新建一个项目存放tokenmodel和生成token并且存入 ...

  6. .NET CORE WebAPI JWT身份验证

    一.appsettings.Json文件配置 配置JWT公用参数. 1 /*JWT设置*/ 2 "JwtSetting": { 3 "Issuer": &quo ...

  7. ASP.NET Core搭建多层网站架构【10-使用JWT进行授权验证】

    2020/01/31, ASP.NET Core 3.1, VS2019, Microsoft.AspNetCore.Authentication.JwtBearer 3.1.1 摘要:基于ASP.N ...

  8. 从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 二十四║ Vuex + JWT 实现授权验证登录

    壹周回顾 哈喽,又是元气满满的一个周一,又与大家见面了,周末就是团圆节了,正好咱们的前后端也要团圆了,为什么这么说呢,因为以后的开发可能就需要前后端一起了,两边也终于会师了,还有几天Vue系列就基本告 ...

  9. .Net Core3.0 WebApi 项目框架搭建 四:JWT权限验证

    .Net Core3.0 WebApi 项目框架搭建:目录 什么是JWT 根据维基百科定义,JWT(读作 [/dʒɒt/]),即JSON Web Tokens,是一种基于JSON的.用于在网络上声明某 ...

  10. ASP.NET Core WebApi基于JWT实现接口授权验证

    一.ASP.Net Core WebApi JWT课程前言 我们知道,http协议本身是一种无状态的协议,而这就意味着如果用户向我们的应用提供了用户名和密码来进行用户认证,那么下一次请求时,用户还要再 ...

随机推荐

  1. c3 linearization详解

    MRO MRO 全称方法解析顺序(Method Resolution Order),在多重继承和多继承存在的时候,寻找属性及方法的顺序. 深度优先(DFS)与广度优先(BFS) python2 所用的 ...

  2. typora使用CSDN图床

    前言 软件下载地址 typora 是一款好用的 markdown 文档编辑器. 我之前研究过CSDN上传图片的接口,前几天发现了Typora 这个好用的软件,可以自定义图床,因为我很多文章图片资源用的 ...

  3. Python3.7.3安装TensorFlow和OpenCV3

    根据python的版本进行下载相应的文件 一.安装TensorFlow 进入网址https://pypi.org/project/tensorflow/#files下载TensorFlow文件 进入下 ...

  4. Promise知一二

    Promise 1.Promise的前置知识 进程(厂房) 程序的运行环境 线程(工人) 线程是实际进行运算的东西 同步 通常情况代码都是自上向下一行一行执行的 前边的代码不执行后边的代码也不会执行 ...

  5. 干电池升压5V,功耗比较低

    干电池升压5V,功耗10uA PW5100干电池升压5V芯片 输出电容: 所以为了减小输出的纹波,需要比较大的输出电容值.但是输出电容过大,就会使得系统的 反应时间过慢,成本也会增加.所以建议使用一个 ...

  6. VideoPipe可视化视频结构化框架更新总结(2022-12-9)

    项目地址:https://github.com/sherlockchou86/video_pipe_c 往期文章:https://www.cnblogs.com/xiaozhi_5638/p/1685 ...

  7. 填坑日志-云网络智慧课堂双网卡Mac地址读取错误的问题及解决

    云网络智慧课堂的双网卡问题记录及解决方案 教师端 其实这里双网卡的问题一直没有解决,分为了两部分,一部分是教师端,一部分是学生端.症状类似,问题也类似,都是在设计之初因为硬件限制可能没有考虑到双网卡的 ...

  8. Win10系统安装U盘,安装纯净版Win10的通用教程

    安装前准备:1.准备8G或8G以上U盘(32G以内).2.制作U盘会格式化U盘,U盘内的重要文件也要事先备份好.操作步骤:1.打开微软下载WIN10网址:(如果网址无法打开,可以下载解压运行附件内的工 ...

  9. freeswitch的gateway配置方案

    概述 freeswitch是一款简单好用的VOIP开源软交换平台. 在voip的网络模型中,网关是我们经常会遇到的概念. 在freeswitch中,如何配置gateway,如何使用好gateway的模 ...

  10. 彻底弄懂Javascript模块导入导出

    笔者开始学习Javascript的时候,对模块不太懂,不知道怎么导入模块,导出模块,就胡乱一通试 比如 import xx from 'test.js' 不起作用,就加个括号 import {xx} ...