如何在Python Flask应用中用AES_256解密Ping Identity的SAML响应
Flask接收SAML响应配置
依赖安装
首先安装SAML处理依赖:
pip install pysaml2 flask pycryptodome
基础配置步骤
- 提前从Ping Identity控制台导出IdP元数据文件,同时生成SP侧的RSA密钥对(公钥给到Ping Identity侧配置断言加密使用,私钥保存在你的服务本地)
- 在Flask项目中添加SAML SP配置,示例如下:
from saml2 import config from saml2.client import Saml2Client from flask import Flask, request app = Flask(__name__) SAML_CONFIG = { 'entityid': '你的SP实体ID', 'service': { 'sp': { 'name': '你的服务名称', 'endpoints': { 'assertion_consumer_service': [ ('https://你的服务域名/saml/acs', config.BINDING_HTTP_POST), ], }, # 配置解密用的私钥路径 'key_file': '本地路径/to/your/private.key', # 配置签名用的公钥路径 'cert_file': '本地路径/to/your/public.crt', # 开启断言解密支持 'want_assertions_encrypted': True, } }, # Ping Identity的IdP元数据路径 'metadata': { 'local': ['本地路径/to/ping-identity-metadata.xml'] }, # 指定加密算法为AES-256 'encryption_algorithm': 'http://www.w3.org/2001/04/xmlenc#aes256-cbc', 'key_transport_algorithm': 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p', } saml_client = Saml2Client(config=config.SPConfig().load(SAML_CONFIG))
- 配置ACS路由接收SAML响应:
@app.route('/saml/acs', methods=['POST']) def saml_acs(): saml_response = request.form.get('SAMLResponse') if not saml_response: return '无效SAML响应', 400 # 后续响应解析、断言解密逻辑放在这里
AES-256解密SAML断言实现
SAML断言的加密逻辑为:Ping Identity用随机生成的AES-256密钥加密明文断言,再用你提供的SP公钥加密这个AES密钥,加密后的密钥和加密断言会一并放在SAML响应的EncryptedAssertion节点中,解密步骤如下:
解密逻辑代码示例
import base64 from xml.etree import ElementTree as ET from Crypto.Cipher import AES from Crypto.Util.Padding import unpad from saml2.sigver import decrypt_key def decrypt_saml_assertion(encrypted_saml_response): # 1. 解码base64格式的SAML响应 decoded_resp = base64.b64decode(encrypted_saml_response) resp_root = ET.fromstring(decoded_resp) # 2. 提取加密的AES密钥、初始化向量和加密断言数据 encrypted_assertion = resp_root.find('.//{urn:oasis:names:tc:SAML:2.0:assertion}EncryptedAssertion') encrypted_key = encrypted_assertion.find('.//{http://www.w3.org/2001/04/xmlenc#}EncryptedKey') encrypted_data = encrypted_assertion.find('.//{http://www.w3.org/2001/04/xmlenc#}EncryptedData') cipher_value = encrypted_data.find('.//{http://www.w3.org/2001/04/xmlenc#}CipherValue').text iv = encrypted_data.find('.//{http://www.w3.org/2001/04/xmlenc#}IV').text # 3. 用SP私钥解密得到AES-256密钥 aes_key = decrypt_key(encrypted_key, SAML_CONFIG['service']['sp']['key_file']) # 4. 用AES-256密钥解密断言内容 cipher = AES.new(aes_key, AES.MODE_CBC, iv=base64.b64decode(iv)) decrypted_data = cipher.decrypt(base64.b64decode(cipher_value)) plain_assertion = unpad(decrypted_data, AES.block_size) return plain_assertion.decode('utf-8')
注意事项
- Ping Identity侧配置断言加密时,必须选择AES-256算法,和你的服务配置保持一致
- 解密后必须对断言做签名校验,避免数据被篡改
- 私钥文件必须严格管控访问权限,不要提交到代码仓库
内容的提问来源于stack exchange,提问作者Harmeet Singh Pable
相关产品推荐
相关产品推荐

