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

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

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

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

OAuth 2.0

OAuth 2.0(Open Authorization 2.0)は、APIを通して保護されたリソース(サードパーティのアプリケーション)へアクセスする為のオープンプロトコルです。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

JavaScript

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

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

Q&A

解決済

1回答

4049閲覧

異なるドメインへjsonを送信する方法について

kanetugu_70e

総合スコア100

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

OAuth 2.0

OAuth 2.0(Open Authorization 2.0)は、APIを通して保護されたリソース(サードパーティのアプリケーション)へアクセスする為のオープンプロトコルです。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

JavaScript

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

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

0グッド

0クリップ

投稿2019/09/16 11:46

実現したいこと

異なるドメインへjsonをPOSTリクエストしたいです。
具体的には、サーバ"A"からレスポンスとしてjsonをブラウザで受け取り、それをサーバ"B"へPOST送信したいです。
条件詳細については以降に記載しますが、このような場合受信側サーバBがjsonデータをどのようなパラメータ名で受け取るかわからない限り、実現することはできないのでしょうか?

ブラウザ ====> 【サーバA】 ====> ブラウザ ====> 【サーバB】     

上記実現の為の条件は以下の通りです。
・サーバ間で直接やり取りは行わず、UA(ブラウザ)を介してPOST通信を行う。
・サーバBはjsonを受け取れることしかわからない。(受取るkey名は不明である)
・サーバBでは、access-control-allow-originは許可されていない。

背景

OAuth2.0を学んでいるのですが、アクセストークン取得までに行うパラメータのやり取りに1つ疑問が浮かびました。
OAuth2.0ではHTTPS通信が前提の為、GETでやり取りしている所が多く見受けられますが、POST通信でも同様にjsonのやり取り(実際はJWTでしょうが...)ができるのか疑問に思い実践しています。
そもそもOAuthにおけるJWTはHTTPヘッダのAuthenticationフィールドに付加するものであり、前述のような考え自体が仕様に反している等、OAUthに関する指摘でも構いませんので、ご教授頂けると幸いです。

試したこと

サーバA及び疑似リダイレクトで使用するjsを実装対象としています。

html

1<!-- firstSend.html --> 2 3<form action="/redirect" method="post"> 4 <input type="hidden" id="result" value=""/> 5 <input type="submit"/> 6</form> 7<script> 8 document.addEventListener("DOMContentLoaded",()=>{ 9 var data={name: "名前", age:100}; 10 let json = JSON.stringify(data); 11 const xhr = new XMLHttpRequest(); 12 xhr.open("POST","/send"); 13 14 xhr.setRequestHeader('content-type','application/json;charset=UTF-8'); 15 xhr.onreadystatechange = function(){ 16 if(xhr.readyState === 4){ 17 if(xhr.status === 200){ 18 console.log("OK"); 19 let input = document.getElementById("result"); 20 input.value = xhr.responseText; 21 //window.location.href = "localhots:8080/redirect"; 22 document.forms[0].submit(); 23 } 24 }else{ 25 console.log("通信中"); 26 } 27 }; 28 xhr.send(encodeURIComponent(json)); 29 }); 30</script>

java

1//サーバAに相当 2 3@PostMapping(value="/send", consumes = "application/json") 4@ResponseBody 5public String ajax(HttpServletRequest req, HttpServletResponse res){ 6 String data = null; 7 StringBuilder sb = new StringBuilder(); 8 try{ 9 BufferedReader br = req.getReader(); 10 while((data = br.readLine())!= null){ 11 sb.append(data); 12 } 13 }catch(IOException e){ 14 e.printStackTrace(); 15 } 16 17 data = new URLDecoder().decode(sb.toString(),StandardCharsets.UTF_8); 18 Gson gson = new Gson(); 19 Type type = new TypeToken<Map<String,Object>>(){}.getType(); 20 Map<String,Object> map = gson.fromJson(data,type); 21 map.entrySet().stream().forEach(e->{ 22 System.out.print(e.getKey()+":"); 23 System.out.println(map.get(e.getKey())); 24 }); 25 map.put("sex","male"); 26 String result = gson.toJson(map); 27 28 return result; 29}

java

1//サーバBに相当 2 3@PostMapping(value="/redirect") 4public String receive(HttpServletRequest req, HttpServletResponse res){ 5 //jsonを取得する処理。サーバBではあくまでjsonを取得していることしかわからない。 6

環境

java OpenJDK-12
Spring Boot 2.1.8

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

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

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

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

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

takasima20

2019/09/16 13:05

データ量が少ないなら適当な input タグにつっこんで、そのまま post すればいいんじゃないスかね。
kanetugu_70e

2019/09/16 13:23

「inputタグに突っ込んでpost」となるとform送信になりますが、この場合受け取り側(今回でいうサーバB)はパラメータを指定しないとjsonを取り出せないですよね? 記載通りの繰り返しになりますが、送信するjsonに名前付けはできないという条件があります。 あくまでjsonのみを送りたいです。
takasima20

2019/09/16 13:59

POST はしたいが FORM タグは使いたくない、と。ムリじゃね?
guest

回答1

0

ベストアンサー

XHRでの他ドメインへのアクセス禁止はブラウザ側の仕様です。
これを素直にクリアするにはサーバ側でAccess-Control-Allow-Originを正しく設定する他ありません。

よって

このような場合受信側サーバBがjsonデータをどのようなパラメータ名で受け取るかわからない限り、実現することはできないのでしょうか?

POSTされるかどうかはサーバ側でAccess-Control-Allow-Originが設定されているかどうかが条件であって、jsonの形式は関係ありません。
サーバ側アプリケーションからすればjsonを含むHTTPリクエストはただの文字列なので、受け取りさえ出来ればどうにでもなります。

Javaでの実装については知りませんが、どんな言語でも(普通はそこまでする必要は無いと思いますが)最悪でも生のHTTPリクエストを自力でパースすればデータを取得出来ます。

ブラウザの開発者ツールを使って、実際に送信されているデータを確認してみると原因と対策を把握しやすいかと思いますよ。

投稿2019/09/16 15:06

tanat

総合スコア18713

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

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

kanetugu_70e

2019/09/16 16:27 編集

ご回答頂きありがとうございます。 条件の3番目の通り、サーバBは`Access-Control-Allow-Origin`を設定していない為、ajaxによるPOSTは使うことができません。 その為、先の回答者様及び私の実装記載例の様にFormによるPOST通信が考えられます。しかしこれまた条件の通りですが、jsonが紐づいているkey名をサーバBが知る事はできません。 このような状況で、json文字列だけを受け取る方法はあるのでしょうか?(key名などは含めないでjsonだけを受け取れるか) もしくは、tanat様がおっしゃる自力パースとは、「他のform要素やkey名が混じった文字列をパースして、json部分だけを抽出する」といった意味合いでしょうか? お手数ですがご確認の程宜しくお願い致します。
tanat

2019/09/16 18:03 編集

どういった状況でそういった制限下での開発が必要になるかは想像がつきませんが、(背景として記載されている部分ともどうつながるかわかりません) > もしくは、tanat様がおっしゃる自力パースとは、「他のform要素やkey名が混じった文字列をパースして、json部分だけを抽出する」といった意味合いでしょうか? というのはその通りです。 POSTとして受け取ったすべてのキーの値をJSONとしてパースしてみて、サーバ側が望むJSONが取得出来たらそれが正しいとみなす くらいの方法しかないでしょうね。 *もし、制約が実は「サーバ側のソースを修正できない」というということであれば方法は存在しません。(質問の条件下では。) HTML formでのJSONの送信については この辺 https://www.w3.org/TR/html-json-forms/ を見ると検討された形跡はありますが、その後廃止されているので、この仕様を実装しているブラウザが存在するかは不明です。(多分無いと思います) * 開発時にクロスドメインになってしまうのでそれをどうにかしたいというだけであれば、 https://teratail.com/questions/210879 この辺の方法でなんとかなります。
tanat

2019/09/16 18:06

質問中の条件を変えていいのであれば、サーバAで一旦POSTを受け取ってからサーバ間通信でサーバBにJSONを送信すれば可能です(Access-Control-Allow-Originが設定されないAPIはそういった利用方法を想定しています)
kanetugu_70e

2019/09/17 03:55 編集

私の経験が浅く、今回のような条件で通信可能であるかが分からない(何か私が知らない方法があるかもしれない)為、質問させて頂きました。 その為、"実現不可"も私が求めていた回答の一つになります。 サーバ間通信についても、サーバAに余計な穴を開けたくない為、今回は考えておりませんでした。 ともあれ、頂いた回答及びリンクで私自身納得する事が出来ました。 背景、目的共に分り辛い質問にも関わらずお付き合い頂きありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問