JSON Web标记(JWT)是目前最流行的跨域身份验证解决方案。为了网络应用环境间传递声明而执行的一种基于JSON的开发标准(RFC 7519),
该令牌被设计为紧凑且安全的,特别适用于分布式站点的单点登陆(SSO)场景.JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,
以便于从资源服务器获取资源,该令牌也可直接被用于认证,也可被加密。
下面是JWT的一段示例,分为三个部分,分别是头部(头),载荷(载荷)}和签证(签名),他们之间用点隔开。
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9。
引用>
eyJpc3MiOiLmtYHmnIjml6Dlj4wiLCJleHAiOjE1NzExMDIxNTMsInN1YiI6InRlc3RKV1QiLCJhdWQiOiJVU0VSIiwiaWF0IjoiMjAxOS8xMC8xNSA5OjE1OjQzIiwiZGF0YSI6eyJuYW1lIjoiMTExIiwiYWdlIjoxMSwiYWRkcmVzcyI6Imh2YmVpIn19。
25 ibzpabsxbqsr2k3h0izkrac6z3ojtwg38vdtceer8
JWT是基于json的鉴权机制,而且是无状态的,服务器端是没有如传统那样保存客户端的登录信息的,这就为分布式开发提供了便利,
因为传统的方式是在服务端保存会话信息,会话是保存在内存中的,当客户量变大的时候,对服务器的压力自然会增大,
最关键的是在集群分布式中,每一次登录的服务器可能不一样,那么可能导致会话保存在其中一个服务器,而另外一个服务器被请求的
时候还是无状态,除非你再次登录,这就造成了很大的麻烦,也有人说把会话存放在专门的服务器,每次都去那个服务器请求,
我不认为这是很好的解决方案,本来集群就是为了高可用,如果你配置会话的服务器坏了,大家都跟着完蛋,所以JWT这种无状态的方式
就非常适合这种分布式的系统。
光说不练假把式、下面还是来一段代码。
还是老方式,先用NuGet把JWT引用进来,这里需要引入JWT和newtonsoft.json
如下图所示:
然后就是生成JWT的方法。
静态IJwtAlgorithm算法=new HMACSHA256Algorithm ();//HMACSHA256加密 静态IJsonSerializer序列化器=new JsonNetSerializer();//序列化和反序列 静态IBase64UrlEncoder urlEncoder=new JwtBase64UrlEncoder ();//Base64编解码 静态IDateTimeProvider提供者=new UtcDateTimeProvider ();//UTC时间获取 常量字符串秘密=癕IGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4aKpVo2OHXPwb1R7duLgg”;//服务端 公共静态字符串CreateJWT (Dictionary<字符串,object>有效负载) { IJwtEncoder编码器=new JwtEncoder(算法、序列化器urlEncoder); 返回编码器。编码(载荷、秘密); }看到这段代码,你说觉得怎么这么简单,没错,就是这么简单,这个方法是被我们引用进来的这个JWT给封装了,所以看起来很简单
当时我看到这里也是有点吃惊,不过我还是对源码进行了研究,下面贴出一段源码给大家看看
如下所示,这段代码是比较核心的代码,在没有传递头的时候,他帮你默认加了标题,
其实下面的这段代码很容易看懂,无非就是对报头和有效载荷进行base64加密(其实这里说加密也不是很恰当)。
这里的头你可以自己传递进来。
公共字符串编码(IDictionary<字符串,object>extraHeaders、对象有效载荷、byte[]键) { 如果(有效载荷为空) 把新的ArgumentNullException (nameof(载荷)); var段=new List(3); var头=extraHeaders零& # 63;新的Dictionary<字符串,object> (StringComparer.OrdinalIgnoreCase):新的Dictionary<字符串,object> (extraHeaders StringComparer.OrdinalIgnoreCase); 头。添加(“typ”、“JWT”); 头。添加(alg _algorithm.Name); var headerBytes=GetBytes (_jsonSerializer.Serialize(头); var payloadBytes=GetBytes (_jsonSerializer.Serialize(载荷)); segments.Add (_urlEncoder.Encode (headerBytes)); segments.Add (_urlEncoder.Encode (payloadBytes)); var stringToSign=String.Join (”。”,segments.ToArray ()); var bytesToSign=GetBytes (stringToSign); var=_algorithm签名。符号(关键、bytesToSign); segments.Add (_urlEncoder.Encode(签名)); 返回String.Join (”。”,segments.ToArray ()); } 下面一段就是对JWT进行验证的代码,这里的写法都差不多,反正都是调用JWT里面的方法,我们传递参数即可。
c#关于JWT跨域身份验证的实现代码