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. 2022!影响百万用户金融信用评分,Equifax被告上法庭,罪魁祸首——『数据漂移』!⛵

    作者:韩信子@ShowMeAI 数据分析实战系列:https://www.showmeai.tech/tutorials/40 机器学习实战系列:https://www.showmeai.tech/t ...

  2. php 程序员进化之路

    1.目标明确 2.消除干扰 3.自我激励 鸟哥 --2018年11月17日php年会

  3. golang 概念理解

    https://www.youtube.com/watch?v=cN_DpYBzKso https://blog.golang.org/gos-declaration-syntax 1.golang ...

  4. vcenter密码设置永不过期

    由于机房断电,原本的vcenter重启后web页面出现报错,为尽快恢复vcenter管理机,直接停用了旧的vcenter虚机,重新安装了一台vcenter,两个月后,页面开始报警密码即将到期: 经查阅 ...

  5. 读Bilgin Ibryam 新作 《Dapr 是一种10倍数 平台》

    Bilgin Ibryam 最近加入了开发者软件初创公司Diagrid Inc,他是Apache Software Foundation 的 committer 和成员.他也是一个开源的布道师,并且是 ...

  6. element ui 使用Tooltip 文字提示,文本内容中输入空格

    '\u00a0'是'nbsp'的16进制表示 其他空格也可以使用下表的值: 代码如下 <el-tooltip effect="light" placement="t ...

  7. 如何在kali Linux上安装VMware Tools

    作用: 1.让虚拟机和本地上的文件可以互传,直接拖动就可以实现转接 2.可在虚拟机上执行本地脚本 3.本地时钟与虚拟机同步 4........... 方法: 1.运行虚拟机 2.在上方菜单栏中点击安装 ...

  8. 小程序canvas2D绘制印章,话不多说,直接上代码

    效果图:  CanvasContext 是旧版的接口,不维护了, 新版 Canvas 2D 接口与 Web 一致 官方文档: https://developers.weixin.qq.com/mini ...

  9. C++初阶(stack+queue)

    stack stack介绍 stack是一种先进后出的数据结构,只有一个出口,类似于栈.stack容器哦允许新增元素,移除元素,取得栈顶元素,但是除了最顶端之后,没有任何其他办法可以存取stack的其 ...

  10. 关于 .NET 在不同操作系统中 IO 文件路径拼接方法结升级 .NET 7 后注意到的一个小坑

    .NET 现在支持跨平台这件事情已经是众所周知的特点了,虽然平台整体支持跨平台了,但是我们的代码如果真的想要实现跨平台运行其实还是有些小细节要注意的,今天想要记录分享的就是关于 文件I/O操作时路径的 ...