NetCoreApi框架搭建三、JWT授权验证)
1.首先还是粘贴大神的链接
虽然说大神的博客已经讲得很详细了,但是此处还是自己动手好点。
首先配置Startup Swagger的验证
2.新建一个项目存放tokenmodel和生成token并且存入缓存
以上是tokenmodel 具体属性可以自定义
缓存帮助类安装nuget包Microsoft.Extensions.Caching.Memory
代码:
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Generic;
using System.Text;
namespace MyFirstFrame.Token.Model
{
/// 缓存
public class RayPIMemoryCache
{
public static MemoryCache _cache = new MemoryCache(new MemoryCacheOptions());
/// 验证缓存项是否存在
///缓存Key
///
public static bool Exists(string key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
object cached;
return _cache.TryGetValue(key,out cached);
}
///
/// 获取缓存
///
///缓存Key
///
public static object Get(string key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
return _cache.Get(key);
}
///
/// 添加缓存
///
///缓存Key
///缓存Value
///滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)
///绝对过期时长
///
public static bool AddMemoryCache(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
_cache.Set(key, value,new MemoryCacheEntryOptions().SetSlidingExpiration(expiresSliding).SetAbsoluteExpiration(expiressAbsoulte));
return Exists(key);
}
}
}
生成token字符串
代码:
using Microsoft.Extensions.Caching.Memory;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text; namespace MyFirstFrame.Token.Model
{
///
/// 令牌类
///
public class RayPIToken
{
public RayPIToken()
{
}
/// 获取JWT字符串并存入缓存
public static string IssueJWT(TokenModel tokenModel, TimeSpan expiresSliding, TimeSpan expiresAbsoulte)
{
DateTime UTC = DateTime.UtcNow;
Claim[] claims = new Claim[]
{
new Claim(JwtRegisteredClaimNames.Sub,tokenModel.Sub),//Subject,
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),//JWT ID,JWT的唯一标识
new Claim(JwtRegisteredClaimNames.Iat, UTC.ToString(), ClaimValueTypes.Integer64),//Issued At,JWT颁发的时间,采用标准unix时间,用于验证过期
};
JwtSecurityToken jwt = new JwtSecurityToken(
issuer: "MyFirstFrame",//jwt签发者,非必须
audience: tokenModel.Uname,//jwt的接收该方,非必须
claims: claims,//声明集合
expires: UTC.AddHours(12),//指定token的生命周期,unix时间戳格式,非必须
signingCredentials: new Microsoft.IdentityModel.Tokens
.SigningCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes("MyFirstFrame's Secret Key")), SecurityAlgorithms.HmacSha256));//使用私钥进行签名加密
var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);//生成最后的JWT字符串
RayPIMemoryCache.AddMemoryCache(encodedJwt, tokenModel, expiresSliding, expiresAbsoulte);//将JWT字符串和tokenModel作为key和value存入缓存
return encodedJwt;
}
}
}
新建中间件:TokenAuth
代码:
using Microsoft.Extensions.Caching.Memory;
using Microsoft.AspNetCore.Http;
using MyFirstFrame.Token.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks; namespace MyFirstFrame.AuthHelper
{
///
/// Token验证授权中间件
///
public class TokenAuth
{
///
/// http委托
///
private readonly RequestDelegate _next;
///
/// 构造函数
///
///
public TokenAuth(RequestDelegate next)
{
_next = next;
}
///
/// 验证授权
///
///
///
public Task Invoke(HttpContext httpContext)
{
//获取请求头部
var headers = httpContext.Request.Headers;
//检测是否包含'Authorization'请求头,如果不包含返回context进行下一个中间件,用于访问不需要认证的API
if (!headers.ContainsKey("Authorization"))
{
return _next(httpContext);
}
var tokenStr = headers["Authorization"];
try
{
string jwtStr = tokenStr.ToString().Substring("Bearer ".Length).Trim();
//验证缓存中是否存在该jwt字符串
if (!RayPIMemoryCache.Exists(jwtStr))
{
return httpContext.Response.WriteAsync("非法请求");
}
TokenModel tm = ((TokenModel)RayPIMemoryCache.Get(jwtStr));
//提取tokenModel中的Sub属性进行authorize认证
List lc = new List();
Claim c = new Claim(tm.Sub + "Type", tm.Sub);
lc.Add(c);
ClaimsIdentity identity = new ClaimsIdentity(lc);
ClaimsPrincipal principal = new ClaimsPrincipal(identity);
httpContext.User = principal;
return _next(httpContext);
}
catch (Exception)
{
return httpContext.Response.WriteAsync("token验证异常");
}
} }
}
在Startup配置注意这里需要放在app.UseMvc();上面
注册缓存和验证:
3.验证使用
为了验证使用我直接写了一个生成token字符串的接口
点击验证,这样你的接口就可以访问成功了。
2019.9.11更新
感觉出现瓶颈了,搭完简单的框架之后就不知道要干嘛了,感觉一下没有目标了,所以就抽空把JWT来深入一下。
前面讲的JWT是存入缓存的,所以用不用JWT生成字符串其实都无所谓,下面讲一下JWT的身份验证。
这生成JWT字符串的类里面加了两个方法,一个是生成字符串,一个是解析字符串的
代码:
///
/// 获取JWT字符串
///
///
///
///
///
public static string IssueJWTNew(TokenModel model)
{
DateTime UTC = DateTime.UtcNow;
Claim[] claims = new Claim[] {
new Claim(JwtRegisteredClaimNames.Sub,model.UserID.ToString()),//Subject,
new Claim(JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Iat,UTC.ToString(),ClaimValueTypes.Integer64),
new Claim(ClaimTypes.Role,model.SystemRoleId),
new Claim("Role",model.SystemRoleId.ToString()),
new Claim("Name",model.Name.ToString())
};
//秘钥
var jwtConfig = new JwtAuthConfigModel();
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtConfig.JWTSecretKey));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
//过期时间
double exp = 0;
switch (model.TokenType)
{
case "Web":
exp = jwtConfig.WebExp;
break;
case "App":
exp = jwtConfig.AppExp;
break;
case "MiniProgram":
exp = jwtConfig.MiniProgramExp;
break;
case "Other":
exp = jwtConfig.OtherExp;
break;
}
JwtSecurityToken jwt = new JwtSecurityToken(
issuer: "XQP.NetCore",
audience: model.Name,
claims: claims,
expires: UTC.AddHours(exp),
signingCredentials: creds
);
var jwtHandler = new JwtSecurityTokenHandler();
var encodedJwt = jwtHandler.WriteToken(jwt);
return encodedJwt;
} ///
/// 解析
///
///
///
public static TokenModel SerializeJWT(string jwtStr)
{
var jwtHandler = new JwtSecurityTokenHandler();
JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(jwtStr);
object role = new object(); ;
object name = new object();
try
{
jwtToken.Payload.TryGetValue("Role", out role);
jwtToken.Payload.TryGetValue("Name", out name);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
var tm = new TokenModel
{
UserID = int.Parse(jwtToken.Subject),
SystemRoleId =role.ToString(),
Name = name.ToString(),
};
return tm;
}
同时在登录哪里登录成功之后调用生成字符串的方法,并返回。
实体也根据自己的情况修改了一下,这里其实主要用的角色这个字段
还加了一个配置类,主要配置密钥和过期时间的
最后就是中间件的修改了,这里给解析出来的身份进行了授权。
然后就是Startup配置修改了,这里用的是画红线的那个,大神说可以用多个身份的,我试了没成功,如果有哪位知道原因也可以告诉我一下
然后和之前一下使用就可以了,登录的时候拿到JWT字符串,然后访问接口的时候进行认证(直接用Swagger上的锁就可以)
NetCoreApi框架搭建三、JWT授权验证)的更多相关文章
- .Net Core3.0 WebApi 项目框架搭建 四:JWT权限验证
.Net Core3.0 WebApi 项目框架搭建:目录 什么是JWT 根据维基百科定义,JWT(读作 [/dʒɒt/]),即JSON Web Tokens,是一种基于JSON的.用于在网络上声明某 ...
- NetCoreApi框架搭建三、AutoFac 依赖入注)
这里不多做理论上的解释,因为我感觉自己也不是很完全的理解,所以只是记录我自己做的过程. 首先还是粘贴大神的链接:https://www.cnblogs.com/RayWang/p/11165509.h ...
- 【从零开始搭建自己的.NET Core Api框架】(四)实战!带你半个小时实现接口的JWT授权验证
系列目录 一. 创建项目并集成swagger 1.1 创建 1.2 完善 二. 搭建项目整体架构 三. 集成轻量级ORM框架——SqlSugar 3.1 搭建环境 3.2 实战篇:利用SqlSuga ...
- Unity 游戏框架搭建 (三) MonoBehaviour单例的模板
上一篇文章讲述了如何设计C#单例的模板.也随之抛出了问题: 如何设计接收MonoBehaviour生命周期的单例的模板? 如何设计? 先分析下需求: 1.约束脚本实例对象的个数. 2.约束 ...
- .Net Core3.0 WebApi 项目框架搭建 三:读取appsettings.json
.Net Core3.0 WebApi 项目框架搭建:目录 appsettings.json 我们在写项目时往往会把一些经常变动的,可能会变动的参数写到配置文件.数据库中等可以存储数据且方便配置的地方 ...
- .Net Core官方的 JWT 授权验证
什么是JWT? JSON Web令牌(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间安全地传输信息作为JSON对象.由于此信息是经过数字签名的,因此可以被验 ...
- 自定义统一api返回json格式(app后台框架搭建三)
在统一json自定义格式的方式有多种:1,直接重写@reposeBody的实现,2,自定义一个注解,自己去解析对象成为json字符串进行返回 第一种方式,我就不推荐,想弄得的话,可以自己去研究一下源码 ...
- NetCoreApi框架搭建(一、swagger插件使用)
1.首先用vs2017创建新的项目 2.开始引入swagger插件 右击项目=>管理NuGet程序包=>搜索Swashbuckle.AspNetCore点击安装 3.打开Startup.c ...
- 基于Web Service的客户端框架搭建三:代理层(Proxy)
前言 代理层的主要工作是调用Web Service,将在FCL层序列化好的Json数据字符串Post到Web Service,然后获得Reponse,再从响应流中读取到调用结果Json字符串,在Dis ...
随机推荐
- mybatis if-else用法
demo: <select id="queryRuralCodes" resultType="string" parameterType="ma ...
- 如何解决问题:程序无法正常启动(0xc0000022)
如何解决问题:程序无法正常启动(0xc0000022) 下文是由NeoSmart技术,通过全球网络上的工程师开发者和技术人员一起收集起来的信息,进行汇总并编辑而成的. 错误现象 该错误一般会通过警告, ...
- HDU 1072 Nightmare 题解
Nightmare Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total S ...
- Ubuntu下搭建Kubernetes集群(4)--部署K8S Dashboard
K8S Dashboard是官方的一个基于WEB的用户界面,专门用来管理K8S集群,并可展示集群的状态.K8S集群安装好后默认没有包含Dashboard,我们需要额外创建它. 首先我们执行命令: wg ...
- vue-router路由传参之query和params
首先简单来说明一下$router和$route的区别 //$router : 是路由操作对象,只写对象 //$route : 路由信息对象,只读对象 //操作 路由跳转 this.$router.pu ...
- 曹玉中-201871010105《面向对象程序设计(java)》第6-7周学习总结
曹玉中-201871010105<面向对象程序设计(java)>第6-7周学习总结 项目 内容 这个作业属于哪个课程 <任课教师博客主页链接> https://www.c ...
- linux下安装编译为安装的php扩展
1.进入php源码包中,找到需要安装的扩展模块目录.cd /root/php-5.6.26/ext/mbstring 2.在扩展模块目录,运行phpize程序,(作用是检测 php 的内核版本,并为扩 ...
- USACO Telephone Lines
洛谷 P1948 [USACO08JAN]电话线Telephone Lines https://www.luogu.org/problem/P1948 JDOJ 2556: USACO 2008 Ja ...
- JDOJ 1946 求最长不下降子序列个数
Description 设有一个整数的序列:b1,b2,…,bn,对于下标i1<i2<…<im,若有bi1≤bi2≤…≤bim 则称存在一个长度为m的不下降序列. 现在有n个数,请你 ...
- tornado之获取参数
self.write() # 返回字符串 self.redirect() # 重定向 self.render() # 返回html页面 一. 获取url中携带的参数, 如: 127.0.0.1: ...