载荷实体:

/// <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)操作帮助类的更多相关文章

  1. Java分布式:JWT(JSON Web Tokens)

    Java分布式:JWT(JSON Web Tokens) 0.优势 Session方式存储用户状态占用大量服务器内存.一般而言,大型应用还需要借助一些KV数据库和一系列缓存机制来实现Session的存 ...

  2. ASP.NET Core 简单集成签发 JWT (JSON Web Tokens)

    什么是 JWT ? 从 https://jwt.io/ 可以了解到对 JWT 的描述:JSON Web Tokens are an open, industry standard RFC 7519 m ...

  3. JWT & JSON Web Tokens

    JSON Web Tokens https://jwt.io json web token example https://jwt.io/introduction/ https://medium.co ...

  4. jwt(JSON Web Tokens)的一道题目代码分析

    题目链接https://github.com/wonderkun/CTF_web/tree/5b08d23ba4086992cbb9f3f4da89a6bb1346b305/web300-6 参考链接 ...

  5. 单点登录-JWT(Json Web Tokens)

    来自:http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html 1.跨域认证 1.用户向服务器发送用户名和密码. 2.服务 ...

  6. [翻译]Introduction to JSON Web Tokens

    JWT: Json Web Tokens JWT是一种开放标准(RFC 7519),它定义了一种紧凑且独立的方式,用于将各方之间的信息安全地传输为JSON对象.因为它是经过数字签名的,所以该信息可以进 ...

  7. 服务安全-JWT(JSON Web Tokens):百科

    ylbtech-服务安全-JWT(JSON Web Tokens):百科 JSON Web Tokens是一种开放的行业标准 RFC 7519方法,用于在双方之间安全地表示索赔. JWT.IO允许您解 ...

  8. JSON Web Tokens(JWT)

    现在API越来越流行,如何安全保护这些API? JSON Web Tokens(JWT)能提供基于JSON格式的安全认证.它有以下特点: JWT是跨不同语言的,JWT可以在 .NET, Python, ...

  9. 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 ...

  10. Go实战--golang中使用JWT(JSON Web Token)

    http://blog.csdn.net/wangshubo1989/article/details/74529333 之前写过关于golang中如何使用cookie的博客: 实战–go中使用cook ...

随机推荐

  1. break,continue,return的区别 x

    这三个东西特别坑,一定要记准了!! 1)break     直接跳出当前的循环,从当前循环外面开始执行,忽略循环体中任何其他语句和循环条件测试.他只能跳出一层循环: 注意:如果你的循环是嵌套循环,那么 ...

  2. 通过时间戳批量删除hbase的数据

    如何通过时间戳批量删除hbase的数据 我们使用hive关联hbase插入数据时,有时会写错数据,此时hbase中的数据量已经很大很大了(上亿).此时,我们要修改错误的数据,只需要删除写错的那部分数据 ...

  3. [SDOI2015]序列统计(NTT+求原根)

    题目 [SDOI2015]序列统计 挺好的题!!! 做法 \(f[i][j]\)为第\(i\)个数前缀积在模\(M\)意义下为\(j\) 显然是可以快速幂的:\[f[2*i][j]=\sum\limi ...

  4. LOJ#2977. 「THUSCH 2017」巧克力(斯坦纳树+随机化)

    题目 题目 做法 考虑部分数据(颜色较少)的: 二分中位数\(mid\),将\(v[i]=1000+(v[i]>mid)\) 具体二分操作:然后求出包含\(K\)种颜色的联通快最小的权值和,判断 ...

  5. Java8函数式编程的宏观总结

    1.java8优势通过将行为进行抽象,java8提供了批量处理数据的并行类库,使得代码可以在多核CPU上高效运行. 2.函数式编程的核心使用不可变值和函数,函数对一个值进行处理,映射成另一个值. 3. ...

  6. 微信小程序开发步骤简述

    1.登陆微信的开发这平台 2.找到小程序开发选项进入,填写注册自己的小程序信息 3.下载相应的开发者工具 4.通过开发者工具把自己的项目代码上传,上传时会让你填写自己小程序的appid这样项目代码就和 ...

  7. Java--常用API介绍

    Scanner类--键盘输入,室友起来三个步骤: 第一,导包:import java.util.Scanner 第二,创建:Scanner sc = new Scanner(System.in) 第三 ...

  8. Java 面向对象(十三)

    异常 什么是异常 异常 :指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止. 在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象. ...

  9. Co-Clustering_Reproducing

    调包一时爽,复现马上躺. Co-Clustering 注意右上角的:"Edit on GitHub",一开始疯狂吐槽没有源码,复现得非常难受,今天刚做完GM05中Algotirhm ...

  10. Go 语言入门(一)基础语法

    写在前面 在学习 Go 语言之前,我自己是有一定的 Java 和 C++ 基础的,这篇文章主要是基于A tour of Go编写的,主要是希望记录一下自己的学习历程,加深自己的理解 Go 语言入门(一 ...