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

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

ただいまの
回答率

90.49%

  • JavaScript

    16957questions

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

  • jQuery

    6914questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • API

    1555questions

    APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

  • Ajax

    1113questions

    Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

teratailAPIのアクセストークンを上手く含めることが出来ない

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 5
  • VIEW 4,511

k_fujimoto

score 128

困っていること

teratailAPIを用いて、ランダムに質問を表示するアプリを作っているのですが、リクエスト時にアクセストークンを上手く含めることができずに困っております。
解決方法やヒントをいただけると幸いです。

実践したこと

下記のリンクを参考に、以下のコードを書きました。
http://api\.jquery\.com/jQuery\.ajax/
http://semooh\.jp/jquery/cont/doc/ajax_event/
http://uhyohyo\.net/javascript/13_1\.html
http://docs\.teratailv1\.apiary\.io/#introduction

<html>
  <head>
    <meta name="viewport" content="width=device-width,user-scalable=no,maximum-scale=1" />
    <link rel="stylesheet" type="text/css" href="\./assets/css/questionToday\.css">
    <link rel="stylesheet" type="text/css" href="\./assets/css/reset\.css">
    <title>今日の質問</title>
    <script src="https://ajax\.googleapis\.com/ajax/libs/jquery/2\.2\.0/jquery\.min\.js"></script>
    <script type="text/javascript" src="\./assets/js/questionToday\.js"></script>
    <script type="text/javascript" src="\./assets/js/three\.min\.js"></script>
  </head>
  <body id="p-questionToday">

    <ul class="u-flexBox u-flexBox--alignCenter">
      <li class="j-startChangeId c-btn p-btnStart">スタート</li>
      <li class="j-stopChangeId c-btn p-btnStop">ストップ</li>
    </ul>
    <p class="jt-stopChangeId p-questionId">0</p>

    <div class="u-modal">
      <div class="p-questionBox">
        <h2 class="p-questionBox__ttl"></h2>
        <pre class="p-questionBox__markdown"></pre>
      </div>
      <div class="p-answerBox"></div>
      <p class="c-btn p-btnAnswer is-hidden">teratailで回答する</p>
    </div>
  </body>
</html>
\$\(function\(\){

  //最初にmaxのquestionIdを取得する
  \$\.ajax\({
    //アクセストークンを仕込む
    beforeSend: function\(xhr\){
      xhr\.setRequestHeader\("Authorization", "Bearer " \+ "0123456789abcdef0123456789abcdef0123456789"\);
    },
    type: "GET",
    url: "https://teratail\.com/api/v1/questions\?limit=1&page=1",
    async: true,
    dataType: "json",
    success:function\(json\){
      \$questionId = 0;
      \$maxId = json\.questions\[0\]\.id;

        //start
        if\(\$\('\.j-startChangeId'\)\.on\('click', function\(\){
          //loop処理の上限値に最新のquestionIdを代入する
          function loop \(\) {
            \$questionId = Math\.floor\(Math\.random\(\)\* \$maxId\)\+1;
            \$\('\.jt-stopChangeId'\)\.text\(\$questionId\);
          }
          //questionIdをループで回す
          \$loopId = null;
          clearInterval\(\$loopId\);
          \$loopId = setInterval\(loop, 20\);
        }\)\);

        //stop
        if\(\$\('\.j-stopChangeId'\)\.on\('click', function\(\){
          clearInterval\(\$loopId\);
          \$questionId = \$\('\.jt-stopChangeId'\)\.text\(\);
          \$questionUrl = "https://teratail\.com/api/v1/questions/" \+ \$questionId;
          //questionのリクエスト
          \$\.ajax\({
            //アクセストークンを仕込む
            beforeSend: function\(xhr\){
              xhr\.setRequestHeader\("Authorization", "Bearer " \+ "0123456789abcdef0123456789abcdef0123456789"\);
            },
            type: "GET",
            url: \$questionUrl,
            async: true,
            dataType: "json",
            success:function\(json\){
              \$ttl = json\.question\['title'\];
              \$body = json\.question\['body'\];
              \$\('\.p-questionBox'\)\.children\(\)\.empty\(\);
              \$\('\.p-questionBox__ttl'\)\.append\(\$ttl\);
              \$\('\.p-questionBox__markdown'\)\.append\(\$body\);
              \$\('\.p-btnAnswer'\)\.removeClass\('is-hidden'\);
>'\);
            }
          }\);
        }\)\);
    }
  }\);

}\);

不足している情報などございましたら、ご指摘ください。
よろしくお願いいたします。


追記(2016/04/04 7:00)

実行環境

http://qanji\.github\.io/questionToday\.html

エラー内容

以下2つのエラー内容が吐かれております。

OPTIONS https://teratail\.com/api/v1/questions\?limit=1&page=1
XMLHttpRequest cannot load https://teratail\.com/api/v1/questions\?limit=1&page=1\. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource\. Origin 'http://qanji\.github\.io' is therefore not allowed access\. The response had HTTP status code 501\.

以下の記述を含めない場合、つまりアクセストークンなしのリクエストの場合は正常に機能しており、エラーも吐かれません。

//アクセストークンを仕込む
    beforeSend: function\(xhr\){
      xhr\.setRequestHeader\("Authorization", "Bearer " \+ "0123456789abcdef0123456789abcdef0123456789"\);
    },
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • ikuwow

    2016/04/03 15:32

    「リクエスト時にアクセストークンを上手く含めることができず」というのは具体的にどういう状態でしょうか? リクエストがそもそもエラーになるのでしょうか。それともトークンのないリクエストとなってしまうということでしょうか。現象を追記していただけると助かります。

    キャンセル

  • k_fujimoto

    2016/04/04 07:04 編集

    @ikuwowさん リクエストがそもそもエラーになっております。 追記いたしましたので、お手数ですが改めてご確認いただけると幸いです。

    キャンセル

回答 2

checkベストアンサー

+3

いくつか試してみました。

\$ curl -X GET -H "Authorization: Bearer 0000000aaaaaaaaaaaa" https://teratail\.com/api/v1/questions\?limit=2
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1116  100  1116    0     0   2584      0 --:--:-- --:--:-- --:--:--  2589
{
  "meta": {
    "message": "success",
    "total_page": 15699,
    "page": 1,
    "limit": 2,
    "hit_num": 31397
  },
(略)

こちらは問題なくリクエストが飛んできました。

次にフロントエンドのJavaScriptから取得を試みました

<h1>test</h1>

<script>
var xhr = new XMLHttpRequest\(\);
xhr\.onreadystatechange = function\(\){
    if \(this\.readyState==4 && this\.status==200\) {
        var r = this\.response;
        console\.log\(r\);
    }
};

xhr\.open\('GET','https://teratail\.com/api/v1/users/ikuwow/activities',true\);
xhr\.setRequestHeader\('Authorization', 'Bearer as8769843hhge6c5eb2af8e9c4d0basd4948487'\) // \(1\)
// xhr\.withCredentials = true; \(2\)
xhr\.send\(\);
</script>

この場合以下のエラーが出ました。仰るとおり\(1\)をコメントアウトした状態では無事に取得できました。

XMLHttpRequest cannot load https://teratail\.com/api/v1/users/ikuwow/activities\. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource\. Origin 'http://localhost:8484' is therefore not allowed access\. The response had HTTP status code 501\.

また、いろいろいじっている過程で、\(1\)をコメントアウトして\(2\)のコメントアウトを解いたらまた違うエラーを見ることができました。

XMLHttpRequest cannot load https://teratail\.com/api/v1/users/ikuwow/activities\. A wildcard '\*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true\. Origin 'http://localhost:8484' is therefore not allowed access\. The credentials mode of an XMLHttpRequest is controlled by the withCredentials attribute\.

Access-Control-Allow-Origin\*という不特性多数からアクセス可能なホストでは、セキュアな情報と送れない、ということです。

というわけで気づいたのが、そもそもアクセストークンというセキュアにする情報をユーザーサイドのJavaScriptに渡してはいけないということです。フロントエンドJavaScriptで情報をほんとうに暗号化したまま送ることは不可能なので、バックエンドでAPIとの通信をするなど別の方法を取る必要がある気がします。

(XMLHttpRequestの仕様を詳細を調べずに回答しているので、もし間違いなどあれば間違いなどあれば補足していただけると幸いです)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/07 22:10

    サーバーサイドで認証を行わなければいけないということだったのですね。
    貴重な回答をいただきありがとうございます。

    キャンセル

  • 2016/09/08 15:15

    具体的にサーバサイドでどのように認証を行うのですか?

    キャンセル

  • 2016/09/08 15:28

    ↑すいません、質問を立てます。

    キャンセル

+2

エラーメッセージからすると Ajax のクロスドメイン問題でしょうか。

下記のサイトにいくつかの回避方法が、説明されているので、ご確認ください。

http://d.hatena.ne.jp/satosystems/touch/20140108/1389173683

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/04 21:30

    ご回答頂きありがとうございます。URLを参考にさせていただきました。
    【1. 'Access-Control-Allow-Origin' ヘッダを付与】と【2. JSONP で行う】に関しては、API提供側で対応される必要があるため回避することができませんでした。
    【3. jquery.xdomainajax.js を利用する】を試みてみましたが、こちらもエラー内容に変化が無く回避することができませんでした。

    貴重なアドバイスをありがとうございました。

    キャンセル

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

  • ただいまの回答率 90.49%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • JavaScript

    16957questions

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

  • jQuery

    6914questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • API

    1555questions

    APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

  • Ajax

    1113questions

    Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。