質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

13461閲覧

axiosを用いたajax通信を行ったらcorsエラーが発生してしまった

study_111

総合スコア82

Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/07/18 02:22

編集2020/07/18 04:17

前提・実現したいこと

axiosを用いて、ajax通信を行いたいです。

発生している問題・エラーメッセージ

デベロッパーツールのコンソールに以下のようなエラーが発生してしまいました。

Access to XMLHttpRequest at 'http://127.0.0.1:8000/polls/check/' from origin 'http://localhost:8080' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.

該当のソースコード

App.Vue

<template> <div id="app"> <h3>掲示板に投稿する</h3> <label for="name">ニックネーム:</label> <input id="name" type="text" v-model="name"> <br> <label for="comment">コメント:</label> <textarea id="comment" v-model="comment"></textarea> <br> <button @click="createComment">コメントをサーバーに送る</button> <h2>掲示板</h2> </div> </template> <script> import axios from 'axios'; export default { data(){ return{ name:'', comment:'', }; }, methods: { createComment(){ axios.post( 'http://127.0.0.1:8000/polls/check/', { name:this.name, comment:this.comment }, { headers: { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET, POST, PATCH, PUT, DELETE, OPTIONS", "Access-Control-Allow-Headers": "Origin, Content-Type, X-Auth-Token" } }, ) .then(response => { console.log(response); }) .catch(error => { console.log(error); }) console.log('hello') this.name = ''; this.comment = ''; } }, } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>

Vies.py

def check(request): if request.method == "GET": print('ok') return redirect("polls:index") json_dict = json.loads(request.body) print(json_dict) json_str = json.dumps(json_dict, ensure_ascii=False, indent=2) return HttpResponse(json_str)

試したこと

Django側では、こちらこちらのサイトを参考に、pip install django-cors-headersを行いsettings.pyを以下の部分を追記しました。

INSTALLED_APPS = [ 'corsheaders', ] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', ] CORS_ORIGIN_WHITELIST = ( 'http://localhost:8080', 'http://127.0.0.1:8080', 'http://127.0.0.1:8000', ) CORS_ALLOW_CREDENTIALS = True CORS_ALLOW_CREDENTIALS = True

また、App.vueファイルの以下hedder部分を削除した状態で、postするとPOST http://127.0.0.1:8000/polls/check/ 403 (Forbidden)とエラーが発生してしまっている状況です。

{ headers: { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET, POST, PATCH, PUT, DELETE, OPTIONS", "Access-Control-Allow-Headers": "Origin, Content-Type, X-Auth-Token" } },

補足情報(FW/ツールのバージョンなど)

エディター:VScode,OS:Mac OS

どなたか、エラー解決の為、アドバイス頂けましたら幸いです。

追記

Qiita記事を参考に、axiosにwithCredentials: trueを追記しましたがPOST http://127.0.0.1:8000/polls/check/ 403 (Forbidden)が表示されている状態です。

axios.post( 'http://127.0.0.1:8000/polls/check/', { name:this.name, comment:this.comment }, { withCredentials: true }, )

追記2

こちらの記事を参考に以下の部分をApp.vueに追記しましたが、エラーは解決されていない状況です。

import axios from 'axios'; const headers = {"X-CSRFTOKEN": "<csrf_token_very_long_string_goes_here>"}

axios.postメソッドには、 {headers: headers},を引数に追加しました

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/07/18 02:53 編集

エラーメッセージが Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response. と言ってますけど、そのあたりは調べましたか?
退会済みユーザー

退会済みユーザー

2020/07/18 04:22

普通にユーザーがブラウザを使ってアクセスするケースで、プリフライトリクエスト(エラーメッセージからそうであろうと想像)になる場合は、以下の記事の画像(Fiddler によるキャプチャ画像)の左下のウィンドウに示すように HTTP 動詞が OPTION になって、赤枠で囲ったヘッダが送信されるはずです。 http://surferonwww.info/BlogEngine/post/2016/12/27/wcf-service-in-cross-domain.aspx それを受けて、画像の右下のウィンドウの赤枠で囲ったようなヘッダが返ってくるはずです。 エラーメッセージの "Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response." と話が合わないのが解せませんが、質問者さんの方でも Fiddler を使って要求・応答ヘッダーがどうなっているか調べてはいかがですか。 axios とか全く知らないので、もし的外れのレスでしたらすみません。
guest

回答2

0

ベストアンサー

追記:Vue 公式ドキュメントによって、フロントエンドとバックエンドのサーバーが同一ではない場合、設定の devServer.proxy にバックエンドサーバーのアドレスを入れれば、フロントエンドで知らないリクエストを全部バックエンドに渡せます。

javascript

1// vue.config.js 2module.exports = { 3 devServer: { 4 proxy: 'http://localhost:8000' 5 } 6}

そうしたら、リクエストの際にアドレスを明言する必要がなくなります。

javascript

1 axios.post( 2 '/polls/check/', 3 { 4 name:this.name, 5 comment:this.comment 6 }, 7 )

追記:そうしてもCSRFを踏んだら、Django側その関数に @csrf_exempt でマークしてください

python

1@csrf_exempt 2def check(): 3 pass

AkitoshiManabeさんの言う通り、http://127.0.0.1:8080http://localhost:8080との違いで Cross Origin エラーが出てます。

こちらのコードから推測できる誤解を解けておきましょう:

javascript

1 axios.post( 2 'http://127.0.0.1:8000/polls/check/', 3 { 4 name:this.name, 5 comment:this.comment 6 }, 7 { 8 headers: { 9 "Access-Control-Allow-Origin": "*", 10 "Access-Control-Allow-Methods": "GET, POST, PATCH, PUT, DELETE, OPTIONS", 11 "Access-Control-Allow-Headers": "Origin, Content-Type, X-Auth-Token" 12 } 13 }, 14 )

上記の axios の headers はクライアントからサーバーへのリクエストの headers です。例えば、Cookie や Accept など、クライアントができることを示すためです。

Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers、この三つの headers はサーバーができることですから、サーバーからクライアントへのレスポンスについてるものです。この三つの headers は axios の headers に入れても意味がありません。削除していいです。

python

1CORS_ORIGIN_WHITELIST = ( 2 'http://localhost:8080', 3 'http://127.0.0.1:8080', 4 'http://127.0.0.1:8000', 5)

上記の設定をしたら、上記の headers は Django からのレスポンスに CorsMiddleware によって自動的についてるはずですが、カッコを使ってしまい list ではなく tuple を使っていますので、どんな反応してるかわかりません。カッコ () をブラケット [] で書き換えてみたらいかがでしょうか?

投稿2020/07/21 10:37

編集2020/07/23 09:41
YufanLou

総合スコア463

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

study_111

2020/07/21 16:09 編集

ご回答ありがとうございます。 headersについてなど、基礎的な部分が分かっておりませんでした為、大変勉強になります。 javascriptファイルの「headers」の部分を削除し、「CORS_ORIGIN_WHITELIST 」の部分をカッコではなくブラケットに修正してみましたが、「POST http://127.0.0.1:8000/polls/check/ 403 (Forbidden)」 となってしまいました。 こちら少々調べてみたのですが、「CSRF」トークンの付加が必要になってくるということなのでしょうか?
study_111

2020/07/22 01:01 編集

ご返信ありがとうございます。 実は、ご回答頂きました「index でレスポンスする html のテンプレートに {% csrf_token %} を置いてから 」こちらの部分なのですが、現状VueCliにてプロジェクトを作成し、「npm run server」を実行し、「http://localhost:8080/」にアクセスしましたら「App.Vue」の内容が表示されているといった状況です。 その為、Djangoテンプレートは使用しておらず、App.Vueから直接Django側にaxiosからリクエスト通信を行なっているといった状況です。 分かりにくいご質問で、申し訳ないです。
study_111

2020/07/22 02:15 編集

ご尽力頂きまして、誠にありがとうございます。 ブログ記事の方、読ませて頂いたのですが、英語で記載されておりました為、google翻訳にかけてみたのですが、自分がVue.jsの経験が浅いのもあり、いまいち分らない部分が多くございました。 もし、お願い出来ましたら、お時間のございます際に、追加で記述するコードなどの詳細を、ご教示頂けましたら幸いです。
study_111

2020/07/23 02:34 編集

ご追記ありがとうございます。 「vue.config.js」を「src」フォルダがある場所と同じ階層に作成し、ご回答頂きました通り記述致しました。そして、「axios.post」を指定している場所に、「'/polls/check/',」を指定し、再度リクエストを行いましたが、「500 Internal Server Error」となりました。こちら恐らく、Vue.jsの方で立ち上げているサーバーが「http://localhost:8080/ 」であり、Djangoの開発サーバーが、 「http://127.0.0.1:8000/」であるからだと推測されます。 その為、「axios.post」で指定した部分を「http://127.0.0.1:8000/polls/check/」に書き換え再度リクエストを行いました。しかし、Django側のターミナルでは「Forbidden (CSRF cookie not set.): /polls/check/」と表示され、エラーコードが返ってきてしまっている状況でございます。こちら自分でもどうにか解決方法がないか、調べてみたいと思います。
YufanLou

2020/07/23 07:36

すみません、追記の中のポートに4000で書いてしまいましたので、Djangoサーバーのアドレスではないため500エラー出ましたでしょう。ポートを8000で試してみましょう。
study_111

2020/07/23 08:42 編集

ご修正頂きまして、ありがとうございます。 vue.config.jsを修正し再度Django側へリクエストを送りましたが、「Forbidden (CSRF token missing or incorrect.): /polls/check/」とDjango側で表示されてしまい、修正前と同様にエラーが出力されてしまっている状況でございます。
study_111

2020/07/23 09:52

ご追記ありがとうございます。 「 @csrf_exempt 」をつけたことで、csrfによるエラーが解消されました。 長々とご親切に教えて頂きまして、ありがとうございました。
YufanLou

2020/07/23 10:16

僕も経験浅くて、色々勉強になりました。これはあくまで開発ための一時的なもので、デプロイの際には色々修正しなければなりません。他に webpack を使ってまともに Django から Vue フロントエンドを表示してる方法もありますので、ご時間があればそちらの方も探してみてください。
study_111

2020/07/23 12:30 編集

デプロイの際は、開発用の設定のままになっていないように注意したいと思います。 ご親切にご助言下さり、ありがとうございました。 今後も、教えて貰ったことを生かし、勉強を続けていきたいと思います。
guest

0

オリジン は 「プロトコル + // + ホスト名 + ポート番号」で成る文字列です。

ブラウザは http://127.0.0.1:8080http://localhost:8080 とはクロスオリジンの関係にあるものとして、CORS エラーを吐きます。

エラー解決の為、アドバイス頂けましたら幸いです

他者の記事やコードを真似て、手を動かして確認できているように感じますが、
それぞれの仕組み(なぜ、そのように書けるのか?)について、詳細を再確認してください

活字ばかりだと退屈かもしれませんが、仕組みを覚えると、エラー原因は自身で特定できるようになります。

投稿2020/07/18 06:29

AkitoshiManabe

総合スコア5432

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

study_111

2020/07/18 07:59

ご回答ありがとうございます。 >MDN HTTPヘッダ ... 要求ヘッダ / 応答ヘッダ の違いを間違えない MDN オリジン間リソース共有 (CORS) Google検索 CSRF ... (ご質問の追記2に関連)CORSを解決して考えましょう。 こちら、確認してみました。 やはり恐らく、csrfトークンをpostをする際に、必要だということが分かったのですが、csrfトークンの生成&付加の方法が分からず、手詰まりしてしまってる状況です。。
AkitoshiManabe

2020/07/18 08:46

CSRFの特徴は、 1. サーバー-ブラウザ間で事前にトークン(合言葉)を示し合わせる。 2. POSTされたら、トークンを照合してDBに書き込み/無視。トークンを棄てる 本題(CORS)に関連するのは、1. でトークンを示し合わせる際に HTTPヘッダーを使う場合(Access-Control-Allow-Headers が必要)です。他にも単に input[type=hidden] に埋め込む実装もあります(CORSは無関係)。 修学目的であれば、複数の決め打ちされたトークンをループする手法が使えるでしょう。 詳細はご質問(CORS)とは別になりますので、概要のみのコメントとさせていただきます。
study_111

2020/07/18 10:02 編集

ご返信ありがとうございます。 > 1. サーバー-ブラウザ間で事前にトークン(合言葉)を示し合わせる。 こちらなのですが、実際に運用していく目的であります為、ランダムに一意に生成されるトークンの生成を考えています。 また、サーバーとブラウザ間で示し合せる為には、フロント側で生成したcsrfトークンをDjango側で検証する必要かと思うのですが、今回djangoのテンプレートエンジンを使用し{% csrf_token %}のような形で生成している訳ではない為、実際にどのようにブラウザから送られてきたトークンを検証するのかといった部分が分からない状態ですね。。
AkitoshiManabe

2020/07/18 10:26

> ブラウザから送られてきたトークンを検証する サーバー側で生成してブラウザに渡した情報ですので、セッションとしてサーバー側で保持しておく。 POST時にデータ保存前に比較する(比較後はセッションとの紐付けを解除)。という形で検証できそうですよね。 ご質問の本題であるCORSから脱線して、CSRF、Sessionの話題に変わっていますので、色々と試してみて、改めて質問にまとめてみてはいかがでしょう。
study_111

2020/07/18 16:22 編集

そうですね。もう少し色々と調べてみて、新たに回答がつかなかった場合、質問を新たに立てるか考えたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問