构建服务器端应用程序——第5部分:保护应用程序
服务器端应用程序需要考虑的一个安全特性是验证对初始页面的HTTP请求是否来自合法的Zendesk产品实例。亚博
如果您愿意,Zendesk亚博可以在初始页面的请求中包含一个ZAF JSON Web令牌(JWT)。在收到请求后,服务器端应用程序可以检查签名令牌,以验证请求来自合法的Zendesk产品实例。亚博这有助于预防降级攻击.
签名令牌还包含许多属性(称为声明),服务器端应用程序可以使用这些属性来查找与Zendesk Support帐户相关的外部存储值。亚博
本教程描述了如何修改教程应用程序,以验证web应用程序初始页面的HTTP请求。它将引导您完成以下任务:
本教程是构建服务器端Zendesk应用程序系列的第五部分:亚博
- 第1部分:核心概念
- 第2部分:在Zendesk应用程序中显示服务器端内容亚博
- 第3部分:访问外部api
- 第4部分:访问框架api
- 第5部分:保护应用程序-你在这里
- 第6部分:部署应用程序
有关ZAF jwt的更多信息,请参见在服务器端应用程序中验证Zen亚博desk.
安装所需的库
您需要一个JWT客户端库来解码Zendesk发送的令牌。亚博PyJWT是Python的一个流行选择。
亚博Zendesk签署ZAF JWTRSA数字签名也就是RS256。PyJWT依赖于第二个Python库密码学来解码用RSA签名算法签名的令牌,所以你也需要安装它。
在空终端会话中,安装PyJWT包:
pip3安装PyJWT
安装密码程序包:
Pip3安装加密
获取Zendesk应用程序亚博的公钥和安装id
要解码ZAF JWT, PyJWT库需要Zendesk应用程序的公钥和安装id。亚博要获得公钥和安装id,首先需要安装Zendesk应用程序。亚博
如果正在运行,按Ctrl+C停止ZCLI web服务器。
在app_local文件夹,运行:
zcli应用程序:创建
该命令将Zendesk应用程序打包、上传并安装到Zendesk实例。亚博完成后,它返回应用程序的id。
要获取应用程序的公钥,请创建获取应用程序公钥要求:
卷曲https://{subdomain}.zen亚博desk.com/api/v2/apps/{app_id}/public_key.pem \
密码- u {email_address}: {}
取代
{app_id}
使用在第2步中接收到的id。请求返回应用程序的公钥PEM格式.安全保存密钥。您将在本教程的后面使用它。
-----开始公钥-----
MIIBIjAMBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm / mliC8BuDgagg2wUImH
6 + CAFetSzdGujOCjKdKCuFdwzXKzlt / EfFSlq8BLFD88XEjFljc + y1xzxHS13E
4 ak + CVKtZzInJswb5uQuJokJ0KbQGMudps7grabTklvzbQmoymnTXWTmAAi1IzyS
splm9JGkseja6C6oOt3CtM2wvF6h + nI4h5Zla6Nr + qhoqQlxvML9YKr93sWne8UJ
zasooccc / Q / c9emj9IaRSlGp1UFcEqIjrIZsIRwMmpYlqrf03o0MiDOhfkLnCpbj
91年zojutn / C17A2 / QoPKT6Txoyfl8kXu2p8MsT9dJvhv6qHXNHMBp75Sio6mmEAbb
lQIDAQAB
-----结束公钥-----
要获取应用程序的安装id,请使用应用程序安装列表要求:
卷曲https://{subdomain}.zen亚博desk.com/api/v2/apps/installations.json \
密码- u {email_address}: {}
在响应中,找到包含Zendesk应用程序的对象亚博
app_id
而且的名字
.对象的id
应用程序的安装id。例子:{
“安装”:[
...
{
“id”:1234567890123,
“app_id”:123456,
“产品”:“支持”,
“设置”:{
“名称”:“服务器端应用教程”,
“标题”:“服务器端应用教程”
},
....
}
]
}
在Zendesk中启用ZAF JWT亚博
启用ZAF JWT更新manifest.json安装Zendesk应用的文件。亚博
在app_local文件夹,添加一个顶级
“signedUrls”:真的
财产manifest.json.例子:{
...
“signedUrls”:真正的,
“位置”:{...},
...
}
保存manifest.json文件,但还没有更新你安装的Zendesk应用程序。亚博
您将在本教程的后面更新Zendesk亚博应用程序。
在服务器端应用程序中检索ZAF JWT
一旦ZAF JWT被启用,Zendesk会执行以下操作:亚博
- 将初始页面的请求方法从GET更改为POST。
- 在字段中包含一个已签名的JWT令牌
令牌
在POST请求的表单数据中。
您必须更新服务器端应用程序来执行以下任务:
- 处理web应用程序初始页面的POST请求。
- 从POST请求中的表单数据中获取令牌。
检索令牌
在app.py,将“/sidebar”路由修改为只接受POST请求(高亮显示):
@route(“/栏”,方法=“职位”)
defsend_iframe_html():
...
从请求的表单数据中检索令牌:
@route(“/栏”,方法=“职位”)
defsend_iframe_html():
令牌=请求.形式.得到(“令牌”)
...
如果没有找到令牌,则拒绝页面请求:
@route(“/栏”,方法=“职位”)
defsend_iframe_html():
令牌=请求.形式.得到(“令牌”)
如果不令牌:
返回“失踪的令牌。对不起,不行。”
...
验证ZAF JWT
从POST请求检索JWT令牌后,下一步是验证它。
PyJWT解码器需要两个东西来验证令牌:
- 您的公开密码匙
- 证明您的Zendesk应用程序是亚博令牌的预期受众
如果任意一个都不正确,解码器将返回令牌无效的错误。
Zendesk发行的令牌仅适用亚博于Zendesk应用程序。为了证明你的应用程序是预期的受众,你必须向解码器提供以下值:
https:// {your_subdomain}亚博 .zendesk.com/api/v2/apps/installations/ {app_installation_id} . json
解码器将尝试将其与令牌值中指定的受众进行匹配。值必须匹配,否则解码器将返回无效的令牌错误。
验证令牌
在app_remote文件夹中,将以下变量添加到.env文件:
...
亚博ZENDESK_APP_AUD = " https://{子域名}.zendesk.com/api/v2/apps/installations/ {app_installation_id} . json”
亚博ZENDESK_APP_PUBLIC_KEY = " {zendesk_app_key} "
取代
{子域名}
您的Zendesk帐亚博户的子域。取代{app_installation_id}
你保存的Zende亚博sk应用安装id获取Zendesk应用程序亚博的公钥和安装id.取代
{亚博zendesk_app_key}
使用您保存的公钥获取应用的Zendesk公钥和安装id亚博.包括开头和结尾注释以及任何换行符。确保该值用双引号(")括起来。例子:...
亚博ZENDESK_APP_PUBLIC_KEY = "——开始公钥
MIIBIjAMBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm / mliC8BuDgagg2wUImH
6 + CAFetSzdGujOCjKdKCuFdwzXKzlt / EfFSlq8BLFD88XEjFljc + y1xzxHS13E
4 ak + CVKtZzInJswb5uQuJokJ0KbQGMudps7grabTklvzbQmoymnTXWTmAAi1IzyS
splm9JGkseja6C6oOt3CtM2wvF6h + nI4h5Zla6Nr + qhoqQlxvML9YKr93sWne8UJ
zasooccc / Q / c9emj9IaRSlGp1UFcEqIjrIZsIRwMmpYlqrf03o0MiDOhfkLnCpbj
91年zojutn / C17A2 / QoPKT6Txoyfl8kXu2p8MsT9dJvhv6qHXNHMBp75Sio6mmEAbb
lQIDAQAB
-----结束公钥-----"
在app.py,在文件顶部添加PyJWT库,并使用以下语句:
进口jwt
进口操作系统
从操作系统.路径进口加入,目录名
...
在“/sidebar”路由中,替换以下突出显示的行:
@route(“/栏”,方法=“职位”)
defsend_iframe_html():
令牌=请求.形式.得到(“令牌”)
如果不令牌:
返回“失踪的令牌。对不起,不行。”
qs=请求.query_string
响应.set_cookie(“my_app_params”,qs)
返回模板(“开始”)
...
使用以下工具
try-except-else
块:@route(“/栏”,方法=“职位”)
defsend_iframe_html():
令牌=请求.形式.得到(“令牌”)
如果不令牌:
返回“失踪的令牌。对不起,不行。”
试一试:
关键=操作系统.环境.得到(“亚博ZENDESK_APP_PUBLIC_KEY”)
观众=操作系统.环境.得到(“亚博ZENDESK_APP_AUD”)
有效载荷=jwt.解码(令牌,关键,算法=[“RS256”],观众=观众)
除了jwt.InvalidTokenError:
返回'401无效的令牌。叫警察。”
其他的:
qs=请求.query_string
响应.set_cookie(“my_app_params”,qs)
返回模板(“开始”,qs=qs)
...
的
试一试
Block使jwt.decode ()
方法调用来验证令牌。调用使用令牌
,关键
,观众
参数。的
除了
控件的错误处理jwt.decode ()
调用。如果一个InvalidTokenError
在解码尝试期间引发异常,然后web应用程序返回错误消息并终止请求。如果没有引发异常,那么令牌是有效的,应用程序继续对页面请求进行正常响应。POST请求仍然包含url参数起源而且app_guide值。看到访问框架api在本教程系列的第1部分中。
注意有效载荷变量现在由一个包含所有令牌值的字典组成,这些令牌值也称为索赔.您可以通过以下方式访问索赔要求:
发行人=有效载荷[“国际空间站”]#例子,发行人=“example.亚博zendesk.com”
有关完整列表,请参见JWT索赔.
测试应用程序
要在Zendesk Support中测试更新的web应用程序:亚博
重新启动Bottle开发服务器。
在终端会话为空的情况下,在app_local文件夹:
zcli应用:更新
该命令更新manifest.json已安装应用程序的文件。
在您的浏览器中,登录到Zendesk Support并进亚博入代理工作区。从工作空间打开一个新的或现有的票据。
URL应该是这样的:
https://{子域名}.zendes亚博k.com/agent/tickets/ {ticket_id}
点击Apps图标。
应用程序显示开始页面。
中引入一个拼写错误,以测试JWT的错误处理
亚博ZENDESK_APP_AUD
变量.env.然后重新启动Bottle服务器并重新加载Agent Workspace页面。应用程序显示一条错误消息。当您完成测试时,请记住修复错别字。
您已经更新了web应用程序,以便它验证来自Zendesk的请求。亚博在下一篇教程中,您将部署您的web应用程序到Glitch进行托管。看到第6部分:部署应用程序.