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. Linux内存泄露案例分析和内存管理分享

    作者:李遵举 一.问题 近期我们运维同事接到线上LB(负载均衡)服务内存报警,运维同事反馈说LB集群有部分机器的内存使用率超过80%,有的甚至超过90%,而且内存使用率还再不停的增长.接到内存报警的消 ...

  2. kubeedge架构与核心设计---https://bbs.huaweicloud.com/webinar/100009

    今天是kubeedge的第一节课,今天主要带大家回顾一下云原生和边缘计算的发展历程 然后我们会重点介绍一下kubeedge这个项目,他的设计背景和核心理念与我们整体的架构 首先是我们来简单回归一下云原 ...

  3. Devexpress 图表显示数据标签

    dev的图标功能非常强大其中有一些设置可以更好的展现出数据 设置Series的标签 series.LabelsVisibility = DevExpress.Utils.DefaultBoolean. ...

  4. day10 Test

    public class Test{ public static void main(String[] args){ fun1(); } /**1. * 有2个数组,第一个数组内容为:[黑龙江省,浙江 ...

  5. 靶机练习: Vikings

    靶机:Vikings 准备工作 靶机地址: https://download.vulnhub.com/vikings/Vikings.ova MD5 校验:84f72c38e2458e01d00db9 ...

  6. Java反射与安全问题

    1.Java反射机制 Java反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的 ...

  7. 【大数据课程】高途课程实践-Day01:Python编写Map Reduce函数实现各商品销售量展示(类似wordcount)

    〇.概述 1.工具 http://www.dooccn.com/python3/ 在线运行Python代码 2.步骤 (1)⽣成代码测试数据 (2)编写Mapper逻辑 (3)编写Reducer逻辑 ...

  8. sql周报

    数据库分类 1.关系型数据库 Mysql Qracle MariaDB PostgreSQL mysql:开源免费 使用最广 性价比最高 Oracle:收费 但安全性高 PostgreSQL:开源免费 ...

  9. L1-064 估值一亿的AI核心代码 (20分)

    L1-064 估值一亿的AI核心代码 (20分) 以上图片来自新浪微博. 本题要求你实现一个稍微更值钱一点的 AI 英文问答程序,规则是: 无论用户说什么,首先把对方说的话在一行中原样打印出来: 消除 ...

  10. Python全栈工程师之从网页搭建入门到Flask全栈项目实战(6) - Flask表单的实现

    1.表单介绍 1.1.表单知识回顾 常见的表单元素: 表单标签<form> action:表单提交的URL地址 method:表单请求的方式(GET/POSt) enctype:请求内容的 ...