api-gateway实践(10)新服务网关 - OpenID Connect

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了api-gateway实践(10)新服务网关 - OpenID Connect相关的知识,希望对你有一定的参考价值。

 

网关指南: 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网关后,API网关自动验证这个请求的Appkey和Token是否合法。

技术分享

技术分享

二、业务流程

1、客户端调用 “获取授权 API” ,获取Token的流程

1.1、客户端使用您的 “Appkey 签名”+“用户名/密码” 调用 “获取授权” API 获取(加密后的)Token 用户名/密码 是极为敏感的信息,在网络中明文传输存在风险,建议在传输前对用户名密码再次加密,并使用 HTTPS 协议传输。

1.2、API网关收到请求后,先认证您的 Appkey,认证通过后,调用后端服务的账号系统认证您传递的 “用户名/密码”。

1.3、后端服务认证通过后,依据网关提供的加密方式,颁发 Token返回给客户端,后续客户端可凭 Token 来调用 “业务 API”。

2、客户端调用业务类 API ,来实现业务功能

2.1、客户端使用 “获取授权 API” 得到的 Token 和 签名后的 Appkey 来调用 “业务API”。(调用API请参照:调用API)

2.2、API 网关认证、解析 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 网关。

API 网关会保存校验所使用的公钥,验证并解析 id_token 获取其中的 User 信息传给 Provider,若验证失败则直接返回错误信息。

Provider 处理请求并返回结果给 API 网关。 API 网关透传 Provider 响应的结果给 Consumer。

说明:RS 在整个体系中担任 id_token 消费者角色,只有 id_token 校验通过,才能将请求转发给 Provider。

以上是关于api-gateway实践(10)新服务网关 - OpenID Connect的主要内容,如果未能解决你的问题,请参考以下文章

api-gateway实践新服务网关 - 测试发布(服务端API)

api-gateway实践(14)新服务网关 - 演示环境搭建

api-gateway实践(10)新服务网关-新需求验证api-gateway-engine携带有效token访问SvcApp

api-gateway实践(12)新服务网关 - 审批产生网关身份!

api-gateway实践新服务网关 - 网关请求监控统计

api-gateway实践(13)新服务网关 - SpringCloud Zuul