https如何使用python+flask來實現

摘要:通常http中存在請求信息明文傳輸,容易被竊聽截取;數據的完整性未校驗,容易被篡改;沒有驗證對方身份,存在冒充危險。面對這些問題,怎麼破?

本文分享自華爲雲社區《https如何使用python+flask來實現》,原文做者:SNHer 。python

1、爲何要用https

通常http中存在以下問題:請求信息明文傳輸,容易被竊聽截取;數據的完整性未校驗,容易被篡改;沒有驗證對方身份,存在冒充危險。算法

HTTPS又有哪些優點?

一、使用HTTPS可認證用戶和服務器,確保數據發送到正確的客戶機和服務器。shell

二、HTTPS是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網絡協議,要比http協議安全,可防止數據在傳輸過程當中不被竊取、改變,確保數據的完整性。json

三、HTTPS是現行架構下最安全的解決方案,雖然不是絕對安全,但它大幅增長了中間人攻擊的成本。flask

2、https中的證書是什麼

image.png
CA:證書受權中心( certificate authority)相似於國家出入境管理處同樣,給別人頒發護照;也相似於國家工商管理局同樣,給公司企業頒發營業執照。它有兩大主要性質:segmentfault

  • 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去校驗,就會失敗。

3、生成證書與密鑰

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

一些命令的解釋bash

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天

4、安裝flask

須要安裝python 的 openssl 的類庫,使用pip 安裝服務器

pip install pyOpenSSL網絡

5、https單向認證握手流程

image.png
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))

6、https雙向認證握手流程

image.png

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認證的實現

點擊關注,第一時間瞭解華爲雲新鮮技術~

相關文章
相關標籤/搜索