LoginSignup
6
0

私を苦しめる CORS

Last updated at Posted at 2023-12-13

私が LT の資料を作るとき経験したことです。
大学生のときから経験したことですが、最近思い出して、この error について作成しました。


CORS(cross origin resource sharing)

Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate any origins (domain, scheme, or port) other than its own from which a browser should permit loading resources. CORS also relies on a mechanism by which browsers make a "preflight" request to the server hosting the cross-origin resource, in order to check that the server will permit the actual request. In that preflight, the browser sends headers that indicate the HTTP method and headers that will be used in the actual request.

CORS は application が origin ではない(domain, port, scheme)ほかの origin の resource にアクセスする権限を与えるブラウザに指示するための機能です。

保安のため(ブラウザは CORS の HTTP 要請を制限)同じ origin の resource だけ使えます。

また、実際ブラウザは API 要請によって、CORS 要請を違うように適用します。(simple request をするか preflight request をするかします)

simple request

  • GET, HEAD, POST の method を使う必要があります.
  • 特別なヘッダーを使わず, Content-Typeが次のことの中一つを選ぶ必要があります。: application/x-www-form-urlencoded, multipart/form-data, text/plain.
  • 追加的な保安の仕業のために preflight が必要ではありません

これらの以外には全部 preflight request です。

基本的な preflight request はブラウザから自動的に行われるので frontend エンジニアが直接に設定する必要はありません。

なぜ行われる?

保安のためです。

It helps isolate potentially malicious documents, reducing possible attack vectors.

このような policy がなければ、web application user は簡単に情報(個人情報、パスワードなど)を取られるかもしれません。
そのために web server は API 要請を受けられる host を制限するべきです。

いつ行われる?

基本的に origin(domain, port, scheme)が違う、ほかの origin に resource 要請するときです。
ここで大事なことは単純に domain だけでなく port や scheme も含まれていることです。
それで、CORS 設定がなければ、ときどき local, docker の container をつかって、localhost を使っていても、SOR を違反する可能性があります。

だから解決方法は?

CORS にこの url や port などなど…は安全だとお知らせば、OKです。

  1. 既存のコード
// frontend の fetch 部分
fetch('http://moroboshi-backend.com/hello/world').then(((res) => {...})
// express
// backend
const express = require('express');

const app = express();

app.get('/hello/world', (req, res) => {
  res.send('hello!');
});

app.listen(3000, () => {
  console.log('ハッピーハッピー');
});

たぶん、このままではできると思いますが、例なので、もし、ここに CORS error があったと仮定します。
browser の deveoloper tool から、CORS error が確認できるんでしょうね。

  1. 設定したコード
// frontend の fetch 部分
fetch('http://moroboshi-backend.com/hello/world', {
  method: 'GET', // POST...etc
  headers: {
    // frontend の url を使います。
    'Origin': 'http://moroboshi-frontend.com/hello/world'
    // このデータの形です
    'Content-Type': 'application/json',
  }
}).then(((res) => {...})

既存のコードは fetch に params を一つだけ渡しましたが、実際は option も渡すことができます。
後ろの部分に設定できます。

バックエンドは library が必要です

# backend の server file と同じ場所から library を設置しましょう
$ npm install cors
# yarn add cors
// express
// backend
const express = require('express');
const cors = require('cors');

const app = express();

// origin(domain), header, methods などなど設定できます。
// もし、option がなければ、すべてのことを許可します。
const corsOption = {
  origin: 'http://moroboshi-frontend.com/hello/world' // プロントエンド domain
  methods: ['GET', 'POST', 'PUT', 'DELETE'], // 許可 method
  allowedHeaders: ['Content-Type', 'Authorization'] // 許可 header
}
app.use(cors());

app.get('/hello/world', (req, res) => {
  res.send('hello!');
});

app.listen(3000, () => {
  console.log('ハッピーハッピー');
});

このように設定したら、たぶん、CORS error がなくなります。


まとめ

大学生のときは知らないことだったので、どたばたしましたが、最近練習したら、なんでもありませんね。
簡単に解決できる error なんですけど、ちゃんと設定していないと、保安に問題があったり、適切に resource 共有ができません。


参考した web page
https://developer.mozilla.org/en-US/docs/Glossary/HTTP_header

6
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
0