はじめに
SeleniumでBASIC認証のついたページにアクセスする場合、
https://username:password@example.com
のように、認証情報を埋め込んだURLを使います。
さて、この方式はそもそもセキュリティ的によろしくないので、最近のブラウザでは実施することができません。
BASIC認証がかかったWebサイトがお手元にある方は、試しに上記のように認証情報を埋め込んだURLをChromeのアドレスバーに入力してみてください。
URLに埋め込まれた認証情報は無視され、認証情報入力ダイアログが表示されると思います。
一次文献が見当たらないのでご存じの方は教えていただきたいのですが、どうやらSelenium (WebDriver?) を用いた場合のみ、認証情報を埋め込んだURLは許可されているようです。
ハマったポイント
SPAで構築されたアプリケーションで、特定のページがレンダリングされない問題が起きました。
DevToolを見ても特にエラーなどは出ていませんでした。
リロードしても問題は解決しませんでしたが、
なぜか アドレスバーにフォーカスしてEnterを押下する (つまり、該当のURLに再度アクセスする)と改善しました。
Seleniumからは認証情報を埋め込んだURLhttps://username:password@example.com
でアクセスしていましたが、アドレスバーには認証情報なしのURL https://example.com
が表示されていました。
何が起きていたか
Seleniumで、認証情報を埋め込んだURLを用いると、アドレスバーでは認証情報が省略された状態で表示されますが、内部的には認証情報付きのURLとして扱われます。
このとき、何が問題になるかと言うと、 Fetch API が動作しません。
Request cannot be constructed from a URL that includes credentials
認証情報付きのURLでFetchは使えない、ということですね。
XHRとかだと案外上手く行ったりするのかもしれませんが、めんどくさいので試してません。
そんなわけで、リソースのロードにFetchを利用している場合、そもそもレンダリングが出来ないみたいな状態に陥ります。
どこで握りつぶされていたか、エラーも出ていないし、アドレスバーでは普通のURLにしか見えないし、原因にたどり着くまでリアルに3ヶ月ぐらいかかりました。
どうしたか
もうしょうがないので、 認証情報付きのURLにアクセスしてブラウザにキャッシュさせたあと、認証情報無しのURLで再アクセスする というどうしようもない力技で解決しました。
browser.url('https://username:password@example.com')
browser.url('https://example.com')
Selenium4ではBASIC認証周りの動作が改善されると風のうわさで耳にしたので、それまではパワープレイでごまかしましょう。
補足
もう一つ、BASIC認証周りでハマった点としてこんなんがありました。
-
https://username:password@example.com
にアクセス - Webサーバ(nginx)で
https://example.com
にリダイレクト - 認証情報はキャッシュされてないので認証ウィンドウが出る
- 死
こちらはマジでSelenium側ではどうにもならず、 リダイレクトされないURLを用意して、そこにアクセスしてブラウザにキャッシュさせる というこれまたパワープレイで結着しました。
力こそパワー!