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

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

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

HTTPS(Hypertext Transfer Protocol Secure)はHypertext Transfer プロトコルとSSL/TLS プロトコルを組み合わせたものです。WebサーバとWebブラウザの間の通信を暗号化させて、通信経路上での盗聴や第三者によるなりすましを防止します。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

セキュリティー

このタグは、コンピューターシステムの安全性やデータの機密性に関連したトピックの為に使われます。

SSL

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

1258閲覧

あるページがhttps化されているかどうかをチェックする方法について

jjj001

総合スコア55

HTTPS

HTTPS(Hypertext Transfer Protocol Secure)はHypertext Transfer プロトコルとSSL/TLS プロトコルを組み合わせたものです。WebサーバとWebブラウザの間の通信を暗号化させて、通信経路上での盗聴や第三者によるなりすましを防止します。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

セキュリティー

このタグは、コンピューターシステムの安全性やデータの機密性に関連したトピックの為に使われます。

SSL

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2021/06/15 03:47

編集2021/06/16 02:20

現在、サイトのあるページがHTTPS化されているかどうかをチェックするプログラムを作成しています。
自分は一度以下のような形で試してみたのですが、ある疑問点にぶつかり他の方法を探している状況です。
input_url は入力フォームから受け取ったURLになります。

parsed_url = urlparse(input_url) # スキーム取得 access_url_scheme = parsed_url.scheme if access_url_scheme == "http": replace_scheme_url = input_url.replace("http", "https", 1) ssl_check = requests.get(replace_scheme_url) if type(ssl_check) is not dict: try: ssl_check.raise_for_status() except requests.exceptions.HTTPError: # ステータスコードが200番台以外の場合 print('ssl化されていません')

こちらのコードの問題点ですが、https://から始まるページへアクセスし返ってきたステータスコードが仮に500番台であった場合はSSL化されていないのではなく、サーバーエラーなどでサーバーが落ちてしまっているだけであり、実際はSSL化されている可能性は十分にあるという点です。
その為、あるページがSSL化されているかどうかをもう少し正確にチェックしたいと考えています。
他に方法などありましたら、ご助言頂けましたら幸いです。

追記です。
requests.getを使用せずに、以下の関数を作成し、https化されていないページに対してリクエストを送ってみた所 except ssl.SSLError:こちらの例外は捕捉されず、print("ステータスコード: ", response.status_code)こちらの行が出力され、「404」と表示されました。

def check_ssl_certification(targetURL, waitsec_from=1, waitsec_to=3): err_msg = {} headers = { "User-Agent": ( "Mozilla/5.0 (X11; Linux x86_64; rv:57.0)" "Gecko/20100101 Firefox/57.0" ) } session = requests.Session() # retries = Retry(total=1, # リトライ回数 # backoff_factor=1, # sleep時間(リトライするごとに待機時間を指定した秒数加算する) # status_forcelist=[500, 502, 503, 504],raise_on_status=False) # timeout以外でリトライするステータスコード """ Session.mount(prefix, adapter) はこのセッションで行う URL が prefix で始まる HTTP 通信に対して、 アダプター adapter を設定する関数。 prefix="https://" の場合、URL が https:// で始まるすべての通信が対象 """ # session.mount("https://", HTTPAdapter(max_retries=retries)) # session.mount("http://", HTTPAdapter(max_retries=retries)) try: # print('ok') response = session.get( url=targetURL, headers=headers, stream=True, timeout=(20.0, 30.0) ) except ssl.SSLError: print("SSL認証エラー") except requests.exceptions.ConnectTimeout: print("タイムアウトしました。") err_msg["connection_timeout"] = "ホストへの接続に失敗しました。" except requests.exceptions.ConnectionError as e: print("ホストが見つかりませんでした(https)", e) err_msg["no_host"] = "ホストが見つかりませんでした。" return response # HTTP ステータスコードが 4xx と 5xx の場合は urllib.error.HTTPError 例外が投げられる except requests.exceptions.HTTPError as e: print(e.response.status_code) # except requests.exceptions.RetryError: # print('再試行制限に到達しました') except requests.exceptions.ReadTimeout as e: print("requests.exceptions.ReadTimeoutエラー : ", e) except requests.exceptions.TooManyRedirects as e: print("エラー: ", e) else: print("ステータスコード: ", response.status_code) return response return err_msg

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

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

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

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

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

guest

回答1

0

ベストアンサー

質問文からの想像としてはHTTPS化されているかどうか
正しい証明書が設置されており、HTTPS通信が成立しているという条件のみのように思われるのでその前提での回答です。
*他に条件がある or 明確に定義していないのであれば、先に定義する必要があります。

こちらのコードの問題点ですが、https://から始まるページへアクセスし返ってきたステータスコードが仮に500番台であった場合はSSL化されていないのではなく、サーバーエラーなどでサーバーが落ちてしまっているだけであり、実際はSSL化されている可能性は十分にあるという点です。

ドキュメントを読む限り、証明書の検証を無視することを明示しない限りは証明書が正しい事を検証してから通信を開始します。(=証明書が設置されていなかったり不正な証明書の場合は例外が発生します。)

通信が開始されない場合はレスポンスコードを受け取ることも無いので、
500番が返ってくる=通信は成立しているということで、サーバ(やその前段に設置されるリバースプロキシやLB)には自体には正しい証明書が設置されていると判断出来ます。

投稿2021/06/15 04:32

tanat

総合スコア18713

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

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

jjj001

2021/06/15 10:59

ご回答ありがとうございます。 > 正しい証明書が設置されていると判断出来ます。 こちらなのですが、 以前の質問( https://teratail.com/questions/342825 )で、サーバー証明書が存在すること = サイト内の全てのページがhttps化されているという意味ではないとご回答を頂きました。 その為、実際にSSLサーバー証明書が設置されており、且つページに対して有効になっているのかどうかを判断する必要があるのではないかと思っております。
jjj001

2021/06/15 11:15

調べていたのですが、もしかすると、「https://docs.python.org/ja/3/library/ssl.html 」こちらのサイトに書いてある方法を参考に証明書が有効かどうか判定することが出来るかもしれないです!
tanat

2021/06/15 11:51

> こちらなのですが、 以前の質問( https://teratail.com/questions/342825 )で、サーバー証明書が存在すること = サイト内の全てのページがhttps化されているという意味ではないとご回答を頂きました。 その為、実際にSSLサーバー証明書が設置されており、且つページに対して有効になっているのかどうかを判断する必要があるのではないかと思っております。 その回答自体は正しいのですが、回答に対する理解が足りていないように思います。 ページに対してHTTPSでアクセスして500エラーが帰ってくるのであれば、 少なくともそのページに対して適用されている証明書は正しく設置され、ページに対して有効になっているものと判断されます。 それ以上検証する必要はありませんし、できません。 > 調べていたのですが、もしかすると、「https://docs.python.org/ja/3/library/ssl.html 」こちらのサイトに書いてある方法を参考に証明書が有効かどうか判定することが出来るかもしれないです! 多分、 requests.get()の中ではこのAPIを使って証明書が有効かどうか判定していると思いますよ。 証明書が有効な場合のみレスポンスコード500(やほかのレスポンスコード)が取得できます。
jjj001

2021/06/16 02:04

ご返信ありがとうございます。 > 証明書が有効な場合のみレスポンスコード500(やほかのレスポンスコード)が取得できます。 こちらなのですが、一度検証を行うために、関数を作成し、https化されていないページに対して、リクエストを行なってみました。 しかし、ステータスコード「404」が返却されてしまいました。 こちらにつきましては、質問本文に追記致しました為、お手数ですが一度チェックの程頂けましたら幸いです。 よろしくお願いします
tanat

2021/06/16 02:22 編集

>> 証明書が有効な場合のみレスポンスコード500(やほかのレスポンスコード)が取得できます。 >こちらなのですが、一度検証を行うために、関数を作成し、https化されていないページに対して、リクエストを行なってみました。 うーん、今一つ何を検証しようとされているのか分からないです。 https化されていないと分かっているところ(http://で始まるURL?)にリクエストを送って404が返ってくることで何が検証されたと思われていますか? 恐らく、 - HTTP通信の基本的な流れ - (強制HTTPS化の際の)HTTP→HTTPSのリダイレクトの際の挙動 - サーバサイドでエラーが発生した場合とHTTPレスポンスコードの関係 - サーバに設置されている証明書とページのHTTPS化の関係 と言った基本的な通信の流れに対する理解の不足から、実際に発生するであろう現象についての正確な認識が出来ていない様に思われます (一度ご自身で証明書の取得とHTTPS通信の出来るサーバを立ち上げてみると理解が進みやすいです。) 基本的な理解が曖昧なままでは検証は進まないので、まずは > その為、あるページがSSL化されているかどうかをもう少し正確にチェックしたいと考えています。 について「正確にチェック」とは何を指しているのかを整理して考えているパターンをリストアップしてみて下さい。
jjj001

2021/06/16 02:26

> https化されていないと分かっているところ(http://で始まるURL?)にリクエストを送って404が返ってくることで何が検証されたと思われていますか? こちらなのですが、自分と致しましては、https化されていなかった場合、「 except ssl.SSLError 」こちらが捕捉されるはずであると考えています。 その為、「 print("ステータスコード: ", response.status_code) 」こちらが出力された原因がいまいち分からないといった状況です...
dodox86

2021/06/16 02:26

質問者さんはもしかすると、"アクセスしたページそのもの"にSSLの証明がかかっていると思っているのではないでしょうか。そうではなく、サーバー間のhttp(s)の通信全体にかかっています。404のエラーは「要求したページはありません」と言うエラーなので、SSLでのサーバー間通信はOKであるけれども、要求したページのhtmlファイル/リソースが無いというhttpサーバーが返す別のレイヤーのエラーです。そのページからまた別のサイトへのリンクがあったりしたら、それはまた別の話になります。
jjj001

2021/06/16 02:34

> 質問者さんはもしかすると、"アクセスしたページそのもの"にSSLの証明がかかっていると思っているのではないでしょうか。そうではなく、サーバー間のhttp(s)の通信全体にかかっています こちら、少々混乱してしまっているのですが、そうなりますと、「 except ssl.SSLError 」こちらの例外はどのような場合に捕捉されることになるのでしょうか...?
tanat

2021/06/16 02:44 編集

> jjj001さん http://で始まっているURLに対して通信を行った場合は、 証明書の検証自体が必要無いので証明書に関するエラーは発生しません。 先のコメントの > 「正確にチェック」とは何を指しているのかを整理して考えているパターンをリストアップしてみて下さい。 をお願いします。 恐らく、技術的に正確な「あるページがhttps化されているか」とjjj001さんの「あるページがhttps化されているか」には定義に違いがあります。
dodox86

2021/06/16 02:48

>質問者@jjj001さん > except ssl.SSLError 」こちらの例外はどのような場合に捕捉されることになるのでしょうか...? HTTPサーバー自身がそのURLのページにアクセス(そのページのファイルなどのリソースをHTTPサーバー上から読み取る)しようとする以前にサーバーとクライアントが証明書を用いて検証し、SSLでの通信を確立しようとしますが、それがNGだった場合のはずです。(証明書が有効期限切れであったり不正であったり) HTTPSでの通信がどのようにされるかを最初に理解されると良いと思います。 [第2回 HTTPSの詳細 - @IT] https://www.atmarkit.co.jp/ait/articles/1704/13/news030.html コメントの流れを阻害させてしまってすみません。>tanatさん
tanat

2021/06/16 02:50

> dodox86さん > コメントの流れを阻害させてしまってすみません。>tanatさん 補足いただきありがとうございます!
jjj001

2021/06/16 04:26

少々、自分のHTTPS通信に関して理解が足りていない部分があったようですね。 申し訳ないです... > 「正確にチェック」とは何を指しているのかを整理して考えているパターンをリストアップしてみて下さい。 こちら、今一度整理してみたのですが、実装したい部分としましては、該当のページに対して、SSLサーバー証明書が発行されていて、且それが有効となっているかどうか、といった点です。 こちらの箇所の実装を行いたいと考えています。
tanat

2021/06/16 04:32

> こちら、今一度整理してみたのですが、実装したい部分としましては、該当のページに対して、SSLサーバー証明書が発行されていて、且それが有効となっているかどうか、といった点です この定義だけだと、 - https://でアクセスして何らかのレスポンスコードが取得出来れば真 となり、それだけ検証すれば問題無いです。 一方で、追加の検証では http://でアクセスした場合 について検証されている様に見えるので 例えば「http://でアクセスした場合にエラーになる事」を期待していたりしませんか? その場合は想定されている定義が曖昧なので、先に定義を明確にしないと答えは出ません。 「http://でアクセスした場合にエラーになる事」などの想定している具体例をリストアップしてみてください。
jjj001

2021/06/16 05:34 編集

tanatさんに頂きました以下のご返信の箇所を読み返している内に、自分ちょっとかなり勘違いしてしまっていることに、ようやく気付きました... 「 http://で始まっているURLに対して通信を行った場合は、証明書の検証自体が必要無いので証明書に関するエラーは発生しません。」 ただ、プログラム上の問題なのかもしれないのですが、レンタルサーバーへデプロイしてありますサイト(SSL化していない)のURLを「https://」で始まる形にし「check_ssl_certification」関数へかけてみたのですが、レスポンスコードが「 404 」として返ってきてしまいました。 実際の所、例外が捕捉されるはずだと予測しておりました為、こちらの原因は分からない状況です... >「http://でアクセスした場合にエラーになる事」などの想定している具体例をリストアップしてみてください。 こちらですが、今回はhttpで入力されたURLはhttpsへ変換し直し、「check_ssl_certification」関数へかけようと思っている為、「http://」の形ではリクエストを行わない仕様でいこうかと考えております
tanat

2021/06/16 05:39

> ただ、プログラム上の問題なのかもしれないのですが、レンタルサーバーへデプロイしてありますサイト(SSL化していない)のURLを「https://」で始まる形にし「check_ssl_certification」関数へかけてみたのですが、レスポンスコードが「 404 」として返ってきてしまいました。 なるほど。検証しようとしている事が理解できました。 - requests.getで同じように確認した場合 - ブラウザで同じようにアクセスした場合 はそれぞれどうなりますか?
jjj001

2021/06/16 06:28 編集

度々すみません。 > - requests.getで同じように確認した場合 requests.getで試した際は、「requests.exceptions.SSLError:」が発生致しました。 > - ブラウザで同じようにアクセスした場合 Chrome及びfirefoxでアクセスしてみましたら、「この接続ではプライバシーが保護されません」といった警告画面が表示されました。 こちら、 requests.getで試した際と、自分で作成した関数で結果が違っていた為、再度check_ssl_certificate関数で試してみましたら、同様のエラーが出力されました。 自作関数の方では、色々とプログラムをいじっておりました為、余計なコードが入ってしまっていたことが原因でした... 今回、単純に自分が実装するために必要だった事は、複雑なコードという訳ではなく、きちんとしたSSLの理解であったと認識致しました。 何度もご丁寧に教えて頂いたtanatさんには本当に感謝です。 ありがとうございました。 dodox86さんもSSLに関するご助言、ありがとうございました。 一度貼って頂きました記事きちんと読ませて頂きたいと思います
tanat

2021/06/16 06:27

解決して良かったです。 フィードバックありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問