翼度科技»论坛 编程开发 python 查看内容

[flask]使用mTLS双向加密认证http通信

6

主题

6

帖子

18

积分

新手上路

Rank: 1

积分
18
前言

mTLS,全称为双向TLS(Mutual Transport Layer Security),是一种安全通信协议,确保通信双方在传输层进行身份验证。与单向HTTPS不同,吗TLS不仅要求客户端验证服务端的身份,还要求服务端验证客户端的身份。
生成证书

常见的证书生成方式就是自签名证书,有条件的话还是自建CA机构或者购买专门的证书。

  • 生成ca根证书。生成过程中会提示填写密码,记住密码,后续会用到。这里直接声明Common Name为qw.er.com,可根据实际需求修改ON、OU、CN等信息。
  1. openssl req -x509 -newkey rsa:4096 -keyout ca.key -out ca.crt -subj "/CN=qw.er.com"  -days 3650
复制代码

  • 新建并编辑openssl.cnf文件,根据实际需求修改CN、CN等信息
  1. [req]
  2. req_extensions = v3_req
  3. distinguished_name = req_distinguished_name
  4. prompt = no
  5. [req_distinguished_name]
  6. countryName = CN
  7. stateOrProvinceName = Anhui
  8. localityName = Hefei
  9. organizationName = zhangsan
  10. commonName = qw.er.com
  11. [v3_req]
  12. subjectAltName = @alt_names
  13. [alt_names]
  14. DNS.1 = qw.er.com
复制代码

  • 创建服务端证书。生成私钥文件时会提示输入根证书密码。
  1. openssl req -newkey rsa:2048 -nodes -keyout server.key -out server.csr -subj "/CN=qw.er.com" -config openssl.cnf
  2. openssl x509 -req -in server.csr -out server.crt -CA ca.crt -CAkey ca.key -CAcreateserial -days 365 -extensions v3_req -extfile openssl.cnf
复制代码

  • 创建客户端证书。生成私钥文件时会提示输入根证书密码
  1. openssl req -newkey rsa:2048 -nodes -keyout client.key -out client.csr -subj "/CN=qw.er.com" -config openssl.cnf
  2. openssl x509 -req -in client.csr -out client.crt -CA ca.crt -CAkey ca.key -CAcreateserial -days 365 -extensions v3_req -extfile openssl.cnf
复制代码
服务端示例

除了flask本身,只需要导入标准库ssl。注意证书路径需要是绝对路径。
  1. from flask import Flask
  2. import ssl
  3. app = Flask(__name__)
  4. @app.get("/health")
  5. def health():
  6.     return "ok"
  7. def get_ssl_context():
  8.     ca_crt_path = "/home/atlas/workspace/flask-learn/certs/ca.crt"
  9.     server_crt = "/home/atlas/workspace/flask-learn/certs/server.crt"
  10.     server_key = "/home/atlas/workspace/flask-learn/certs/server.key"
  11.     password = "qwerasdf"
  12.     context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLS_SERVER)
  13.     context.verify_mode = ssl.CERT_REQUIRED
  14.     context.load_verify_locations(ca_crt_path)
  15.     context.load_cert_chain(certfile=server_crt, keyfile=server_key, password=password)
  16.     return context
  17. if __name__ == "__main__":
  18.     ssl_context = get_ssl_context()
  19.     app.run(host="0.0.0.0", port=5000, ssl_context=ssl_context)
复制代码
客户端示例


  • 方式1:使用curl命令
  1. curl -k --cacert ca.crt --key client.key --cert client.crt https://127.0.0.1:5000/health
复制代码

  • 方式2:使用requests库。注意修改hosts文件将qw.er.com映射到IP
  1. import requests
  2. ca_crt_path = "/home/atlas/workspace/flask-learn/certs/ca.crt"
  3. client_crt = "/home/atlas/workspace/flask-learn/certs/client.crt"
  4. client_key = "/home/atlas/workspace/flask-learn/certs/client.key"
  5. url = "https://qw.er.com:5000/health"
  6. resp = requests.get(url, cert=(client_crt, client_key), verify=ca_crt_path)
  7. print(resp.status_code)
  8. print(resp.text)
复制代码

  • 方式3:使用httpx库。注意修改hosts文件将qw.er.com映射到IP
  1. import httpx
  2. import ssl
  3. def get_ssl_context():
  4.     password = "qwerasdf"
  5.         ca_crt_path = "/home/atlas/workspace/flask-learn/certs/ca.crt"
  6.         client_crt = "/home/atlas/workspace/flask-learn/certs/client.crt"
  7.         client_key = "/home/atlas/workspace/flask-learn/certs/client.key"
  8.     context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLS_CLIENT)
  9.     context.verify_mode = ssl.CERT_REQUIRED
  10.     context.load_verify_locations(ca_crt_path)
  11.     context.load_cert_chain(certfile=client_crt, keyfile=client_key, password=password)
  12.     return context
  13. url = "https://qw.er.com:5000/health"
  14. context = get_ssl_context()
  15. with httpx.Client(verify=context) as client:
  16.     resp = client.get(url)
  17.     print(resp.status_code)
  18.     print(resp.text)
复制代码
来源:https://www.cnblogs.com/XY-Heruo/p/18324384
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具