JWT(JSON Web Tokens)操作帮助类
载荷实体:
/// <summary>
/// JWT载荷实体
/// </summary>
public sealed class JWTPlayloadInfo
{
/// <summary>
/// jwt签发者
/// </summary>
public string iss { get; set; } = "Berry.Service";
/// <summary>
/// jwt所面向的用户
/// </summary>
public string sub { get; set; } = "ALL";
/// <summary>
/// 接收jwt的一方
/// </summary>
public string aud { get; set; } = "guest";
/// <summary>
/// jwt的签发时间
/// </summary>
public string iat { get; set; } = DateTimeHelper.GetTimeStamp(DateTime.Now).ToString();
/// <summary>
/// jwt的过期时间,这个过期时间必须要大于签发时间.默认60分钟
/// </summary>
public string exp { get; set; }
/// <summary>
/// 定义在什么时间之前,该jwt都是不可用的.
/// </summary>
public int nbf { get; set; }
/// <summary>
/// jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
/// </summary>
public string jti { get; set; } = CommonHelper.GetGuid();
/// <summary>
/// 用户ID。自定义字段
/// </summary>
public string userid { get; set; }
/// <summary>
/// 扩展字段。自定义字段
/// </summary>
public string extend { get; set; }
}
JWTHelper.cs:
/// <summary>
/// JWT操作帮助类
/// </summary>
public sealed class JWTHelper
{
/// <summary>
/// 签发Token
/// </summary>
/// <param name="playload">载荷</param>
/// <returns></returns>
public static string GetToken(JWTPlayloadInfo playload)
{
string token = String.Empty; IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
IJsonSerializer serializer = new JsonNetSerializer();
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
//设置过期时间
DateTime time = DateTime.Now.AddMinutes();
playload.exp = DateTimeHelper.GetTimeStamp(time).ToString();
Dictionary<string, object> dict = playload.Object2Dictionary();
//获取私钥
string secret = GetSecret();
//将Token保存在缓存中
if (!string.IsNullOrEmpty(playload.aud) && playload.aud.Equals("guest"))
{
//计算公用Token
token = CacheFactory.GetCacheInstance().GetCache("JWT_TokenCacheKey:Guest", () =>
{
return encoder.Encode(dict, secret);
}, time);
}
else
{
//计算Token
token = CacheFactory.GetCacheInstance().GetCache($"JWT_TokenCacheKey:{playload.aud}", () =>
{
return encoder.Encode(dict, secret);
}, time);
}
return token;
} /// <summary>
/// Token校验
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
public static JWTPlayloadInfo CheckToken(string token)
{
if (string.IsNullOrEmpty(token)) return null; IJsonSerializer serializer = new JsonNetSerializer();
IDateTimeProvider provider = new UtcDateTimeProvider();
IJwtValidator validator = new JwtValidator(serializer, provider); IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder); //获取私钥
string secret = GetSecret();
JWTPlayloadInfo playloadInfo = decoder.DecodeToObject<JWTPlayloadInfo>(token, secret, true);
if (playloadInfo != null)
{
if (!string.IsNullOrEmpty(playloadInfo.aud) && playloadInfo.aud.Equals("guest"))
{
string cacheToken = CacheFactory.GetCacheInstance().GetCache<string>("JWT_TokenCacheKey:Guest"); return Check(playloadInfo, cacheToken, token) ? playloadInfo : null;
}
else
{
string cacheToken = CacheFactory.GetCacheInstance().GetCache<string>($"JWT_TokenCacheKey:{playloadInfo.aud}");
return Check(playloadInfo, cacheToken, token) ? playloadInfo : null;
}
}
return null;
} private static bool Check(JWTPlayloadInfo info, string cacheToken, string token)
{
if (string.IsNullOrEmpty(cacheToken)) return false;
if (string.IsNullOrEmpty(token)) return false;
if (!cacheToken.Equals(token)) return false; //Token过期
DateTime exp = DateTimeHelper.GetDateTime(info.exp);
if (DateTime.Now > exp)
{
if (!string.IsNullOrEmpty(info.aud) && info.aud.Equals("guest"))
{
CacheFactory.GetCacheInstance().RemoveCache("JWT_TokenCacheKey:Guest");
}
else
{
CacheFactory.GetCacheInstance().RemoveCache($"JWT_TokenCacheKey:{info.aud}");
}
return false;
}
return true;
} /// <summary>
/// 获取私钥
/// </summary>
/// <returns></returns>
private static string GetSecret()
{
//TODO 从文件中去读真正的私钥
return "eyJpc3MiOiJCZXJyeS5TZXJ2aWNlIiwic3ViIjoiMTgyODQ1OTQ2MTkiLCJhdWQiOiJndWVzdCIsImlhdCI6IjE1MzEzODE5OTgiLCJleHAiOiIxNTMxMzg5MTk4IiwibmJmIjowLCJqdGkiOiI1YzdmN2ZhM2E4ODVlODExYTEzNTQ4ZDIyNGMwMWQwNSIsInVzZXJpZCI6bnVsbCwiZXh0ZW5kIjpudWxsfQ";
}
}
自定义忽略验证特性:
/// <summary>
/// 忽略验证
/// </summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class IgnoreTokenAttribute : Attribute
{
public bool Ignore { get; set; }
/// <summary>
/// 忽略验证.默认忽略
/// </summary>
/// <param name="ignore"></param>
public IgnoreTokenAttribute(bool ignore = true)
{
this.Ignore = ignore;
}
}
自定义Action拦截器,处理验证逻辑:
public class CustomActionFilterAttribute : ActionFilterAttribute
{
/// <summary>在调用操作方法之前发生。</summary>
/// <param name="actionContext">操作上下文。</param>
public override void OnActionExecuting(HttpActionContext actionContext)
{
string isInterfaceSignature = ConfigHelper.GetValue("IsInterfaceSignature");
if (isInterfaceSignature.ToLower() == "false") return; BaseJsonResult<string> resultMsg = null;
//授权码
string accessToken = string.Empty;
//操作上下文请求信息
HttpRequestMessage request = actionContext.Request;
//数字签名数据
if (request.Headers.Contains("Authorization"))
{
accessToken = HttpUtility.UrlDecode(request.Headers.GetValues("Authorization").FirstOrDefault());
} //接受客户端预请求
if (actionContext.Request.Method == HttpMethod.Options)
{
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Accepted);
return;
} //忽略不需要授权的方法
var attributes = actionContext.ActionDescriptor.GetCustomAttributes<IgnoreTokenAttribute>();
if (attributes.Count > && attributes[].Ignore) return; //判断请求头是否包含以下参数
if (string.IsNullOrEmpty(accessToken))
{
resultMsg = new BaseJsonResult<string>
{
Status = (int)JsonObjectStatus.ParameterError,
Message = JsonObjectStatus.ParameterError.GetEnumDescription()
};
actionContext.Response = resultMsg.ToHttpResponseMessage();
return;
} //校验Token是否有效
JWTPlayloadInfo playload = JWTHelper.CheckToken(accessToken);
if (playload == null)
{
resultMsg = new BaseJsonResult<string>
{
Status = (int)JsonObjectStatus.TokenInvalid,
Message = JsonObjectStatus.TokenInvalid.GetEnumDescription()
};
actionContext.Response = resultMsg.ToHttpResponseMessage();
return;
}
else
{
//校验当前用户是否能够操作某些特定方法(比如更新用户信息)
if (!attributes[].Ignore)
{
if (!string.IsNullOrEmpty(playload.aud) && playload.aud.Equals("guest"))
{
resultMsg = new BaseJsonResult<string>
{
Status = (int)JsonObjectStatus.Unauthorized,
Message = JsonObjectStatus.Unauthorized.GetEnumDescription()
};
actionContext.Response = resultMsg.ToHttpResponseMessage();
return;
}
}
} base.OnActionExecuting(actionContext);
}
}
在WebApiConfig.cs中注册:
config.Filters.Add(new CustomActionFilterAttribute());
新增获取Token控制器,添加获取Token方法:
/// <summary>
/// 获取授权Token
/// </summary>
/// <param name="arg"></param>
/// <returns></returns>
[HttpPost]
[IgnoreToken(true)]
public HttpResponseMessage GetJWTToken(GetTokenArgEntity arg)
{
BaseJsonResult<string> resultMsg = this.GetBaseJsonResult<string>(); Logger(this.GetType(), "获取授权Token-GetJWTToken", () =>
{
if (!string.IsNullOrEmpty(arg.t))
{
//TODO 根据UserID校验用户是否存在
if (true)
{
JWTPlayloadInfo playload = new JWTPlayloadInfo
{
iss = "Berry.Service",
sub = arg.Account,
aud = arg.UserId
};
string token = JWTHelper.GetToken(playload); resultMsg = this.GetBaseJsonResult<string>(token, JsonObjectStatus.Success);
}
else
{
resultMsg = this.GetBaseJsonResult<string>(JsonObjectStatus.UserNotExist);
}
}
else
{
resultMsg = this.GetBaseJsonResult<string>(JsonObjectStatus.Fail, ",请求参数有误。");
}
}, e =>
{
resultMsg = this.GetBaseJsonResult<string>(JsonObjectStatus.Exception, ",异常信息:" + e.Message);
}); return resultMsg.ToHttpResponseMessage();
}
获取Token参数实体:
/// <summary>
/// 获取Token参数
/// </summary>
public class GetTokenArgEntity : BaseParameterEntity
{
/// <summary>
/// 用户ID
/// </summary>
[Required(ErrorMessage = "UserId不能为空")]
public string UserId { get; set; }
/// <summary>
/// 帐号
/// </summary>
[Required(ErrorMessage = "Account不能为空")]
public string Account { get; set; }
}
JWT(JSON Web Tokens)操作帮助类的更多相关文章
- Java分布式:JWT(JSON Web Tokens)
Java分布式:JWT(JSON Web Tokens) 0.优势 Session方式存储用户状态占用大量服务器内存.一般而言,大型应用还需要借助一些KV数据库和一系列缓存机制来实现Session的存 ...
- ASP.NET Core 简单集成签发 JWT (JSON Web Tokens)
什么是 JWT ? 从 https://jwt.io/ 可以了解到对 JWT 的描述:JSON Web Tokens are an open, industry standard RFC 7519 m ...
- JWT & JSON Web Tokens
JSON Web Tokens https://jwt.io json web token example https://jwt.io/introduction/ https://medium.co ...
- jwt(JSON Web Tokens)的一道题目代码分析
题目链接https://github.com/wonderkun/CTF_web/tree/5b08d23ba4086992cbb9f3f4da89a6bb1346b305/web300-6 参考链接 ...
- 单点登录-JWT(Json Web Tokens)
来自:http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html 1.跨域认证 1.用户向服务器发送用户名和密码. 2.服务 ...
- [翻译]Introduction to JSON Web Tokens
JWT: Json Web Tokens JWT是一种开放标准(RFC 7519),它定义了一种紧凑且独立的方式,用于将各方之间的信息安全地传输为JSON对象.因为它是经过数字签名的,所以该信息可以进 ...
- 服务安全-JWT(JSON Web Tokens):百科
ylbtech-服务安全-JWT(JSON Web Tokens):百科 JSON Web Tokens是一种开放的行业标准 RFC 7519方法,用于在双方之间安全地表示索赔. JWT.IO允许您解 ...
- JSON Web Tokens(JWT)
现在API越来越流行,如何安全保护这些API? JSON Web Tokens(JWT)能提供基于JSON格式的安全认证.它有以下特点: JWT是跨不同语言的,JWT可以在 .NET, Python, ...
- Java JWT: JSON Web Token
Java JWT: JSON Web Token for Java and Android JJWT aims to be the easiest to use and understand libr ...
- Go实战--golang中使用JWT(JSON Web Token)
http://blog.csdn.net/wangshubo1989/article/details/74529333 之前写过关于golang中如何使用cookie的博客: 实战–go中使用cook ...
随机推荐
- ICEM-圆柱与长方体相切
原视频下载地址:https://yunpan.cn/cqvgLe39ZU4Ke 访问密码 c1c9
- Bean Shell常用内置变量
JMeter在它的BeanShell中内置了变量,用户可以通过这些变量与JMeter进行交互,其中主要的变量及其使用方法如下: log:写入信息到jmeber.log文件,使用方法:log.info( ...
- [ambari环境搭建](未完待续)
[安装] https://blog.csdn.net/Happy_Sunshine_Boy/article/details/86595945#commentBox https://www.jiansh ...
- Leetcode题目461:汉明距离(位运算-简单)
题目描述: 两个整数之间的汉明距离指的是这两个数字对应二进制位不同的位置的数目. 给出两个整数 x 和 y,计算它们之间的汉明距离. 注意:0 ≤ x, y < 231. 示例: 输入: x = ...
- Ubuntu 16.04安装完重启后黑屏,光标一直闪
原文:https://blog.csdn.net/weixin_38533896/article/details/81023690 版权声明:本文为博主原创文章,转载请附上博文链接! 安装教程网址:h ...
- Alpha项目冲刺! Day4-产出
各个成员今日完成的任务 林恩:任务分工,博客撰写,了解安卓环境搭建 杨长元:安卓本地数据库基本建立 李震:学习 胡彤:完善服务端 寇永明:学习 王浩:学习 李杰:学习 各个成员遇到的问题 林恩:为自己 ...
- Mac地址转换成long长整型
Mac地址转换成long长整型 using System;using System.Collections.Generic;using System.IO;using System.Text;usin ...
- 调用百度地图API的总结
因为项目要用到百度地图,所以先摸索了一下,各种功能官方都有文档,点击可查看,文章的话我就直接写我用到的功能例子了,要用可以直接复制粘贴~ 一.主要涉及到的几个接口(先申请密钥): 1.技术一:坐标转换 ...
- yum安装PostgreSQL 在6和7
一.安装PostgreSQL 复制代码// 安装EPEL源# wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.n ...
- 阶段5 3.微服务项目【学成在线】_day16 Spring Security Oauth2_17-认证接口开发-申请令牌测试
远程 调用Spring Security来申请令牌,然后把申请到令牌存储到redis里面 cookieMaxAge: ‐1 -1表示浏览器一关闭cookie就失效. 测试远程申请令牌 TestCl ...