HTTPSサーバ
自作製品開発中にhttps serverが必要になる事が有ります。 今回はRaspberry PIでhttps serverを上げてみます。
暗号化通信の https には証明書が必要になります。 今回は ”mkcert” を使い証明書を作成して行きます。まずは mkcert の Install から
mkcertのInstallと証明書作成
Installの手順
次に mkcert を使ってローカルCA(認証局)をシステムにインストールします。
mkcert localhost を実行してlocalhost に対しての証明書と秘密鍵を生成します。
これで localhost-key.pem と localhost.pem の2つのファイルが作成されます。
Pythonでhttps server
前回のコード "hello.py" をHTTPS対応に修正しました。(ファイル名は”hello_https.py") 変更箇所をハイライトしています。
from http.server import HTTPServer, SimpleHTTPRequestHandler
from urllib.parse import urlparse,parse_qs
import os
from gpiozero import LED
import datetime
import subprocess
import ssl
def file_list():
subprocess.run('date +"%Y/%m/%d %H:%M:%S" > file_list.txt', shell=True)
subprocess.run("ls >> file_list.txt", shell=True)
def get_time():
now = datetime.datetime.now()
time_str = now.strftime('%Y-%m-%d %H:%M:%S')
fp = open("time.txt",'w')
fp.write(time_str)
fp.close()
class MyHandler(SimpleHTTPRequestHandler):
def do_GET(self):
global btn_0
allowed_extensions = {'.html', '.css', '.js', '.ico', '.png', '.txt'}
_, ext = os.path.splitext(self.path)
if self.path == "/" or ext.lower() in allowed_extensions:
return super().do_GET()
else :
self.send_response(200)
self.send_header('Content-type', "text/html")
self.end_headers()
parsed = urlparse(self.path)
params = parse_qs(parsed.query)
a = next(iter(params))
flg = 1
#----- LED ON/OFF --------------
if a == "btn0":
btn_0 ^= 1
if btn_0 == 1 :
led.on()
else :
led.off()
print("ボタン0が押されました")
#----- 時間の取得 -----------------
elif a == "btn1":
get_time()
print("ボタン1が押されました")
#----- ファイルリストの作製 -------
elif a == "m_dir":
file_list()
#----- 状態を送る -----------------
elif a == "80":
self.wfile.write(str(btn_0).encode("utf-8"))
flg = 0
if flg == 1:
fp = open("index.html",'rb')
self.wfile.write(fp.read())
fp.close()
#---------------------------------------------------------
btn_0 = 0
led = LED(17)
led.off()
get_time()
file_list()
# SSLを設定
host = ''
port = 443
httpd = HTTPServer((host, port), MyHandler)
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain(certfile='./localhost.pem', keyfile='./localhost-key.pem')
httpd.socket = context.wrap_socket(httpd.socket, server_side=True)
# 起動
print("HTTPS Server running on https://x.x.x.x:443")
httpd.serve_forever()
- 9行:import ssl
- 79行:port = 443
- SSLは通常ポートの443を使用する様です。
- もちろん他のポートでもOK
- 83行:context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
- セキュリティ設定を格納するインスタンスを作成
- 84行:<context.load_cert_chain(certfile='./localhost.pem', keyfile='./localhost-key.pem')
- 証明書と秘密鍵の読み込み
- 85行:httpd.socket = context.wrap_socket(httpd.socket, server_side=True)
- ソケット作製
ブラウザで確認
前回同様、 index.html、 http_server.js、 http_server.css、 http_server.py の4つの ファイル に加え、localhost-key.pem と localhost.pem の2つのファイルを同じフォルダに保存し サーバを sudo python3 hello_https.py で実行。その後別のPCでブラウザ (Firefox)を上げてURL欄に https://raspberrypi.local:443 と入力してサーバにアクセスします。
自分で製作した証明書は正式のそれと違いブラウザに危険性の有るページと判断されます。 そこで使用しても問題無いとブラウザに登録します。
- URL欄に https://raspberrypi.local:443 と入力
- この画面が表示されます。右下の”詳細へ”をクリック
- 次はこの画面が表示されます。”危険性を承知の上で使用”をクリック
- やっとHPが表示されましたが、URLの鍵マークにびっくりマーク”!”が有ります。
- ”!” は SSLとして危険性の有るページを表示しているという意味
この様に自分で作製した証明書を使うと鍵アイコンの下にびっくりマークが付きますがHttpsとして問題無く使用出来ます。
最後に
これでPython HTTP_Serverの説明を終わります。