はじめに
備忘録です。
下記の構成でアプリケーションを作成する際にCORSを解放する必要がありました。
ExpressでJSON形式のAPI
フロントエンドでReact
CORSを解放するのはCookieを設定したいためであることが多いと思います。
ついでに載せておきます。
CORSとは?
CROSS-ORIGIN-RECOSE-SHARERING
オリジンが違う場合でもアクセスできるようにする処理です
SPAの場合
バックエンドはlocalhost:4000
フロントエンドはlocalhost:3000
といったかんじで同一オリジンではないので、Cookie関連の処理ができません。
正確にいうとPOSTリクエストでCookie関連の処理ができません。 GETはできたはず?
cors
こういった設定はheaderというところに設定を記述します。
npmには便利なパッケージがあるので使います。
import cors from "cors"
app.use(
cors({
// cookieの送受信を可能にする
credentials: true,
// 許可するドメイン登録
origin: 'url',
}),
);
// 複数ある場合の解放方法
origin: ['url1', 'url2'],
上記は下記のようなことを行っています。
// packageを使わずに手動で設定する場合
app.use(function (req, res, next) {
// アクセスを許可するオリジン(ドメイン)を登録
res.header("Access-Control-Allow-Origin", "url");
// 許可したドメインでCookie関連の処理を許可するか設定
// Access-Control-Allow-Originを*で全て許可していた場合tureにできない
res.header("Access-Control-Allow-Credentials", true);
// expressの機能で、次の処理に進ませる
next();
});
Access-Control-Allow-Originを*で全て許可していた場合tureにできない
の部分ですが、
*を利用して全ての接続を許可することができるのですが、良くないみたいです。 ネットサーフィンしている時にどこかで読みました。
ここまでがフロントエンドとのCookieの送受信を可能にするためのCORSの
設定です。
cookieの保存
express標準の機能でCookieの保存ができます
// 下記の構成になっています。
// 下記の記述があると、HTTPレスポンスヘッダに対して、Set-Cookieというものを付与します。
// クライアントはその値を見て、Cookieを自動で保存します。
// つまり、リクエストを飛ばせば、特に何をするまでもなく自動で保存されます。
res.cookie("key", "value", {option})
// 下記のエンドポイントを叩くと、`name: hogehoge`がCookieに保存されます。
app.get('/', (req, res) => {
res.cookie('name', 'hogehoge', {
sameSite: 'none',
secure: true,
maxAge: 24 * 60 * 60 * 1000,
httpOnly: true,
});
res.send('Cookie has been set');
});
オプションの解説をします
// 他のドメイン(別オリジン)からのPOSTでもCookieの送受信を許可
sameSite: 'none'
// HTTPSで暗号化された通信以外は拒絶する (HTTP接続を禁止)
// localhostの場合HTTPでも接続できる
// ブラウザによってsameSite noneでsecureがfalseの場合Cookieの処理を受け付けなくなっている
// Chromeのような主要ブラウザではそうなっているのでほぼ必須と言える
// つまり、sampeSiteを'none'にする場合必ずtrueである必要がある
secure: true,
// Cookieの有効期限
// ms秒で設定します。 下記は24Hです。
maxAge: 24 * 60 * 60 * 1000,
// JavaScriptでアクセスできなくする
// HTTPでしか接続できなくするものではないです (HTTPS接続を禁止するものではないです)
// この設定により不正なサイトにユーザーが誘導され、Cookieの値が抜き取られることを防ぎます
httpOnly: true,
いろいろ説明してきましたが、クロスオリジンでCookieをやりとりするための必須項目は下記3つです。
- CORSの設定
- sameSite: true (Cookie保存時)
- secure: true (Cookie保存時)
他は最悪なくても動きますが、セキュリティ的に本番環境では設定した方が良いです
cookieParser
リクエストからcookieを取得するためのpackage
ExpressはCokkieの保存には追加packageが不要ですが、Cookieの取得には追加のpackageが必要です。
自力でできないこともないですが、かなり面倒です
import cookieParser from "cookie-parser"
app.use(cookieParser());
app.get('/', (req, res) => {
// 下記のようのreqestからcookieの値を取得できる
const cookieValue = req.cookies.name;
res.json({ name: cookieValue })
});
フロントエンド側の話も
axiosを使う場合を例に挙げてみます
ちなみにfetchも同じで、デフォルトではCookieの送信や受信時のCookie追加の処理をしません
fetchの場合は設定値の仕方が若干変わるので調べてみてください
// デフォルトではCookieの送信や受信後の処理を行わない
// withCredentialsをtureに設定する
const getCookie = async () => {
const response = await axios.get(URL, {
withCredentials: true,
});
console.log(response.data);
};
終わりに
Expressは情報が比較的多いのですが、SPA特有の設定調べるのに時間がかかりますね・・・
Cookieは検証ツールのApplicationタブから見ることができます。
フロントエンドからAPIを叩いた際、検証ツールのNetworkタブでheader情報を確認することができます。
Cookieの追加の場合Responseの部分にSet-Cookie
があるはずです。
自分でいろいろ検証したい場合は参考にしてください