OK、このクエストは完了しましたが、最初に言いたいのは、後で行ったように、https の LetsEncrypt 無料証明書を取得する方がはるかに簡単であるということです。
このソリューションでは、openssl をインストールする必要があります。
ajax のビューを書きましょう
公開鍵の取得。プロジェクト ディレクトリにない場合は、ペアを生成します。
def public_key(req):
if not os.path.isfile(os.path.join(settings.BASE_DIR, 'form_key.pem')) or not os.path.isfile(os.path.join( settings.BASE_DIR,'form_key_pub.pem')):
check_call(['openssl', 'genrsa', '-out', os.path.join(settings.BASE_DIR,'form_key.pem'), '4096'])
check_call(['openssl', 'rsa', '-pubout', '-in', os.path.join(settings.BASE_DIR,'form_key.pem'), '-out', os.path.join(settings.BASE_DIR,'form_key_pub.pem')])
f = open(os.path.join(settings.BASE_DIR,'form_key_pub.pem'))
key = f.read()
f.close()
return JsonResponse({"publickey": key})
よし、そして握手。このビューを CSRF で保護するには、jCryption JavaScript ライブラリにパッチを適用する必要があります。ここで、AES キーをセッション ストレージに保存します。
@csrf_exempt
def handshake(req):
if req.method == 'POST':
encb64key = req.POST['key']
encb64key = re.sub(r'[^a-zA-Z0-9/=+]', '', encb64key)
enckey = b64decode(encb64key)
openssl = Popen(['openssl', 'rsautl', '-decrypt', '-inkey', os.path.join(settings.BASE_DIR,'form_key.pem')], stdin = PIPE, stdout=PIPE, stderr=PIPE)
key, stderr = openssl.communicate(enckey)
print stderr
key = re.sub(r'[^a-zA-Z0-9]', '', key)
req.session['form_key'] = key
openssl = Popen(['openssl', 'enc', '-aes-256-cbc', '-pass', 'pass:'+key, '-a', '-e'], stdin = PIPE, stdout = PIPE, stderr = PIPE)
enckey , stderr = openssl.communicate(key)
print stderr
enckey = re.sub('[^a-zA-Z0-9/+=]', '' , enckey)
return JsonResponse({'challenge': enckey})
raise Http404()
urls.py でビューの URL を選択しましょう
url('^pubkey', public_key, name = 'publickey'),
url('^handshake', handshake, name = 'handshake'),
そして、最もトリッキーな部分。独自のミドルウェア。settings.py の MIDDLEWARE_CLASSES に追加する必要があります。myapp の views.py ファイルに配置すると、「myapp.views.JCryptionMiddleware」のようなものになります。
トリックは、「jCryption」属性のみで間違った POST データを送信することです。ミドルウェアは、この attr 内の適切なデータを復号化し、それを使用して request オブジェクト内の POST データを書き換えます。Django ドキュメントでミドルウェアについて読んでください。
class JCryptionMiddleware(object):
def process_view(self, request, callback, callback_args, callback_kwargs):
jcryptedb64 = request.POST.get('jCryption', '')
if jcryptedb64:
try:
jcrypted = b64decode(jcryptedb64)
p = Popen(['openssl', 'enc', '-aes-256-cbc', '-pass', 'pass:'+request.session['form_key'], '-d'], stdin = PIPE, stdout = PIPE, stderr = PIPE)
qstr, stderr = p.communicate(jcrypted)
print stderr
wasmutable = request.POST._mutable
request.POST._mutable = True
request.POST.__init__(qstr)
request.POST._mutable = wasmutable
except Exception as e:
print e
return None
フォーム テンプレートを含むページ内のクライアント コード。
<script src="{{ STATIC_URL }}js/jquery.min.js"></script>
<script src="{{ STATIC_URL }}js/jcryption.js"></script>
<script>
$(function() {
$('form').jCryption({"getKeysURL": "/pubkey", "handshakeURL": "/handshake"});
});
</script>
urls.py の URL を参照してください。
たとえば、管理者ログイン フォームを暗号化できます。login.html を django contrib admin から templates/admin/login.html にコピーし、この JavaScript コードをテンプレートに追加します。
タダ!これを使用しないでください。HTTPS を使用してください。