本日は、『Ajaxで”Access-Control-Allow-Origin”エラーの場合の対策』を残しておきます。
環境
今回の実装環境をまとめておきます。
サーバ OS | CentOS 6 |
Web サーバ | Apache 2.2 |
AP サーバ | Tomcat 7 |
サーバ側、言語・フレームワーク | Java 7, Struts2 |
呼び出し元、言語・フレームワーク | HTML, jQuery |
呼び出し元ページ作成
今回は、サンプルなので呼び出し元ページをHTMLで作成します。
HTML内は下記のようになります。
<div id="ajax_content"> </div>
上の”id = ajax_content” にJavascriptで取得したHTMLを埋め込みます。
スクリプトは下記のようになります。
このスクリプトでは、jQueryを利用します。
jQueryはこちらからダウンロードできます。
<script type="text/javascript" src="jquery-1.10.2.min.js"></script> $(document).ready(function(){ $.ajax({ url: "http://sample.com/get_list.html", dataType: "html", cache: false, success: function(data, textStatus){ startIndex = data.toString().indexOf("") + 6; lastIndex = data.toString().lastIndexOf(""); tmp = data.substring(startIndex, lastIndex); $('#ajax_content').html(tmp); } }); });
サーバから取得した値が”data” 変数に入ります。
ここでsubstringをしているのは、dataの値はHTML全体が含まれてしまうためです。
※ スマートなやり方を検討中です。
これで、ページロード時にJavascriptが実行されてサーバから取得した値が”ajax_content” に埋め込まれるはずです。
クロスドメイン対策
前項の実装でAjaxの埋め込みは完了なのですが、思わぬ落とし穴があります。
それは『クロスドメイン』です。
ツールなどを利用すると”Access-Control-Allow-Origin” のエラーが出力される場合がそれに当たります。
要は、ドメインが違うサイト同士ではAjax のやり取りをNG にするというのがこの問題です。この制御ははブラウザによって制御されます。
クロスドメインについてはこちらのサイトが詳しく説明されていると思うのでご参考にしてみて下さい。
※ ちなみにサブドメインが異なる場合もこの問題が発生します。
この問題の根本的な解決方法は、『サーバ側の呼び出されるページのヘッダにアクセス許可を追加すること』です。
具体的にはヘッダに下記の文字列が含まれればどのような方法でも解決出来ます。
Access-Control-Allow-Headers: * Access-Control-Allow-Origin: *
それで、今回は下記の4つの方法の対策を紹介することにします。
※ 4つの方法の内どれか1つでも行えばこの問題は回避出来ます。
- Apacheでの対策
- Actionでの対策
- jspでの対策
- phpでの対策
Apacheでの対策
“Access-Control-Allow-Origin”問題の1つめの解決策は、Apacheでヘッダを制御する方法です。
Apacheにmod_headers を追加し、”httpd.conf” に設定を追記すれば完了です。
mod_headers のインストール方法は下記のように行いました。
# cd /usr/local/src/httpd-2.2.*/modules/mappers/ # /usr/local/apache2.2/bin/apxs -c mod_headers.c # /usr/local/apache2.2/bin/apxs -i -a -n headers mod_headers.la # /usr/local/apache2.2/bin/apachectl -l # /usr/local/apache2.2/bin/apachectl -t
続きて”httpd.conf” の追記です。
DocumentRoot "/usr/local/apache2.2/htdocs" ServerName sample.com Header set Access-Control-Allow-Headers "Content-Type" Header set Access-Control-Allow-Origin "*" ProxyPass ajp://localhost/
っとこんな風に”Header” の設定を記載します。
この対策は先程のサイトこちらを参考にしました。
Actionでの対策
Action内では次の2つの方法の内どちらかを利用することで対応出来ます。
他にも色々と有りそうですね。
HttpHeaderResultを利用する
Header に先ほど説明した内容を追加すれば良いので、Struts2 のActionを利用しても対策の実現ができます。
スクリプトは次のようになると思います。
※ もしかすると間違えているかもしれません。
HttpHeaderResult header = new HttpHeaderResult(); header.add("Access-Control-Allow-Headers", "*"); header.add("Access-Control-Allow-Origin", "*");
こちらのサイトが参考になります。
HttpServletResponseを利用する
public void doGet(HttpServletRequest request, HttpServletResponse response){ ... response.setHeader("Access-Control-Allow-Headers", "*"); response.setHeader("Access-Control-Allow-Origin", "*");
この方法はこちらのサイトを参考にしました。
jspでの対策
jsp を利用して対策を施すこともできます。
jsp では下記のように追記することで対応出来ます。
<head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta http-equiv="Access-Control-Allow-Origin" content="*"> <meta http-equiv="Access-Control-Allow-Methods" content="GET"> <meta http-equiv="Access-Control-Allow-Headers" content="*"> </head>
phpでの対策
外部サイトに手を加えることが出来ない場合、php のページを挟むことで解決することができます。
この方法では、php サイトのリクエストパラメタにアクセス先URL を設定することで実現出来ます。
この方法についてはこちらのサイトをご確認下さい。
まとめ
今回は、『Ajaxで”Access-Control-Allow-Origin”エラーの場合の対策』について説明をしました。
Ajaxで実現する場合は、サーバ側のレスポンスにも十分な注意を払いましょう。
By Saito