基于WSO2-AM的JWT传递问题咨询:如何转发原始JWT至后端服务
我之前在基于WSO2 AM搭建API管理POC时,正好碰到过和你完全一样的需求——既要利用网关做权限校验和限流,又得把用户从IDP拿到的原始JWT传给后端服务。咱们来拆解下最优的解决方案,先聊聊你提到的两个方案的问题,再给出落地性强的办法:
先明确现有方案的痛点
- 官方生成新JWT的方案:确实是WSO2推荐的做法,但它生成的是网关签发的JWT,虽然能映射用户角色等声明,但不是IDP签发的原始JWT——如果后端服务依赖原始JWT的签名、签发者(iss)等字段做验证,这个方案就不适用了。
- 自定义HTTP头传递:虽然可行,但需要应用额外添加头字段,而且如果后端原本依赖
Authorization: Bearer <原始JWT>的格式,还要改后端的逻辑,不够优雅。
最优方案1:结合JWT Grant Type + 自定义Claim传递原始JWT
这个方案既利用了网关的OAuth2流程,又能把原始JWT完整传递给后端,步骤如下:
配置JWT Grant Type
先在身份提供商(WSO2 IS)里开启JWT Grant Type,这样消费应用可以直接用从IDP拿到的原始用户JWT,去换取WSO2 AM的API访问令牌。这个过程中,网关会先用IDP的公钥验证原始JWT的有效性,确保用户身份合法。添加自定义Claim映射原始JWT
- 在WSO2 IS的Claim管理中,新增一个自定义Claim(比如
http://your-org.com/claims/original_jwt) - 在JWT Grant Type的配置里,把原始JWT的完整内容映射到这个自定义Claim上。这样,当应用用原始JWT换网关访问令牌时,网关会把原始JWT作为一个属性存在访问令牌的上下文里。
- 在WSO2 IS的Claim管理中,新增一个自定义Claim(比如
配置API传递自定义Claim到后端
在WSO2 AM的API配置中,开启「Pass Enduser Attributes to Backend Using JWT」,然后把刚才的自定义Claim加入到要传递的Claim列表中。这样网关转发请求时,会把包含原始JWT的新JWT放在X-JWT-Assertion头里传给后端。后端服务可以从
X-JWT-Assertion头解析出网关生成的JWT,然后提取里面的original_jwt字段,拿到用户的原始JWT。同时,后端也可以选择验证网关生成的JWT(用WSO2 AM的公钥),确保请求经过了合法的网关。
最优方案2:利用网关中介扩展(Mediation Sequence)直接转发原始JWT
如果后端必须要原始JWT放在特定的请求头(比如还是想用Authorization头,但网关要求这个头放访问令牌),可以用WSO2 AM的中介脚本实现:
让应用传递原始JWT到网关
消费应用在请求网关时,除了Authorization: Bearer <网关访问令牌>,额外添加一个自定义头,比如X-Original-User-JWT,把原始JWT放在这个头里。创建自定义入站Sequence
在WSO2 AM中创建一个入站Sequence,逻辑如下:- 先验证网关的访问令牌(这一步是网关默认的流程)
- 验证通过后,保留
X-Original-User-JWT头,直接转发给后端服务 - (可选)如果不想让应用额外传头,也可以在Sequence里从网关的认证上下文里提取原始JWT(因为用JWT Grant Type换取访问令牌时,网关已经拿到了原始JWT),然后自动添加到请求头中。
示例中介脚本(简化版):
<sequence xmlns="http://ws.apache.org/ns/synapse" name="PassOriginalJWT"> <!-- 验证网关访问令牌(默认流程,无需额外配置) --> <property name="X-Original-User-JWT" expression="$ctx:oauth2_original_jwt" scope="transport"/> <!-- 转发请求到后端 --> <send/> </sequence>
注意事项
- 安全层面:不管用哪种方案,网关和后端之间一定要用HTTPS通信,防止JWT在传输过程中被窃听。
- 验证逻辑:如果后端需要二次验证原始JWT,要保留IDP的公钥;如果信任网关的验证,也可以只验证网关生成的JWT,直接使用传递的原始JWT内容。
- 性能影响:传递完整的JWT会增加请求的大小,如果JWT包含很多声明,要评估对性能的影响。
内容的提问来源于stack exchange,提问作者Torsten

