標籤:xfs now() es2017 錯誤資訊 most rcu 中心 help util
網關指南: https://help.aliyun.com/document_detail/29487.html?spm=5176.doc48835.6.550.23Oqbl
網關控制台: https://apigateway.console.aliyun.com/?spm=5176.doc42740.2.2.Q4z5ws#/cn-hangzhou/apis/list
參考連結:https://help.aliyun.com/document_detail/48019.html?spm=5176.doc29487.6.580.NFBkpz
一、配置中心
1、配置API時,將所有API分為兩類,【獲得授權Token的API】和【業務訪問API】。
2、【獲得授權Token的API】用於用戶端獲得token。配置【獲得授權Token的API】時,要指定Token對應的Key和解析Token的公開金鑰。
3、【業務訪問API】實際業務API,調用時需攜帶token。配置【業務訪問API】時,要指定請求Token名稱。當用戶端調用這類API的請求到達API Gateway後,API Gateway自動驗證這個請求的Appkey和Token是否合法。
二、商務程序
1、用戶端調用 “擷取授權 API” ,擷取Token的流程
1.1、用戶端使用您的 “Appkey 簽名”+“使用者名稱/密碼” 調用 “擷取授權” API 擷取(加密後的)Token 使用者名稱/密碼 是極為敏感的資訊,在網路中明文傳輸存在風險,建議在傳輸前對使用者名稱密碼再次加密,並使用 HTTPS 協議傳輸。
1.2、API Gateway收到請求後,先認證您的 Appkey,認證通過後,調用後端服務的帳號系統認證您傳遞的 “使用者名稱/密碼”。
1.3、後端服務認證通過後,依據網關提供的加密方式,頒發 Token返回給用戶端,後續用戶端可憑 Token 來調用 “業務 API”。
2、用戶端調用業務類 API ,來實現業務功能
2.1、用戶端使用 “擷取授權 API” 得到的 Token 和 簽名後的 Appkey 來調用 “業務API”。(調用API請參照:調用API)
2.2、API Gateway認證、解析 Token 的內容,並將 Token 中包含的使用者資訊傳遞給後端。
三、證明伺服器AS和資原始伺服器RS
1、證明伺服器,負責產生 id_Token 並管理公開金鑰私密金鑰對 證明伺服器,接收網關請求(u+p),執行u+p認證。 認證成功:返回token(包含了使用者資訊) 認證失敗:返回出錯資訊 註:id_token 必須符合 OIDC(1.0版本)協議中的 規範。
1.1、AS 中使用 OIDC 產生 id_token 的說明 id_token,也叫 ID Token,是在 OIDC 協議中定義的一種令牌,詳細內容參見 OpenID Connect Core 1.0。 id_token 產生需要 KeyPair, keyId 與 Claims (有關Claims更多資訊請訪問 ID_Token)。
(1) KeyId
KeyId 必須保證唯一, 比如使用 UUID 產生的長度至少32位的隨機字串, 可以全為數字或數字+字母。
參考樣本(JAVA)
String keyId = UUID.randomUUID().toString().replaceAll("-", "");
String keyId = String.valueOf(UUID.randomUUID().getMostSignificantBits()) + String.valueOf(UUID.randomUUID().getMostSignificantBits());
(2) KeyPair
KeyPair 是一個基於 PKI 體系的非對稱演算法的公私密金鑰組合, 每一對包括公開金鑰(publicKey)與私密金鑰(privateKey);
公開金鑰放置在 RS 中,在校正(verify)時使用, 私密金鑰放置在 AS 中,在產生 id_token 時做數位簽章使用;
KeyPair 使用 RSA SHA256 密碼編譯演算法, 為保證足夠安全其加密的位元為2048;
AS 中使用的 KeyPair 均為 JSON 格式的資料,樣本如下:
publicKey:
{"kty":"RSA","kid":"67174182967979709913950471789226181721","alg":"ES256","n":"oH5WunqaqIopfOFBz9RfBVVIIcmk0WDJagAcROKFiLJScQ8N\_nrexgbCMlu-dSCUWq7XMnp1ZSqw-XBS2-XEy4W4l2Q7rx3qDWY0cP8pY83hqxTZ6-8GErJm\_0yOzR4WO4plIVVWt96-mxn3ZgK8kmaeotkS0zS0pYMb4EEOxFFnGFqjCThuO2pimF0imxiEWw5WCdREz1v8RW72WdEfLpTLJEOpP1FsFyG3OIDbTYOqowD1YQEf5Nk2TqN\_7pYrGRKsK3BPpw4s9aXHbGrpwsCRwYbKYbmeJst8MQ4AgcorE3NPmp-E6RxA5jLQ4axXrwC0T458LIVhypWhDqejUw","e":"AQAB"}
privateKey:
{"kty":"RSA","kid":"67174182967979709913950471789226181721","alg":"ES256","n":"oH5WunqaqIopfOFBz9RfBVVIIcmk0WDJagAcROKFiLJScQ8N\_nrexgbCMlu-dSCUWq7XMnp1ZSqw-XBS2-XEy4W4l2Q7rx3qDWY0cP8pY83hqxTZ6-8GErJm\_0yOzR4WO4plIVVWt96-mxn3ZgK8kmaeotkS0zS0pYMb4EEOxFFnGFqjCThuO2pimF0imxiEWw5WCdREz1v8RW72WdEfLpTLJEOpP1FsFyG3OIDbTYOqowD1YQEf5Nk2TqN\_7pYrGRKsK3BPpw4s9aXHbGrpwsCRwYbKYbmeJst8MQ4AgcorE3NPmp-E6RxA5jLQ4axXrwC0T458LIVhypWhDqejUw","e":"AQAB","d":"aQsHnLnOK-1xxghw2KP5JTZyJZsiwt-ENFqqJfPUzmlYSCNAV4T39chKpkch2utd7hRtSN6Zo4NTnY8EzGQQb9yvunaiEbWUkPyJ6kM3RdlkkGLvVtp0sRwPCZ2EAYBlsMad9jkyrtmdC0rtf9jerzt3LMLC7XWbnpC3WAl8rsRDR1CGs\_-u4sfZfttsaUbJDD9hD0q4NfLDCVOZoQ\_8wkZxyWDAQGCe6GcCbu6N81fTp2CSVbiBj7DST\_4x2NYUA2KG8vyZYcwviNTxQzk4iPfdN2YQz\_9aMTZmmhVUGlmTvAjE5ebBqcqKAS0NfhOQHg2uR46eBKBy\_OyVOLohsQ","p":"8Tdo3DCs-0t9JMtM0lYqPRP4wYJs37Rv6S-ygRui2MI\_hadTY9I2A199JMYw7Fjke\_wa3gqJLa98pbybdLWkrOxXbKEkwE4uc4-fuNjLbUTC5tqdM5-nXmpL887uREVYnk8FUzvWeXYTCNCb7OLw5l8yPJ1tR8aNcd0fJNDKh98","q":"qlRrGSTsZzBkDgDi1xlCoYvoM76cbmxrCUK-mc\_kBRHfMjlHosxFUnAbxqIBE4eAJEKVfIJLQrHFvIDjQb3kM9ylmwMCu9f8u9DHrT8J7LSDlLqDaXuiM2oiKtW3bAaBPuiR7sVMFcuB5baCebHU487YymJCBTfeCZtFdi6c4w0","dp":"gVCROKonsjiQCG-s6X4j-saAL016jJsw-7QEYE6uiMHqR\_6iJ\_uD1V8Vuec-RxaItyc6SBsh24oeqsNoG7Ndaw7w912UVDwVjwJKQFCJDjU0v4oniItosKcPvM8M0TDUB1qZojuMCWWRYsJjNSWcvAQA7JoBAd-h6I8AqT39tcU","dq":"BckMQjRg2zhnjZo2Gjw\_aSFJZ8iHo7CHCi98LdlD03BB9oC\_kCYEDMLGDr8d7j3h-llQnoQGbmN\_ZeGy1l7Oy3wpG9TEWQEDEpYK0jWb7rBK79hN8l1CqyBlvLK5oi-uYCaiHkwRQ4RACz9huyRxKLOz5VvlBixZnFXrzBHVPlk","qi":"M5NCVjSegf\_KP8kQLAudXUZi\_6X8T-owtsG\_gB9xYVGnCsbHW8gccRocOY1Xa0KMotTWJl1AskCu-TZhOJmrdeGpvkdulwmbIcnjA\_Fgflp4lAj4TCWmtRI6982hnC3XP2e-nf\_z2XsPNiuOactY7W042D\_cajyyX\_tBEJaGOXM"} 範例程式碼(JAVA) String keyId = UUID.randomUUID().toString().replaceAll("-", ""); RsaJsonWebKey jwk = RsaJwkGenerator.generateJwk(2048); jwk.setKeyId(keyId); jwk.setAlgorithm(AlgorithmIdentifiers.ECDSA\_USING\_P256\_CURVE\_AND\_SHA256); String publicKey = jwk.toJson(JsonWebKey.OutputControlLevel.PUBLIC\_ONLY); String privateKey = jwk.toJson(JsonWebKey.OutputControlLevel.INCLUDE\_PRIVATE); (3) Claims 通過 OIDC 協議中定義的 Claims 屬性(aud, sub, exp, iat, iss)與其屬性值,產生 Claims(全稱 JwtClaims) 範例程式碼(JAVA) JwtClaims claims = new JwtClaims(); claims.setGeneratedJwtId(); claims.setIssuedAtToNow(); //expire time NumericDate date = NumericDate.now(); date.addSeconds(120); claims.setExpirationTime(date); claims.setNotBeforeMinutesInThePast(1); claims.setSubject("YOUR_SUBJECT"); claims.setAudience("YOUR_AUDIENCE"); //添加自訂參數 claims.setClaim(key, value); (4) 通過 keyId, Claims, privateKey 與使用的數位簽章演算法 (RSA SHA256 )產生 JWS( Json Web Signature) 範例程式碼(JAVA) JsonWebSignature jws = new JsonWebSignature(); jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA\_USING\_SHA256); jws.setKeyIdHeaderValue(keyId); ws.setPayload(claims.toJson()); PrivateKey privateKey = new RsaJsonWebKey(JsonUtil.parseJson(privateKeyText)).getPrivateKey(); jws.setKey(privateKey); (5)通過 JWS 擷取 id_token 值 範例程式碼(JAVA) String idToken = jws.getCompactSerialization(); 一個產生的 id_token 樣本: eyJhbGciOiJSUzI1NiIsImtpZCI6Ijg4NDgzNzI3NTU2OTI5MzI2NzAzMzA5OTA0MzUxMTg1ODE1NDg5In0.eyJ1c2VySWQiOiIzMzcwMTU0NDA2ODI1OTY4NjI3IiwidGFnTmFtZSI6ImNvbmFuVGVzdCIsImV4cCI6MTQ4MDU5Njg3OSwiYXVkIjoiQWxpX0FQSV9Vc2VyIiwianRpIjoiTm9DMFVVeW5xV0N0RUFEVjNoeEIydyIsImlhdCI6MTQ4MDU5MzI3OSwibmJmIjoxNDgwNTkzMjE5LCJzdWIiOiJ7ZGF0YU1hcD0ne3VzZXJJZD0zMzcwMTU0NDA2ODI1OTY4NjI3fScsIHN0YXR1c0NvZGU9JzAnLCBlcnJvcnM9J1tdJ30ifQ.V3rU2VCziSt6uTgdCktYRsIwkMEMsO_jUHNCCIW_Sp4qQ5ExjtwNt9h9mTGKFRujk2z1E0k36smWf9PbNGTZTWmSYN8rvcQqdsupcC6LU9r8jreA1Rw1CmmeWY4HsfBfeInr1wCFrEfZl6_QOtf3raKSK9AowhzEsnYRKAYuc297gmV8qlQdevAwU75qtg8j8ii3hZpJqTX67EteNCHZfhXn8wJjckl5sHz2xPPyMqj8CGRQ1wrZEHjUmNPw-unrUkt6neM0UrSqcjlrQ25L8PEL2TNs7nGVdl6iS7Nasbj8fsERMKcZbP2RFzOZfKJuaivD306cJIpQwxfS1u2bew
2、資原始伺服器RS,負責校正 id_token,並解析出相應的資訊 Consumer 用帶有 id_token 的參數去請求 API Gateway。
API Gateway會儲存校正所使用的公開金鑰,驗證並解析 id_token 擷取其中的 User 資訊傳給 Provider,若驗證失敗則直接返回錯誤資訊。
Provider 處理請求並返回結果給 API Gateway。 API Gateway透傳 Provider 響應的結果給 Consumer。
說明:RS 在整個體系中擔任 id_token 消費者角色,只有 id_token 校正通過,才能將請求轉寄給 Provider。
api-gateway實踐(10)新服務網關 - OpenID Connect