jwt私钥和公钥怎么获取_jwt 用rsa公钥私钥进行验证(python发送,java接受)
JWT的主要應用場景
身份認證在這種場景下,一旦用戶完成了登陸,在接下來的每個請求中包含JWT,可以用來驗證用戶身份以及對路由,服務和資源的訪問權限進行驗證。由于它的開銷非常小,可以輕松的在不同域名的系統中傳遞,所有目前在單點登錄(SSO)中比較廣泛的使用了該技術。 信息交換在通信的雙方之間使用JWT對數據進行編碼是一種非常安全的方式,由于它的信息是經過簽名的,可以確保發送者發送的信息是沒有經過偽造的。
JWT的結構
JWT包含了使用.分隔的三部分: Header 頭部 Payload 負載 Signature 簽名
其結構看起來是這樣的Header.Payload.Signature
Header
在header中通常包含了兩部分:token類型和采用的加密算法。{ "alg": "HS256", "typ": "JWT"} 接下來對這部分內容使用 Base64Url 編碼組成了JWT結構的第一部分。
Payload
Token的第二部分是負載,它包含了claim, Claim是一些實體(通常指的用戶)的狀態和額外的元數據,有三種類型的claim:reserved, public 和 private.Reserved claims: 這些claim是JWT預先定義的,在JWT中并不會強制使用它們,而是推薦使用,常用的有 iss(簽發者),exp(過期時間戳), sub(面向的用戶), aud(接收方), iat(簽發時間)。 Public claims:根據需要定義自己的字段,注意應該避免沖突 Private claims:這些是自定義的字段,可以用來在雙方之間交換信息 負載使用的例子:{ "sub": "1234567890", "name": "John Doe", "admin": true} 上述的負載需要經過Base64Url編碼后作為JWT結構的第二部分。
Signature
創建簽名需要使用編碼后的header和payload以及一個秘鑰,使用header中指定簽名算法進行簽名。例如如果希望使用HMAC SHA256算法,那么簽名應該使用下列方式創建: HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret) 簽名用于驗證消息的發送者以及消息是沒有經過篡改的。 完整的JWT 完整的JWT格式的輸出是以. 分隔的三段Base64編碼,與SAML等基于XML的標準相比,JWT在HTTP和HTML環境中更容易傳遞。 下列的JWT展示了一個完整的JWT格式,它拼接了之前的Header, Payload以及秘鑰簽名:
encoded-jwt3.png
python發送數據
import calendar
import datetime
import time
import jenkins
import requests
import json
import logging
import configparser
import jwt
#read the private_key
with open('rsa_private_key.pem') as f:
private_key = f.read()
exp = datetime.datetime.utcnow() + datetime.timedelta(minutes=10)
exp = calendar.timegm(exp.timetuple())
# Generate the JWT
payload = {
# issued at time
'iat': int(time.time()),
# JWT expiration time (10 minute maximum)
'exp': exp,
# Integration's GitHub identifier
'iss': 'tom',
}
encoded = jwt.encode(payload, private_key, algorithm='RS256')
try:
headers = {
'content-type': "application/json",
'jwt': encoded
}
response = requests.post(server_url, headers=headers)
if response.status_code != 200:
logger.error("commit builds post go wrong , status code is : {}".format(response.status_code))
logger.error(response.text)
except Exception as e:
logger.error("commit builds post Error: {}".format(e))
java接受數據(springboot攔截器)
public class WebInterceptor implements HandlerInterceptor {
static final Logger logger = LoggerFactory.getLogger(WebInterceptor.class);
@Autowired
private MyConfig myconfig;
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
logger.info("============== request before ==============");
String jwt = httpServletRequest.getHeader("jwt");
logger.info("jwt is : " + jwt);
String str = null;
if(myconfig == null){
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(httpServletRequest.getServletContext());
myconfig = wac.getBean(MyConfig.class);
}
try {
//read the public key
File file = ResourceUtils.getFile(myconfig.getRsaPublicKeyDir());
FileReader reader = new FileReader(file);
BufferedReader bReader = new BufferedReader(reader);
StringBuilder sb = new StringBuilder();
String s;
while ((s = bReader.readLine()) != null) {
sb.append(s);
}
bReader.close();
str = sb.toString();
RsaKeyUtil rsaKeyUtil = new RsaKeyUtil();
PublicKey publicKey = rsaKeyUtil.fromPemEncoded(str);
// create a JWT consumer
JwtConsumer jwtConsumer = new JwtConsumerBuilder()
.setRequireExpirationTime()
.setVerificationKey(publicKey)
//不能少不然會報錯
.setRelaxVerificationKeyValidation()
.setJwsAlgorithmConstraints( // only allow the expected signature algorithm(s) in the given context
new AlgorithmConstraints(AlgorithmConstraints.ConstraintType.WHITELIST, // which is only RS256 here
AlgorithmIdentifiers.RSA_USING_SHA256))
.build();
// validate and decode the jwt
JwtClaims jwtDecoded = jwtConsumer.processToClaims(jwt);
Map jwtClaims = jwtDecoded.getClaimsMap();
Object iss = jwtClaims.get("iss");
logger.info("jwtClaims is : "+ jwtClaims);
}catch (Exception e){
logger.error(e.getMessage());
return false;
}
return true;
}
}
簽名的目的
最后一步簽名的過程,實際上是對頭部以及載荷內容進行簽名。一般而言,加密算法對于不同的輸入產生的輸出總是不一樣的。對于兩個不同的輸入,產生同樣的輸出的概率極其地小(有可能比我成世界首富的概率還小)。所以,我們就把“不一樣的輸入產生不一樣的輸出”當做必然事件來看待吧。
所以,如果有人對頭部以及載荷的內容解碼之后進行修改,再進行編碼的話,那么新的頭部和載荷的簽名和之前的簽名就將是不一樣的。而且,如果不知道服務器加密的時候用的密鑰的話,得出來的簽名也一定會是不一樣的。
服務器應用在接受到JWT后,會首先對頭部和載荷的內容用同一算法再次簽名。那么服務器應用是怎么知道我們用的是哪一種算法呢?別忘了,我們在JWT的頭部中已經用alg字段指明了我們的加密算法了。
如果服務器應用對頭部和載荷再次以同樣方法簽名之后發現,自己計算出來的簽名和接受到的簽名不一樣,那么就說明這個Token的內容被別人動過的,我們應該拒絕這個Token,返回一個HTTP 401 Unauthorized響應。
信息會暴露?
是的。
所以,在JWT中,不應該在載荷里面加入任何敏感的數據。在上面的例子中,我們傳輸的是用戶的User ID。這個值實際上不是什么敏感內容,一般情況下被知道也是安全的。
但是像密碼這樣的內容就不能被放在JWT中了。如果將用戶的密碼放在了JWT中,那么懷有惡意的第三方通過Base64解碼就能很快地知道你的密碼了。
JWT的適用場景
我們可以看到,JWT適合用于向Web應用傳遞一些非敏感信息。例如在上面提到的完成加好友的操作,還有諸如下訂單的操作等等。
其實JWT還經常用于設計用戶認證和授權系統,甚至實現Web應用的單點登錄。在下一次的文章中,我將為大家系統地總結JWT在用戶認證和授權上的應用。
總結
以上是生活随笔為你收集整理的jwt私钥和公钥怎么获取_jwt 用rsa公钥私钥进行验证(python发送,java接受)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 检测并解析二维码
- 下一篇: jieba库词频统计_如何用python