jwt是什么
jwt全稱是json web token,是一種用于雙方之間傳遞安全信息的簡(jiǎn)潔的、url安全的表述性聲明規(guī)范。jwt作為一個(gè)開(kāi)放的標(biāo)準(zhǔn)( rfc 7519 ),定義了一種簡(jiǎn)潔的,自包含的方法用于通信雙方之間以json對(duì)象的形式安全的傳遞信息。因?yàn)閿?shù)字簽名的存在,這些信息是可信的,jwt可以使用hmac算法或者是rsa的公私秘鑰對(duì)進(jìn)行簽名。
jwt的結(jié)構(gòu)
jwt一般由三段構(gòu)成,用.號(hào)分隔開(kāi),第一段是header,第二段是payload,第三段是signature,例如:
1
|
eyj0exaioijkv1qilcjhbgcioijiuzi1nij9.eyjuyw1lijoitxjcdwcilcjlehaioje1mti5ntkzmdmumcwianrpijoibhvvemhpcgvuzyj9.9iwgmhms0mophyfglilk15hs_ee770ichaz-bwcx5c0 |
1、header
jwt的頭部承載兩部分信息:
聲明類型。這里是jwt
聲明加密的算法。通常直接使用 hmac sha256,其它還有rs256等
完整的頭部就像下面這樣的json:
1
2
3
4
|
{ "alg": "hs256", "typ": "jwt" } |
然后將頭部進(jìn)行base64加密(該加密是可以對(duì)稱解密的),構(gòu)成了第一部分
1
|
eyj0exaioijkv1qilcjhbgcioijiuzi1nij9 |
2、playload
載荷就是存放有效信息的地方。這個(gè)名字像是特指飛機(jī)上承載的貨品,這些有效信息包含三個(gè)部分:
標(biāo)準(zhǔn)中注冊(cè)的聲明
公共的聲明
私有的聲明
標(biāo)準(zhǔn)中注冊(cè)的聲明 (建議但不強(qiáng)制使用) :
iss : jwt簽發(fā)者
sub:jwt所面向的用戶
aud:接收jwt的一方
exp:jwt的過(guò)期時(shí)間,這個(gè)過(guò)期時(shí)間必須要大于簽發(fā)時(shí)間
nbf:定義在什么時(shí)間之前,該jwt都是不可用的.
iat :jwt的簽發(fā)時(shí)間
jti :jwt的唯一身份標(biāo)識(shí),主要用來(lái)作為一次性token,從而回避重放攻擊。
公共的聲明 :
公共的聲明可以添加任何的信息,一般添加用戶的相關(guān)信息或其他業(yè)務(wù)需要的必要信息.但不建議添加敏感信息,因?yàn)樵摬糠衷诳蛻舳丝山饷?
私有的聲明 :
私有聲明是提供者和消費(fèi)者所共同定義的聲明,一般不建議存放敏感信息,因?yàn)閎ase64是對(duì)稱解密的,意味著該部分信息可以歸類為明文信息。
定義一個(gè)playload
1
2
3
4
5
|
{ "name": "mrbug", "exp": 1512959303, "jti": "luozhipeng" } |
然后將其進(jìn)行base64加密,得到j(luò)wt的第二部分
1
|
eyjuyw1lijoitxjcdwcilcjlehaioje1mti5ntkzmdmumcwianrpijoibhvvemhpcgvuzyj9 |
3、signature
jwt的第三部分是一個(gè)簽證信息,這個(gè)簽證信息由三部分組成:
header (base64后的)
payload (base64后的)
secret
這個(gè)部分需要base64加密后的header和base64加密后的payload使用.連接組成的字符串,然后通過(guò)header中聲明的加密方式進(jìn)行加secret組合加密,然后就構(gòu)成了jwt的第三部分。
1
2
3
4
|
< span style = "color: #008000" >//</ span >< span style = "color: #008000" > javascript</ span > < span style = "color: #0000ff" >var</ span > encodedstring = base64urlencode(header) + '.' +< span style = "color: #000000" > base64urlencode(payload); </ span >< span style = "color: #0000ff" >var</ span > signature = hmacsha256(encodedstring, 'secret'); < span style = "color: #008000" >//</ span >< span style = "color: #008000" > 9iwgmhms0mophyfglilk15hs_ee770ichaz-bwcx5c0</ span > |
將這三部分用.連接成一個(gè)完整的字符串,構(gòu)成了最終的jwt:
1
|
eyj0exaioijkv1qilcjhbgcioijiuzi1nij9.eyjuyw1lijoitxjcdwcilcjlehaioje1mti5ntkzmdmumcwianrpijoibhvvemhpcgvuzyj9.9iwgmhms0mophyfglilk15hs_ee770ichaz-bwcx5c0 |
注意:secret是保存在服務(wù)器端的,jwt的簽發(fā)生成也是在服務(wù)器端的,secret就是用來(lái)進(jìn)行jwt的簽發(fā)和jwt的驗(yàn)證,所以,它就是你服務(wù)端的私鑰,在任何場(chǎng)景都不應(yīng)該流露出去。一旦客戶端得知這個(gè)secret, 那就意味著客戶端是可以自我簽發(fā)jwt了。
如何應(yīng)用
一般是在請(qǐng)求頭里加入authorization,并加上bearer標(biāo)注:
1
2
3
4
5
|
fetch('api/user/1', { headers: { 'authorization': 'bearer ' + token } }) |
服務(wù)端會(huì)驗(yàn)證token,如果驗(yàn)證通過(guò)就會(huì)返回相應(yīng)的資源。整個(gè)流程就是這樣的:
安全相關(guān)
不應(yīng)該在jwt的payload部分存放敏感信息,因?yàn)樵摬糠质强蛻舳丝山饷艿牟糠帧?/p>
保護(hù)好secret私鑰,該私鑰非常重要。
如果可以,請(qǐng)使用https協(xié)議
如何在.net中使用
這里要用到一個(gè)jwt.net的第三方庫(kù),可以通過(guò)nuget的方式獲取,目前最新版是3.1.1,最新版只支持.net framework4.6及以上,如圖
因?yàn)椋翼?xiàng)目中用的是.net framework4.5,所以我安裝的是jwt.net 3.0.0,你可以使用vs 工具 / nuget包管理器 / 程序包管理器控制臺(tái) ,輸入以下命令手動(dòng)安裝
1
|
install-package jwt -version 3.0.0 |
1、創(chuàng)建token,此處,我們只需要自定義payload和secrect密鑰即可,可生成三段格式的字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
idatetimeprovider provider = new utcdatetimeprovider(); var now = provider.getnow(); var unixepoch = new datetime(1970, 1, 1, 0, 0, 0, datetimekind.utc); // or use jwtvalidator.unixepoch var secondssinceepoch = math.round((now - unixepoch).totalseconds); var payload = new dictionary< string , object> { { "name", "mrbug" }, {"exp",secondssinceepoch+100 }, {"jti","luozhipeng" } }; console.writeline(secondssinceepoch); ijwtalgorithm algorithm = new hmacsha256algorithm(); ijsonserializer serializer = new jsonnetserializer(); ibase64urlencoder urlencoder = new jwtbase64urlencoder(); ijwtencoder encoder = new jwtencoder(algorithm, serializer, urlencoder); var token = encoder.encode(payload, secret); console.writeline(token); |
2、token解密
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
try { 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); var json = decoder.decode(token, secret, verify: true);//token為之前生成的字符串 console.writeline(json); } catch (tokenexpiredexception) { console.writeline("token has expired"); } catch (signatureverificationexception) { console.writeline("token has invalid signature"); } |
3、自定義json解析器,只要繼承ijsonserializer接口
1
2
3
4
5
6
7
8
9
10
11
|
public class customjsonserializer : ijsonserializer { public string serialize(object obj) { // implement using favorite json serializer } public t deserialize&l t ;t>(string json) { // implement using favorite json serializer } } |
使用
1
2
3
4
|
ijwtalgorithm algorithm = new hmacsha256algorithm(); ijsonserializer serializer = new customjsonserializer(); ibase64urlencoder urlencoder = new jwtbase64urlencoder(); ijwtencoder encoder = new jwtencoder(algorithm, serializer, urlencoder); |
4、自定義json序列化
默認(rèn)的json序列化由jsonnetserializer完成,可以自定義序列化:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
jsonserializer customjsonserializer = new jsonserializer { // all json keys start with lowercase characters instead of the exact casing of the model/property. e.g. fullname contractresolver = new camelcasepropertynamescontractresolver(), // nice and easy to read, but you can also do formatting.none to reduce the payload size (by hardly anything...) formatting = formatting.indented, // the best date/time format/standard. dateformathandling = dateformathandling.isodateformat, // don't add key/values when the value is null. nullvaluehandling = nullvaluehandling.ignore, // use the enum string-value, not the implicit int value, e.g. "oolor" : "red" converters.add(new stringenumconverter()) }; ijsonserializer serializer = new jsonnetserializer(customjsonserializer); |
以上這篇基于jwt.net的使用(詳解)就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持服務(wù)器之家。
原文鏈接:http://www.cnblogs.com/mrbug/archive/2017/12/11/8022826.html