質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.36%
Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

WSL(Windows Subsystem for Linux)

WSL (Windows Subsystem for Linux) は、Windows10のOS上でLinux向けのバイナリプログラムを実行可能にする機能です。また、WindowsOSのAPIを用いた仕組みを提供しており、Linux側からWindowsOSへのファイルアクセスもできます。

SSL

SSL(Secure Sockets Layer)とは、暗号化されたプロトコルで、インターネット上での通信セキュリティを提供しています。

Q&A

0回答

1427閲覧

Django reCAPTCHA 認証時、WSL上の環境でのみ内部SSLエラーが出る

larksiper

総合スコア11

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

WSL(Windows Subsystem for Linux)

WSL (Windows Subsystem for Linux) は、Windows10のOS上でLinux向けのバイナリプログラムを実行可能にする機能です。また、WindowsOSのAPIを用いた仕組みを提供しており、Linux側からWindowsOSへのファイルアクセスもできます。

SSL

SSL(Secure Sockets Layer)とは、暗号化されたプロトコルで、インターネット上での通信セキュリティを提供しています。

0グッド

0クリップ

投稿2021/08/14 13:36

編集2021/08/16 13:45

前提・実現したいこと

djangoの講座動画などを参考に現在recaptchaの実装を行っているのですが、
その前段階のrecaptchaでの確認部分にて内部のSSLエラーが発生しています。

GAEの本番環境で動かした場合はエラーが出ず問題なく確認が可能であったため、
内部の環境(WSL2 + ubuntu20.04LTS)起因によるエラーを疑っています。
色々試しましたが、解決できない状況が続いているためお力をお借りしたいです。

エラーメッセージ

実際にrecapthhaを用いてformで入力・送信を行った瞬間、
下記のようにrecaptcha用の認証サイトに入る段階でurlopen内部でエラーが出ています。

python

1"GET /contact/ HTTP/1.1" 200 5188 2Internal Server Error: /contact/ 3Traceback (most recent call last): 4 File "/usr/lib/python3.8/urllib/request.py", line 1354, in do_open 5 h.request(req.get_method(), req.selector, req.data, headers, 6 File "/usr/lib/python3.8/http/client.py", line 1252, in request 7 self._send_request(method, url, body, headers, encode_chunked) 8 File "/usr/lib/python3.8/http/client.py", line 1298, in _send_request 9 self.endheaders(body, encode_chunked=encode_chunked) 10 File "/usr/lib/python3.8/http/client.py", line 1247, in endheaders 11 self._send_output(message_body, encode_chunked=encode_chunked) 12 File "/usr/lib/python3.8/http/client.py", line 1007, in _send_output 13 self.send(msg) 14 File "/usr/lib/python3.8/http/client.py", line 947, in send 15 self.connect() 16 File "/usr/lib/python3.8/http/client.py", line 1421, in connect 17 self.sock = self._context.wrap_socket(self.sock, 18 File "/usr/lib/python3.8/ssl.py", line 500, in wrap_socket 19 return self.sslsocket_class._create( 20 File "/usr/lib/python3.8/ssl.py", line 1040, in _create 21 self.do_handshake() 22 File "/usr/lib/python3.8/ssl.py", line 1309, in do_handshake 23 self._sslobj.do_handshake() 24ssl.SSLError: [SSL] internal error (_ssl.c:1131) 25 26During handling of the above exception, another exception occurred: 27 28Traceback (most recent call last): 29 File "ReallySite/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner 30 response = get_response(request) 31 File "ReallySite/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response 32 response = wrapped_callback(request, *callback_args, **callback_kwargs) 33 File "ReallySite/mysite/views.py", line 77, in contact 34 res = grecaptcha_request(recaptcha_token) 35 File "ReallySite/mysite/views.py", line 113, in grecaptcha_request 36 f = request.urlopen(req, context=context) 37 File "/usr/lib/python3.8/urllib/request.py", line 222, in urlopen 38 return opener.open(url, data, timeout) 39 File "/usr/lib/python3.8/urllib/request.py", line 525, in open 40 response = self._open(req, data) 41 File "/usr/lib/python3.8/urllib/request.py", line 542, in _open 42 result = self._call_chain(self.handle_open, protocol, protocol + 43 File "/usr/lib/python3.8/urllib/request.py", line 502, in _call_chain 44 result = func(*args) 45 File "/usr/lib/python3.8/urllib/request.py", line 1397, in https_open 46 return self.do_open(http.client.HTTPSConnection, req, 47 File "/usr/lib/python3.8/urllib/request.py", line 1357, in do_open 48 raise URLError(err) 49urllib.error.URLError: <urlopen error [SSL] internal error (_ssl.c:1131)> 50[10/Aug/2021 21:49:24] "POST /contact/ HTTP/1.1" 500 103432

該当のソースコード

ソース部分は講座に挙げられていた内容そのままです。(実際に比較も行いソース上問題ないことは確認済みです)
今回Recapthcaを入れているmysite/view.py部分となります。

python

1def contact(request): 2 context={ 3 'grecaptcha_sitekey': os.environ['GRECAPTCHA_SITEKEY'], 4 } 5 6 print(os.environ['GRECAPTCHA_SITEKEY']) 7 if request.method == "POST": 8 #reCAPTHA要のトークンを取得 9 recaptcha_token = request.POST.get('g-recaptcha-response') 10 res = grecaptcha_request(recaptcha_token) 11 # メール設定部分 12 subject = "djangoテスト用問い合わせ" 13 message = "お問い合わせ内容\n 名前: {} \n メールアドレス:{} \n 内容: {}".format( 14 request.POST.get('name'), 15 request.POST.get('email'), 16 request.POST.get('content')) 17 email_from = os.environ['DEFAULT_EMAIL_FROM'] 18 email_to = [ 19 os.environ['DEFAULT_EMAIL_FROM'], 20 ] 21 22 send_mail( subject, message, email_from, email_to, fail_silently=False,) 23 messages.success(request,'お問い合わせ完了しました') 24 return render(request, 'mysite/contact.html', context) 25 26# recaptcha 認証用 27def grecaptcha_request(token): 28 from urllib import request, parse 29 import json, ssl 30 31 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) 32 33 url = "https://www.google.com/recaptcha/api/siteverify" 34 headers = { 'content-type': 'application/x-www-form-urlencoded' } 35 data = { 36 'secret': os.environ['GRECAPTCHA_SECRETKEY'], 37 'response': token, 38 } 39 data = parse.urlencode(data).encode() 40 req = request.Request( 41 url, 42 method="POST", 43 headers=headers, 44 data=data, 45 ) 46 f = request.urlopen(req, context=context) 47 response = json.loads(f.read()) 48 f.close() 49 print("response---\n",response) 50 return response['success']

認証ページのHTMNLは以下となります

html

1{% extends 'mysite/base.html' %} 2 3{% block content %} 4 5<main class="container"> 6 <div class="row"> 7 <div class="col-md-8"> 8 <h3 class="pb-4 mb-4 font-italic border-bottom"> 9 問い合わせページ 10 </h3> 11 12 <form class="row g-3" method="POST"> 13 {% csrf_token %} 14 <div class="col-12"> 15 <label class="form-label">名前</label> 16 <input type="text" class="form-control" id="id_username" name="name" placeholder="name" required> 17 </div> 18 <div class="col-12"> 19 <label class="form-label">メールアドレス</label> 20 <input type="email" class="form-control" id="id_email" name="email" placeholder="メールアドレス" required> 21 </div> 22 23 <div class="col-12"> 24 <label class="form-label">問い合わせ内容</label> 25 <textarea name="content" class="form-control" rows="4" required> </textarea> 26 </div> 27 28 {% include 'mysite/snippets/grecapcha.html' %} 29 30 <div class="col-12"> 31 <button type="submit" id="submit" class="btn btn-primary" disabled>送信</button> 32 </div> 33 </form> 34 35 </div> 36 37 {% include 'mysite/snippets/sidebar.html' %} 38 39 </div> 40</main> 41 42 43{% endblock %}

recaptchaを用いるためのmysite/snippets/grecapcha.htmlの内容は以下です

html

1 2{#google recaptcha部分処理#} 3<script src="https://www.google.com/recaptcha/api.js" async defer></script> 4<div class="g-recaptcha" 5 data-sitekey="{{ grecaptcha_sitekey }}" 6 data-callback="verifyCallback"></div> 7 8{#recaptcha チェックが入った場合のみ送信可能なようにJavaScriptで制御 #} 9<script> 10 //コールバック関数 Recaptchaで承認が入った場合、data-callback=""で指定した関数を呼び出す 11 function verifyCallback(response) { 12 console.log(response); 13 //submitのdiable属性を削除 送信可能にする 14 document.getElementById('submit').disabled = false; 15 } 16</script> 17

試したこと

下記確認しました。

  • 本番環境(GAE AppEngine)でのRecaptcha動作

動作が確認できたので、内部の環境起因だと考えてます。(上記のエラー等が無く更新処理が入ったことで確認してます)

  • 証明書関連のパッケージをインストール

次情報を参照に下記モジュールもpip installしたが変化なかったです

pip install python-certifi-win32

URL : [https://pythonmarketer.com/2021/06/10/how-to-fix-your-python-certificates-on-windows/]

  • localhostのSSL対応

ローカルホスト上ではSSLが無いため、内部のrecaptchaへの認証が失敗しているのかと推測して導入しました。
方法は下記のサイトを参照に入れています。
URL : [https://medium.com/@millienakiganda/creating-an-ssl-certificate-for-localhost-in-django-framework-45290d905b88]

  • _ssl.cから原因調査

下記サイトにある情報をもとに確認したが、原因が分からない状態です。
SSL内部で使用されている相対性識別名(RDN)というのをを作成していているみたいなコメントが付近にありますが、知識が無く何の処理か分からなかったです・・・
URL : [https://github.com/python/cpython/blob/main/Modules/_ssl.c]

使用環境

WSL2 + ubuntu20.04 LTS
python 3.8.10 + venv

mkcertについてはlinuxbrewというのを導入して、その上で作成しています。
また、pip側で使用しているrequipments.txtの部分です

requirements.txt

1asgiref==3.4.0 2astroid==2.6.2 3autopep8==1.5.7 4beautifulsoup4==4.9.3 5cachetools==4.2.2 6certifi==2021.5.30 7charset-normalizer==2.0.4 8Django==3.2.4 9django-livereload-server==0.3.2 10django-sslserver==0.22 11google-api-core==1.31.1 12google-api-python-client==2.15.0 13google-auth==1.34.0 14google-auth-httplib2==0.1.0 15googleapis-common-protos==1.53.0 16gunicorn==20.1.0 17httplib2==0.19.1 18idna==3.2 19isort==5.9.1 20lazy-object-proxy==1.6.0 21mccabe==0.6.1 22mysqlclient==2.0.3 23packaging==21.0 24protobuf==3.17.3 25pyasn1==0.4.8 26pyasn1-modules==0.2.8 27pycodestyle==2.7.0 28pylint==2.9.3 29pylint-django==2.4.4 30pylint-plugin-utils==0.6 31pyparsing==2.4.7 32python-certifi-win32==1.6 33pytz==2021.1 34PyYAML==5.4.1 35pyyml==0.0.2 36requests==2.26.0 37rsa==4.7.2 38six==1.16.0 39soupsieve==2.2.1 40sqlparse==0.4.1 41toml==0.10.2 42tornado==6.1 43uritemplate==3.0.1 44urllib3==1.26.6 45wrapt==1.12.1

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問