CORS

10492 ワード

Web開発を行う過程で、少なくとも1回はこのエラーを経験し、このエラーで頭が痛くなる可能性が高い...私も!だからもっと勉強したいです.

CORSって何なんだ!これらの間違いを知る前に、CORSが必要な背景SOPを調べておきましょう.

SOP


SOPはSame-Origin Policyの略で、同じソースポリシーを意味します.
MDNでは、次のように定義されます.
同じソースポリシー(ison-originpolicy)は、あるソースからロードされたドキュメントまたはスクリプトが別のソースからインポートされたリソースと相互作用することを制限する重要なセキュリティ方法です.
要するに「同じソースのリソースしか共有できない」というポリシーです.ここでいう「出所」は以下の通りです.

ソースは、プロトコル、ホスト、ポートの組み合わせです.どちらかが異なると、同じソースとは思えません.例を挙げて、理解してみましょう.
  • https://velog.io/@ye-ji vs http://velog.io/@ye-ji->2つのURLは、プロトコルが異なるため、同じソースではありません.( https vs http )
  • https://velog.io/@ye-ji vs https://velog.io->2つのURLは、ホストが異なるため、同じソースではありません.( velog.io/@ye-ji vs velog.io )
  • http://velog.io/@ye-ji:81 vs http://velog.io/@ye-ji
  • httpプロトコルの基本ポートは80です.
    従って、http://velog.io/@ye-jihttp://velog.io/@ye-ji:80と同様である.
    =>ポートが異なるため、2つのURLは同じソースではありません.(:81 vs :80)
  • https://velog.io/@ye-ji:443 vs https://velog.io/@ye-ji
  • httpsプロトコルの基本ポートは443です.従って、https://velog.io/@ye-jihttps://velog.io/@ye-ji:443と同様である.
    =>両方のURLのプロトコル、ホスト、ポートは同じソースです.
  • では、なぜSOPが登場するのでしょうか.MDN定義を見てみると、次のように見えます.
    同じソースポリシーは、有害なドキュメントを分離することによって、攻撃を受ける可能性のあるルートを減らします.
    攻撃されるルートを減らせ…!つまり、SOPによってハッカーなどの脅威の中でより安全になるということです.原因を知るために、同じソースポリシーがないと仮定します!
    NAVERのようなWebページにログインしたら、サービスを利用してみましょう.サービスを使用していない場合でも、ログアウトや自動ログイン機能を忘れたため、ブラウザにログイン情報が保持されている可能性があります.
    この状態で別のコードのあるサイトにアクセスして、私たちのログイン情報を表示しますか?ハッカーは私たちのログイン情報を利用して、NAVERで利用できるすべての機能を利用することができます.私が知らないうちに、私のアカウントでブログやカフェで悪い文章を発表したり、数千人に迷惑メールを送ったりすることもできます.
    SOPがあったらどうなりますか?SOPは当初,他サイトとのリソース共有を制限していたため,登録情報が他サイトのコードから漏れることを根本的に防止できる.これらのセキュリティ上の利点から、SOPはすべてのブラウザでデフォルトで使用されるポリシーです.
    しかし、他のソースのリソースを使うことが多すぎます.クライアントとサーバをローカル環境ですぐに開発すると、ソースが異なります.開発中のサイトでNAVERマップapiをご利用になりたい場合は?github情報を取得して使用したい場合は?異なるソースのリソースを使用します!!
    しかし、すべてのブラウザがSOPポリシーを使用しているため、他のソースからリソースを取得するにはどうすればいいですか?

    CORS


    上記の場合、必要なのがCORSです.
    MDNはCORSを以下のように定義する.
    クロスソースリソース共有(Cross-Origin Resource Sharing,CORS)は、追加のHTTPヘッダを使用して、1つのソースで実行されるWebアプリケーションでブラウザに他のソースの選択されたリソースにアクセスする権限を付与するメカニズムです.
    つまり、ブラウザは基本的にSOPによって他のソースからのリソース共有を阻止されていますが、CORSを使用してアクセス権を得ることができます!
    最初に見た間違いをもう一度見てみましょう.
    다른 출처의 리소스를 가져오려고 했지만 SOP 때문에 접근이 불가능합니다.
    CORS 설정을 통해 서버의 응답 헤더에 ‘Access-Control-Allow-Origin’을 작성하면 접근 권한을 얻을 수 있습니다...
    つまり、このエラーが発生したのはCORSではなく、SOPのためだ.CORSはかえってこの間違いを解決する案だ!
    では、CORSがどのようにして、どのように設定されているかを見てみましょう.

    CORS操作方式


    CORSの動き方は大きく3つあります.

    1.飛行前の要請


    実際の要求を送信する前に、OPTIONSメソッドにプリリクエストを送信し、プリフェッチ要求と呼ばれるソースリソースへのアクセス権があることを確認します.

    上の図に示すように、ブラウザは、実際の要求をサーバに送信する前にジャンプ要求を送信し、ヘッダのAllow-Control-Allow-Origin値に応答して要求のソースを返すと、実際の要求が送信される.

    要求されたソースにアクセス権がない場合、応答ヘッダにはまったくありませんAllow-Control-Allow-Originこの場合、ブラウザはCORSエラーをトリガーし、実際のリクエストは転送されません.

    なぜ自由飛行の招待が必要なのですか?

  • 実際のリクエストを送信する前に事前に権限確認を行うことができるため、実際のリクエストは最初からリクエスト全体を送信するよりもリソース面で有効である.
  • CORSは、準備ができていないサーバを保護します.CORS以前に作成されたサーバはSOPリクエストの場合のみを考慮している.そのため、他のソースからのリクエストには準備ができていません.

    これらのサーバに直ちに要求を送信すると、応答を送信する前に要求が最初に処理されます.ブラウザは、応答を受信すると「CORS」権限がないことに気づきますが、ブラウザにエラーが発生すると、リクエストは実行済みになります.リクエストがDELETEまたはPUTのようにサーバ上の情報を削除または変更した場合?考えているだけでめまいがする.
  • しかし,CORSを用意していないサーバであっても,先にスキップ要求を出すと,スキップ要求でCORSエラーが発生する.例に示すように、実行すべきでないCross-Origin要求の実行を防止することができる.そのため、飛灯リクエストは基本仕様に入りました!

    2.単純な要求


    単純なリクエストとは、いくつかの条件を満たす場合に、フリーフライトリクエストをスキップしてリクエストを送信することです.

    条件は以下の通りしかし、これらの条件を満たすのは難しいので、まず参考にするしかありません.
  • GETHEADPOSTお願いの一つ
  • 自動設定のヘッダを除き、手動でAcceptAccept-LanguageContent-LanguageContent-Typeヘッダの値しか設定できません.
    *Content-Typeヘッダ許容値のみapplication/x-www-form-urlencodedmultipart/form-datatext/plain
  • 3.認証情報を含む要求


    これは、要求ヘッダに認証情報を含む要求である.ソースが異なる場合、他の設定をしないとCookieを送信できません.これは敏感な情報だから!この場合、フロント、サーバ双方にCORSを設定する必要があります.
  • フロントはリクエストヘッダに入れるべきwithCredentials : true
  • サーバ側は応答ヘッダに入れるAccess-Control-Allow-Credentials : true
  • サーバー側・設定Access-Control-Allow-Originの場合、すべてのソースが許可されていることを示すワイルドカード(*)に設定するとエラーが発生します.認証情報が含まれている以上、出典を正しく設定する必要があります.
  • CORSの設定方法


    では、CORSの設定方法を簡単に説明しましょう.

    1. Node.jsサーバ


    node.jsを使用して簡単なhttpサーバを作成する場合は、応答ヘッダを次のように設定できます.
    app.use((req, res, next) => {
    // 모든 도메인
      res.header("Access-Control-Allow-Origin", "*"); 
    
    // 특정 도메인
      res.header("Access-Control-Allow-Origin", "https://codestates.com"); 
    
    //인증 정보를 포함한 요청을 받을 경우
    	res.header("Access-Control-Allow-Credentials",  true);
    });

    2.Expressサーバ


    Expressフレームワークを使用してサーバを作成する場合は、Corsミドルウェアを使用してCORSをより簡単に設定できます.
    const cors = require("cors");
    const app = express();
    
    //모든 도메인
    app.use(cors());
    
    //특정 도메인
    const options = {
      origin: "https://codestates.com", // 접근 권한을 부여하는 도메인
      credentials: true, // 응답 헤더에 Access-Control-Allow-Credentials 추가
      optionsSuccessStatus: 200, // 응답 상태 200으로 설정
    };
    
    app.use(cors(options));
    
    //특정 요청
    app.get("/example/:id", cors(), function (req, res, next) {
      res.json({ msg: "example" });
    });
    それ以外にも、様々な開発環境では、ヘッダーの値をどのように設定するかを知っていれば、CORSを設定することができます!