在函数计算为HTTP触发器配置JWT认证鉴权,可以确保只有持有有效JWT的客户端才能访问,从而提升HTTP服务的安全性,有效防止未经授权的访问和阻挡恶意攻击。
背景信息
简介
函数计算支持为HTTP触发器开启JWT认证鉴权。JWT(JSON Web Token,RFC7519)是一种基于令牌的便捷请求认证鉴权方案。用户状态信息存储在Token中,由客户端提供,函数(服务端)无需存储,是一种Serverless友好的鉴权方式。函数计算可以通过用户绑定在HTTP触发器上的Public JWKS实现对HTTP调用请求的JWT认证。并根据HTTP触发器上的配置,将claims作为参数转发给函数,函数无需对请求进行鉴权,只需关注业务逻辑即可。如果需要了解JWT的Token认证流程及基础知识,请参见基于JWT的token认证和JWT简介。
JWT认证流程
上图是函数计算HTTP触发器利用JWT实现认证的整个业务流程时序图(使用非对称加密算法),步骤详细解析如下。
客户端向自定义授权服务发起认证请求,请求中一般会携带终端用户的用户名和密码。
自定义授权服务读取请求中的验证信息(例如用户名、密码等)进行验证,验证通过之后使用私钥生成标准的
Token。自定义授权服务将携带
Token的应答返回给客户端,客户端需要将这个Token缓存到本地。客户端向HTTP触发器发送业务请求,请求中携带
Token。HTTP触发器使用用户设置的公钥对请求中的
Token进行验证。验证通过之后,将请求透传给受保护的函数。
受保护的函数处理业务请求,并进行应答。
HTTP触发器将业务应答返回给客户端。
前提条件
使用限制
可以使用任何方式来生成和分发JWT,函数计算负责通过触发器配置的Public JWKS来认证JWT。
支持不含
kid的JWK。支持从
header、Query参数(GET)、表单参数(POST)和cookie中读取Token。支持将
claims作为header、表单参数(POST)和cookie转发给函数。函数计算支持为一个HTTP触发器配置一组JWT(JWKS),在JWKS中寻找与
Token中的kid相同的JWK公钥,并使用这个公钥对Token进行签名校验。一个触发器的JWKS最多只允许一个JWK的kid不存在或者为空字符串。目前函数计算的JWT支持如下算法。
签名算法
alg取值
RSASSA-PKCS1-V1_5
RS256,RS384,RS512
RSASSA-PSS
PS256,PS384,PS512
Elliptic Curve (ECDSA)
ES256,ES384,ES512
HMAC
HS256,HS384,HS512
EdDSA
EdDSA
重要HMAC签名算法为对称加密,安全性相对较低,建议使用安全性更高的非对称加密算法。
使用非对称加密算法时,出于安全考虑,您的JWT中只需要包含公钥信息即可,不建议包含私钥信息。
建议使用HTTPS来对请求中的
Token等敏感信息进行保护,可以有效避免Token泄漏。
操作步骤
步骤一:配置JWT认证
- 登录函数计算控制台,在左侧导航栏,单击服务及函数。
- 在顶部菜单栏,选择地域,然后在服务列表页面,单击目标服务。
- 在函数管理页面,单击目标函数名称,然后在函数详情页面,单击触发器管理(URL)页签。
在触发器管理(URL)页签,单击HTTP触发器操作列的编辑按钮。
在编辑触发器面板,设置以下配置项,然后单击确定。
认证方式选择为JWT 认证。

配置JWKS。
为HTTP触发器配置JWT鉴权,首先需要提供一个有效的JWKS(JSON Web Key Set)。您可以自行生成JWKS,或者搜索JSON Web Key Generator寻找在线可用的生成工具,例如mkjwk.org。如果您已经有pem格式的密钥,可以借助工具(例如jwx),将其转换为JWKS格式。
本文以使用mkjwk.org工具生成JWKS为例进行演示。如下图所示,在生成界面,Key Use选择Signature、Algorithm选择RS256、Show X.509选择Yes,然后单击Generate。在您的代码中需要使用Private Key(下图中①)签发JWT Token,请妥善保管。您可以复制Public Key(下图中②)中的内容填入到控制台JWKS配置的keys数组中。


本文配置的JWKS示例如下。
{ "keys": [ { "alg": "RS256", "e": "AQAB", "kty": "RSA", "n": "u1LWgoomekdOMfB1lEe96OHehd4XRNCbZRm96RqwOYTTc28Sc_U5wKV2umDzolfoI682ct2BNnRRahYgZPhbOCzHYM6i8sRXjz9Ghx3QHw9zrYACtArwQxrTFiejbfzDPGdPrMQg7T8wjtLtkSyDmCzeXpbIdwmxuLyt_ahLfHelr94kEksMDa42V4Fi5bMW4cCLjlEKzBEHGmFdT8UbLPCvpgsM84JK63e5ifdeI9NdadbC8ZMiR--dFCujT7AgRRyMzxgdn2l-nZJ2ZaYzbLUtAW5_U2kfRVkDNa8d1g__2V5zjU6nfLJ1S2MoXMgRgDPeHpEehZVu2kNaSFvDUQ", "use": "sig" } ] }在JWT Token 配置配置项中,选择
Token所在位置和Token的名称。Token位置支持Header、Cookie、Query参数(GET)和表单参数(POST)。如果Token位置选择为Header,则还需为其指定参数名称和去除前缀。函数计算在获取Token时,会删除去除前缀中设定的前缀内容。
重要设定去除前缀时,请注意前缀后面是否存在空格。推荐在前缀字段后加一个空格,例如
Bearer。在JWT Claim 转换配置项中,选择透传给函数的参数所在位置、参数原始名称和参数透传给函数之后的名称。
映射参数位置支持Header、Cookie和表单参数(POST)。

设置请求匹配模式。
匹配全部:所有HTTP请求都需要进行JWT校验。
白名单模式:请求路径白名单中设置的Path的HTTP请求不需要JWT校验,其他请求需要JWT校验。
黑名单模式:请求路径黑名单中设置的Path的HTTP请求需要JWT校验,其他请求不需要JWT校验。
白名单模式和黑名单模式支持以下两种匹配模式。
精确匹配
请求的路径和设置的路径完全一致才可以匹配。例如,设置请求路径黑名单为/a,则来自路径/a的请求需要JWT校验,来自路径/a/的请求无需校验。
模糊匹配
支持使用通配符(*)设置路径,且通配符(*)只能放到路径的最后。例如,设置请求路径黑名单为/login/*,则来自路径前缀为/login/(例如/login/a、/login/b/c/d)的请求均需要JWT校验。
步骤二:操作验证
在调测工具(本文以Postman工具为例)中,根据HTTP触发器的JWT配置,填写访问地址、Token等,验证是否可以正常访问HTTP服务。
使用步骤一中生成的X.509 PEM格式的Private Key作为私钥来颁发JWT Token。以下步骤以Python为例演示通过本地脚本生成Token的过程。
安装 PyJWT模块。
pip install 'PyJWT>=2.0'在本地运行如下Python示例脚本生成JWT Token。
import jwt import time private_key = """ -----BEGIN PRIVATE KEY----- <使用步骤一生成的 X.509 PEM格式的private key> -----END PRIVATE KEY----- """ headers = { "alg": "RS256", "typ": "JWT" } payload = { "sub": "1234567890", "name": "John Snow", "iat": int(time.time()), # token颁发时间 "exp": int(time.time()) + 60 * 60, # 设定token有效时间为1小时 } encoded = jwt.encode(payload=payload, key=private_key.encode(), headers=headers) print("Generated token: %s" % encoded)
使用Postman工具验证HTTP服务是否可正常访问。
在目标函数的触发器管理(URL)页签获取HTTP触发器的公网访问地址,将地址填入Postman的URL位置。
在Postman的Headers配置Token参数信息,然后单击Send发送请求。本文填写的Token示例如下。
名称
示例值
说明
Key
Authentication在JWT Token 配置中设置的参数名称。
Value
Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSm9uIFNub3ciLCJhZG1pbiI6dHJ1ZSwiZXhwIjo0ODI5NTk3NjQxfQ.eRcobbpjAd3OSMxcWbmbicOTLjO2vuLR9F2QZMK4rz1JqfSRHgwQVqNxcfOIO9ckDMNlF_3jtdfCfvXfka-phJZpHmnaQJxmnOA8zA3R4wF4GUQdz5zkt74cK9jLAXpokwrviz2ROehwxTCwa0naRd_N9eFhvTRnP3u7L0xn3ll4iOf8Q4jS0mVLpjyTa5WiBkN5xi9hkFxd__p98Pah_Yf0hVQ2ldGSyTtAMmdM1Bvzad-kdZ_wW0jcctIla9bLnOo-Enr14EsGvziMh_QTZ3HQtJuToSKZ11xkNgaz7an5de6PuF5ISXQzxigpFVIkG765aEDVtEnFkMO0xyPGLg在JWT Token 配置中设置的去除前缀信息拼接JWT Token。示例值假设去除前缀已设置为
Bearer。重要请注意,请求header中JWT参数的前缀和空格需要与JWT Token 配置中设置的去除前缀内容一致,否则会导致触发器解析Token时出错并返回invalid or expired jwt错误。
配合自定义域名使用JWT鉴权
如上图所示,自定义域名位于HTTP触发器之前,用户的请求会先经过自定义域名的处理,然后才会被HTTP触发器处理,JWT认证鉴权是位于HTTP触发器上的逻辑。下文介绍自定义域名如何使用JWT认证鉴权。
普通自定义域名
如果为自定义域名配置了路由,未配置重写策略,那么到达HTTP请求中的Path就是自定义域名请求的Path。
假设自定义域名www.fc-jwt.com设置的路由规则如下,且函数jwt-demo的HTTP触发器设置的JWT鉴权配置中请求路径黑名单配置为/fc-jwt/auth/*。
路径 | 服务名 | 函数名 | 版本 |
/fc-jwt/* | jwt | jwt-demo | 1 |
如果用户请求URL为/fc-jwt/auth/aliyun,则HTTP触发器会对请求进行校验,因为到达HTTP触发器的请求的Path与设置的请求路径黑名单匹配。
结合自定义域名的重写功能
如果为自定义域名配置了路由,且配置了重写策略,那么到达HTTP请求中的Path为自定义域名重写后的Path。关于自定义域名的重写功能,请参见配置重写策略(公测中)。
假设自定义域名www.fc-jwt.com设置的路由规则如下,函数jwt-demo的HTTP触发器设置的JWT鉴权配置中请求路径黑名单配置为/fc-jwt/auth/*,且配置了通配符重写策略(匹配规则为/fc-jwt/*,替换规则为 /$1)。
路径 | 服务名 | 函数名 | 版本 |
/fc-jwt/* | jwt | jwt-demo | 1 |
如果用户请求URL为/fc-jwt/auth/aliyun,则重写后的URL为/auth/aliyun。关于通配符重写规则,请参见通配符重写。此时,HTTP触发器不会对请求进行校验,因为到达HTTP触发器的请求的Path为/auth/aliyun,与设置的请求路径黑名单不匹配。
如果将触发器请求路径黑名单配置为/auth/*,那么HTTP触发器会对URL为/fc-jwt/auth/aliyun的请求进行JWT校验。