Laravel Sanctumサーバとローカル開発環境でAjax通信(CORS)したい
やりたいこと
Laravel Sanctumで構築したクラウドサーバと、ローカル開発しているwebページを通信したい。
サーバは、HTTPS × Basic認証で、ローカルはHTTP。
想定している環境
サーバ(PHP)環境
- Apache
- Laravel Sanctum
- Basic認証あり
- EC2 -> Cloud Front
- HTTPS環境
ローカル環境
- HTTP環境
- axios使用
手順
通信するために2種類の設定が必要
- CORS(別ドメイン) + Basic認証 + Ajax(axios)の通信
- Laravel SanctumでCORS通信を許可
CORS(別ドメイン) + Basic認証 + Ajax(axios)の通信設定
Basic認証をつけたサーバでHTMLを開いた場合は、Basic認証のダイアログが表示されるが、
別ドメイン(CORS)からアクセスすると、CORS × Basic認証の部分ではまることがあるようだ。
詳しい解説は↓にあるように2つの許可が同時にとれない問題が発生する
解決方法も記事に書かれているので、そのように変更する。
# アクセスを許可するURLを指定
Header set Access-Control-Allow-Origin "https://example.hoge.com"
# 許可するリクエストヘッダのメソッドを指定
Header set Access-Control-Allow-Methods "POST, GET, OPTIONS"
# 許可するリクエストヘッダの種類を指定
Header set Access-Control-Allow-Headers "Content-Type, origin, authorization"
# プリフライトレスポンスをキャッシュする時間を指定
Header set Access-Control-Max-Age "600"
# OPTIONSに対する反応
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
<LimitExcept OPTIONS>
AuthType Basic
AuthUserFile /hoge/.htpasswd
AuthName "ID and password"
Require valid-user
</LimitExcept>
今回の環境では、CORSの許可はCDN(CloudFront)で出せるので、Basic認証でOPTIONを除外のみを行った。
<LimitExcept OPTIONS>
AuthType Basic
AuthUserFile /hoge/.htpasswd
AuthName "ID and password"
Require valid-user
</LimitExcept>
CloudFrontで、CORS設定はこちらを参考にした
Laravel SanctumでCORS通信を許可
基本的にドキュメントに従って進める。
まず、credentials
を有効化
// 中略
'supports_credentials' => true
次に、 .env
を下の例のように設定を追加する
SANCTUM_STATEFUL_DOMAINS=http://localhost:3000,http://127.0.0.1:3000,http://localhost#開発環境を指定する。SANCTUM認証除外対象
SESSION_DOMAIN=.hoge.com#サーバのドメイン。"."から書くとサブドメインも対象にする
SESSION_SECURE_COOKIE=false#開発がHTTP環境なので指定する
(略)
SANCTUM_STATEFUL_DOMAINS
項目はドキュメントではドメインのみ記載している。
しかし、http
から書かないとサーバが https
ローカルが http
だとうまくいかないのに注意。
サーバ側の設定はこれで終わりです。
Webで通信を設定
axiosライブラリで、Ajaxを設定する。
web側で、CORS通信のために withCredentials
を有効化する。
また、sanctumのAPIにアクセスする前に /sanctum/csrf-cookie
でcookieを取得する必要があります。
コードの例は下のようになると思います。
axios.defaults.withCredentials = true// CORSするためにCredentialsを有効化
axios.defaults.baseURL = 'https://hoge.com'// サーバのドメインを設定
/** SanctumのAPIにアクセスする前にこちらのAPIを踏む必要がある */
const apiStartUp = async ()=>{ return axios.get('/sanctum/csrf-cookie', {
auth: {// 送信するbasic認証
username:'hoge',
password:'fuga'
}})
};
apiStartUp().then(()=>{
//通信成功を待って、他の通信を行う
await axios.get('/api/hoge')// <-本命の通信
});
終わり
どの問題もそれなりに情報があるが、微妙に領域が重なるところで問題が起こり調べるのに時間がかかった。
まとめた、ドキュメントをここに記載しておきます。
誰かの役に立つと幸いです。
Discussion