关于https:https如何使用pythonflask来实现

18次阅读

共计 5132 个字符,预计需要花费 13 分钟才能阅读完成。

摘要:个别 http 中存在申请信息明文传输,容易被窃听截取;数据的完整性未校验,容易被篡改;没有验证对方身份,存在假冒危险。面对这些问题,怎么破?

本文分享自华为云社区《https 如何应用 python+flask 来实现》,原文作者:SNHer。

一、为什么要用 https

个别 http 中存在如下问题:申请信息明文传输,容易被窃听截取;数据的完整性未校验,容易被篡改;没有验证对方身份,存在假冒危险。

HTTPS 又有哪些劣势?

1、应用 HTTPS 可认证用户和服务器,确保数据发送到正确的客户机和服务器。

2、HTTPS 是由 SSL+HTTP 协定构建的可进行加密传输、身份认证的网络协议,要比 http 协定平安,可避免数据在传输过程中不被窃取、扭转,确保数据的完整性。

3、HTTPS 是现行架构下最平安的解决方案,尽管不是相对平安,但它大幅减少了中间人攻打的老本。

二、https 中的证书是什么


CA:证书受权核心 (certificate authority) 相似于国家出入境管理处一样,给他人颁发护照;也相似于国家工商管理局一样,给公司企业颁发营业执照。它有两大次要性质:

  • CA 自身是受信赖的,国内认可的;
  • 给他受信赖的申请对象颁发证书。和办理护照一样,要确定你的非法身份,你不能是犯罪分子或造反派。当然,你须要被收保护费,同时,CA 能够随时撤消你的证书。

CA 的证书 ca.crt 和 SSL Server 的证书 server.crt 是什么关系呢?

  • SSL Server 本人生成一个 私钥 / 公钥对,server.key/server.pub。server.pub 生成一个申请文件 server.req。申请文件中蕴含有 server 的一些信息,如域名 / 申请者 / 公钥等。
  • server 将申请文件 server.req 递交给 CA,CA 验明正身后,将用 ca.key 和申请文件加密生成 server.crt 因为 ca.key 和 ca.crt 是一对, 于是 ca.crt 能够解密 server.crt。
  • 在理论利用中:如果 SSL Client 想要校验 SSL server. 那么 SSL server 必须要将他的证书 server.crt 传给 client. 而后 client 用 ca.crt 去校验 server.crt 的合法性。如果是一个钓鱼网站,那么 CA 是不会给他颁发非法 server.crt 证书的,这样 client 用 ca.crt 去校验,就会失败。

三、生成证书与密钥

shell 脚本

#!/bin/bash

PROJECT_NAME="https Project"

# Generate the openssl configuration files.
cat > ca_cert.conf << EOF
[req]
distinguished_name     = req_distinguished_name
prompt                 = no

[req_distinguished_name]
 O                      = $PROJECT_NAME Certificate Authority
EOF

cat > server_cert.conf << EOF
[req]
distinguished_name     = req_distinguished_name
prompt                 = no

[req_distinguished_name]
 O                      = $PROJECT_NAME
 CN                     = 
EOF

cat > client_cert.conf << EOF
[req]
distinguished_name     = req_distinguished_name
prompt                 = no

[req_distinguished_name]
 O                      = $PROJECT_NAME Device Certificate
 CN                     = 
EOF

mkdir ca
mkdir server
mkdir client

# 生成私钥
openssl genrsa -out ca.key 1024
openssl genrsa -out server.key 1024
openssl genrsa -out client.key 1024

# 依据私钥创立证书申请文件,须要输出一些证书的元信息:邮箱、域名等
openssl req -out ca.req -key ca.key -new -config ./ca_cert.conf
openssl req -out server.req -key server.key -new -config ./server_cert.conf
openssl req -out client.req -key client.key -new -config ./client_cert.conf

# 联合私钥和申请文件,创立自签订证书
openssl x509 -req -in ca.req -out ca.crt -sha1 -days 5000 -signkey ca.key
openssl x509 -req -in server.req -out server.crt -sha1 -CAcreateserial -days 5000 -CA ca.crt -CAkey ca.key
openssl x509 -req -in client.req -out client.crt -sha1 -CAcreateserial -days 5000 -CA ca.crt -CAkey ca.key

mv ca.crt ca.key ca/
mv server.crt server.key server/
mv client.crt client.key client/

rm *.conf
rm *.req
rm *.srl

一些命令的解释

openssl genrsa [-out filename] [-passout arg] [-des] [-des3] [-idea] [numbits]

选项阐明:-out filename:将生成的私钥保留至 filename 文件,若未指定输入文件,则为规范输入。-numbits:指定要生成的私钥的长度,默认为 1024。该项必须为命令行的最初一项参数。-des|-des3|-idea:指定加密私钥文件用的算法,这样每次应用私钥文件都将输出明码,太麻烦所以很少应用。-passout args:加密私钥文件时,传递明码的格局,如果要加密私钥文件时单未指定该项,则提醒输出明码。传递明码的 args 的格局

openssl req -out ca.req -key ca.key -new -config ./ca_cert.conf
次要命令选项:-new : 阐明生成证书申请文件
-key : 指定已有的秘钥文件生成秘钥申请,只与生成证书申请选项 -new 配合。-out : 指定生成的证书申请或者自签名证书名称

openssl x509 -req -in ca.req -out ca.crt -sha1 -days 5000 -signkey ca.key
openssl x509 命令具以下的一些性能,例如输入证书信息,签订证书申请文件、生成自签名证书、转换证书格局等。-in filename:指定证书输出文件,若同时指定了 "-req" 选项,则示意输出文件为证书申请文件,再应用 "-signkey" 提供自签订时应用的私钥。-out filename:指定输入文件
-days: 指定证书的无效工夫长短。缺省为 30 天

四、装置 flask

须要装置 python 的 openssl 的类库,应用 pip 装置

pip install pyOpenSSL

五、https 单向认证握手流程


python 实现

server 端:

from flask import Flask
app = Flask(__name__)

@app.route('/login')
def hello_world():
    return 'Hello World!'
 
if __name__ == '__main__':
    app.run(host="0.0.0.0", port=8091, ssl_context=('server.crt', 'server.key'))

客户端:

import urllib.request

import ssl

if __name__ == '__main__':
    CA_FILE = "ca.crt"
    context = ssl.SSLContext(ssl.PROTOCOL_TLS)
    context.check_hostname = False
    context.load_verify_locations(CA_FILE)
    context.verify_mode = ssl.CERT_REQUIRED
    try:
        request = urllib.request.Request('https://127.0.0.1:8091/login')
        res = urllib.request.urlopen(request, context=context)
        print(res.code)
        print(res.read().decode("utf-8"))
    except Exception as ex:
        print("Found Error in auth phase:%s" % str(ex))

六、https 双向认证握手流程

python 实现

客户端:

from flask import Flask, request, Response
import json

app = Flask(__name__)
@app.route("/login")
def hello():
    return "Hello World!"
@app.route('/login1', methods=['POST'])
def login():
    username = request.form.get("username")
    password = request.form.get("password")
    login_config = {"name": "pwd1"}
    if username in login_config.keys():
        if password == login_config[username]:
            return Response(json.dumps(True), status=200, mimetype='application/json')

    return Response(json.dumps(False), status=200, mimetype='application/json')
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8091, ssl_context=('server/server.crt', 'server/server.key'))

客户端:

import urllib.request

import ssl

if __name__ == '__main__':
    CA_FILE = "ca.crt"

    context = ssl.SSLContext(ssl.PROTOCOL_TLS)
    context.check_hostname = False
    context.load_verify_locations(CA_FILE)
    context.verify_mode = ssl.CERT_REQUIRED
    dict = {
        "username": "name",
        "password": "pwd1",
    }
    data = urllib.parse.urlencode(dict).encode('utf-8')
    try:
        request = urllib.request.Request('https://127.0.0.1:8091/login')
        res = urllib.request.urlopen(request, context=context)
        print(res.code)
        print(res.read().decode("utf-8"))
    except Exception as ex:
        print("Found Error in auth phase:%s" % str(ex))
    try:
        request = urllib.request.Request('https://127.0.0.1:8091/login1', data=data, method='POST')
        res = urllib.request.urlopen(request, context=context)
        print(res.code)
        print(res.read().decode("utf-8"))
    except Exception as ex:
        print("Found Error in auth phase:%s" % str(ex))

参考链接

openssl 命令(1): openssl req 命令详解

openssl 简介 - 指令 x509

openssl 命令(3): openssl x509 命令详解

OpenSSL 命令—pkcs12

十分钟搞懂 HTTP 和 HTTPS 协定?

Https 单向认证和双向认证

python 对于 SSL/TLS 认证的实现

点击关注,第一工夫理解华为云陈腐技术~

正文完
 0