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

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

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

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

HTML5

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

JavaScript

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

3回答

5939閲覧

HTMLの img タグの src 属性に設定されたURLにアクセスする際に HTTP ヘッダーを設定したい

yamashita_yuich

総合スコア316

Vue.js

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

HTML5

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

JavaScript

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

2クリップ

投稿2020/06/18 02:24

編集2020/06/18 03:54

1. 現状 & わからないこと

フロントエンドにて、リッチエディタを使用しております。
リッチエディタの中に画像が挿入された場合、
その画像はバックエンドサーバー内に保存し、
画像を取得するURLをリッチエディタのimgタグのsrc属性に設定する仕様としております。

バックエンドサーバーはREST API として提供しており、
ユーザーの判定はJWTトークンをHTTPヘッダーに渡すことで実現しております。

リッチエディタ内の画像についてはユーザーごとに厳格なアクセス制御をる必要があるのですが、
imgタグのsrc属性に設定されたURLのアクセス時にHTTPヘッダーを設定する方法がわかりません。

また、リッチエディタに挿入する画像をそもそも imgタグのsrc属性で管理すること自体
ナンセンスなのかもしれませんが、
他の実装案が思いついておらず、困っている状況でございます。

補足ですが、バックエンド・フロントエンド共に私の担当領域であるため、
実装の修正はいずれも柔軟にできます。
つきましては、なるべくあるべき実装にしていきたいと考えております。

何かアイデアなど頂けませんでしょうか。
よろしくお願い致します。

P.S.

参考までに、本件、Jiraの画像管理の方式を調査して参考にしようと思ったのですが、
現時点でイマイチ正しく理解できていません。
この点についてもこんな方式で実現しているのではないか、という仮説がありましたら
ご教示頂けますと幸いです。


[2020/6/18 12:41 追記]

その後、更に Jira の実装を解析しました。
その結果、以下がわかりました。

① リッチエディタにて画像が挿入された際、img 要素をラップする div 要素にて、 data-id というカスタム属性を用いて画像のidを示している
② data-id を基に Ajax 通信を使用してサーバー側と REST通信を実行
③ 得られたデータは URL.createObjectURL() で内部的なURLに変換
④ 得られた内部的なURLを①で言及した div タグ配下のimgタグに挿入する (JSによるDOM操作が走っていると思われ)

ここからは恐らくですが、
ユーザーによるリッチエディタの編集が完了して保存された際は、
imgタグをラップするdivタグを走査してその配下のimgタグを初期化 / 削除した後サーバーに送信
(もしくはサーバー側で除去) しているのではないかと思います。

同じことを実装すれば一旦本課題はcloseできそうですが、
できればDOM操作を避けることができるとより良いです。

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

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

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

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

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

kei344

2020/06/18 02:29

「ユーザーごとに厳格なアクセス制御」とは具体的にどのようなものなのでしょう。
yamashita_yuich

2020/06/18 03:38 編集

コメントありがとうございます。 例えば、ユーザーAが起票した情報に埋め込まれた画像は、 ユーザーAがログインしている状態でないと見れないようにアクセス制御したいという意です。 つまり、第三者がimgタグのsrc属性に設定されたURLを入手したとしても、 ユーザーA以外の第三者がアクセスしても401/403が返却されるようにしたいということです。
guest

回答3

0

例えば、ユーザーAが起票した情報に埋め込まれた画像は、

ユーザーAがログインしている状態でないと見れないようにアクセス制御したいという意です。

画像を公開領域に置かず、サーバ側言語を経由して読み込むようにすれば制御できます。

投稿2020/06/18 02:41

kei344

総合スコア69606

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

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

yamashita_yuich

2020/06/18 02:51

回答ありがとうございます。 質問本文に記述しましたが、 バックエンドサーバーは「Rest API」形式で提供しており、 ログインユーザーの制御はJWTトークンを用いて実施しております。 JWTトークンは常に HTTPヘッダーに設定し、 バックエンドサーバーはそのJWTトークンを基にログインユーザーを特定しています。 当然、JWTトークンを設定しないと401が返却される仕様です。 imgタグのsrc属性に設定されたURLにアクセスする際、 HTTPヘッダーの設定はできませんね。 HTTPヘッダーを設定できないということはJWTトークンを設定できないということなので、 APIからのレスポンスは常に401になります。 これでは困るために、imgタグのsrc属性に設定したURLへのアクセスの際に HTTPヘッダーを設定し、特定のユーザーのみ画像を取得できるようにしたいのです。 また、調べていて段々わかってきたのですが、 別のAPIを打鍵して(当方 axios を使用)、そこで得たリソースを URL.createObjectURL() を使用して blob:http~~ 形式の内部的なURLに変換し、それをsrc属性に設定することで、 上手く回避できるかもしれないことがわかってきました。 少しこの辺りを引き続き調査してみようと思います。
kei344

2020/06/18 02:57

サーバ側言語を経由してヘッダーをつければいいのでは。
yamashita_yuich

2020/06/18 02:58

すみません。 正しく理解できていないです。 もう少し細かくご教示頂けないでしょうか。
kei344

2020/06/18 03:00

厳密にしたいのであれば画像のURLを返すときに適当な期限の付いたトークンでも生成して、そのトークンつきの画像URLをサーバで受け取って、判別して、必要な画像を返せばよいでしょう。
kei344

2020/06/18 03:02

コメントが前後しました。「JWTトークン」とやらが何の仕組みかわかりませんので、私が見当違いのことを言っている可能性があります。
yamashita_yuich

2020/06/18 03:07

「画像のURLを返すときに適当な期限の付いたトークンでも生成して」 この仕様だと、適当な期限の間、誰でもその画像にアクセスできる状態となりますので、 厳格なアクセス制御と言えません。 また、トークンつきURLを毎度発行する場合、リッチエディタ内に埋め込まれたURLを 毎回クライアント側で書き換えるというキテレツ処理が必要になります。 なので、URLにトークンを付与するといった、 リッチエディタ内のHTMLに埋め込まれたURLを書き換える処理はなしです。 [JWTトークン] https://ja.wikipedia.org/wiki/JSON_Web_Token
kei344

2020/06/18 03:14

> この仕様だと、適当な期限の間、誰でもその画像にアクセスできる状態となりますので、 厳格なアクセス制御と言えません。 だから、そのトークンの検証をサーバ側でしてからサーバの画像を返すようにすればよいのでは?というコメントをしています。サーバになら認証情報があるでしょう。 https://qiita.com/tokutoku393/items/66c9916e47cab2a01167#%E3%83%99%E3%82%BF%E3%81%AEphp%E3%81%A7%E6%9B%B8%E3%81%8F 上記はPHPの例ですが、出力の前に認証すればよいだけでは。 APIを通す必要がどうしてもあるなら、API側で画像本体をbase64エンコードしたものを返すくらいでしょうか。
yamashita_yuich

2020/06/18 03:34 編集

そもそもですが、「REST API」 はステートレスな通信を実施するプロトコルですよね。 なので、session という概念はありません。 (PHPはステートフルな通信プロトコルを使用します。) 以上を前提としたうえで、 「トークンの検証をサーバ側でしてから」 この点が正しく理解できませんでした。 PHPと違い cookie を保持しない REST API において、 どうやって トークンの検証をサーバ側でするのかが 理解できておりません。
guest

0

ベストアンサー

自分が生成する HTTP チャネルであれば以下のように setRequestHeader が出来ますが、これを <img> タグがサーバに GET リクエストでリソースを取得しに行く時に適用させるには、どうしたら良いかという主旨の理解であっていますか?

function getRequest (method, url, token) { let xhr = new XMLHttpRequest(); xhr.open(method, url); xhr.setRequestHeader('Authorization', 'Bearer ' + token); return xhr; }

投稿2020/06/18 03:13

wata2

総合スコア17

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

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

yamashita_yuich

2020/06/18 03:20

はい。あっています。 ただ、もう少しスコープを広げて、 そもそも img タグ が GET リクエストでリソースを取得しに行く方式が正しいのかを検討したいです。 例えば、事前に、頂いたプログラムのような Ajax などを使用したリソースの取得を実行した後に、 URL.createObjectURL() を使用してFileオブジェクトにアクセスする内部的なURLを生成し、 それを <img> タグで使用するような実装も考えられると思います。 ただ、本件、 ユーザーがリッチエディタ内で挿入した画像に対する処理なので、 DOM操作による img タグの動的書き換えは避けたいです。
wata2

2020/06/18 10:48 編集

そうですね。ご認識のとおり <img> タグは src を指定したとたんに GET 要求を開始してしまいます。 以下のサンプルでは、質問者さんの記載されたように HTTP リクエストを自分で作成して(GET でも POST でもよいです)URL.createObjectURL で取得した画像データを <img> の内容に指定します。 これだと、HTTP リクエストの要求ヘッダは自由に指定できますし、明確に JWT トークンによる認証が働きます。しかし、この場合も、リッチエディタが生成する DOM の <img> タグを書き換えていることには変わらないです。 <!doctype html> <html> <head> <meta charset="utf-8"> <script> function loadImage (obj, url, token) { let xhr = new XMLHttpRequest(); xhr.open('POST', url, true); xhr.setRequestHeader("cache-control", "no-cache"); xhr.setRequestHeader('Authorization', 'Bearer ' + token); xhr.responseType = 'blob'; xhr.onload = function() { let url = URL.createObjectURL(this.response); let img = new Image(); img.onload = function() { URL.revokeObjectURL(url); }; obj.src = url; }; xhr.send(); } </script> </head> <body onload="loadImage(document.getElementById('img1'), 'https://placehold.jp/150x150.png', 'foobar...');"> <img id="img1" src=""> </body> </html>
wata2

2020/06/18 09:56

コメント欄でマークアップが利かないので 画像 URL の後ろの ' だけ &H39; に化けていますが、他は生きているので、ご容赦ください。 先のとおり <img> は src 属性を指定したとたんに GET 要求を開始してしまうので、このリクエストをフック(インターセプト)するには、ブラウザエクステンションを作るしか無いように思います。 Chrome や Edge のブラウザエクステンションを自作することで、インターセプトは容易に実現できますが、利用者にブラウザエクステンションを導入してもらう必要が出てしまうので、利用者環境を狭めてしまうデメリットがあります。
yamashita_yuich

2020/06/18 10:21 編集

ありがとうございます。 やはり、私の記述した・wata2さん記述頂いた方式が現実解ですね。。。 ちなみになんですが、今回使用しているリッチエディタが quill というものです。 (正確には、 quill を ラップした vue2-editor という vuejs 向けのライブラリ) quill では、利用者が画像を挿入した瞬間に動作する (リッチエディタにバインドされる前に) フックスクリプトを登録することができます。 現在は、このフックスクリプトを利用して、 ① バックエンドサーバーに画像を登録 (実際はバックエンド経由で AWS S3 に登録) ② 登録した画像を URL.createObjectURL() で blob:http 形式に変換 ③ 画像のURL自体は <img> の data-id 属性で保持し、src属性に blob:http 形式の URLを設定しリッチエディタに描画 という処理を実施することにしています。 また、リッチエディタが描画される際に、 ① <img>タグを走査して data-id 属性をキーに画像を取得し src 属性を上書きする という処理をインジェクトしようと思っています。(まだ未実装) また、リッチエディタ自体をコンポーネント化し、 <img> タグの書き換え処理は全てこのコンポーネント内で吸収することで、 リッチエディタの利用者 (私以外の開発者) は <img> タグの込み入った処理を意識する必要がない 構造にすることで、今回は許容することにしたいと思います。 ご回答ありがとうございました。
AkitoshiManabe

2020/06/18 10:39 編集

> ユーザーがリッチエディタ内で挿入した画像に対する処理なので リッチエディタ(Jira提供のWISYWIGエディタ:ビジュアルモード?)の画像取扱い周辺でイベントに割り込みをかけたりフックする方法があれば対応できるのではないかと感じましたが、エディタ内部にまで手を加えるのは本意ではないですよね(JWTトークンを要求Headerに加えるなら、Ajax以外に思いつきませんね。私も、DOM操作による img タグの動的書き換えは不可避ではないかと感じます)。プロセス待ちは生じるかもしれませんが、公式に機能提案してみる形になるのかなぁ。と感じました。 追記) …quill でしたか。
yamashita_yuich

2020/06/18 10:49

すみません。 quill にまで話が発展すると想定しておらず、 質問では記述しませんでした。。。 Jiraも結局 リッチエディタ内の DOM に修正を加えているので、 レベルの違いはあれど、本質問と同じ問題を抱えて、 本質問と同じような回避策をとったのだと思います。 例えばですが、 quill-src のような拡張属性を用意して、 リクエスト実施時に 任意の HTTPヘッダーを挿入できる 拡張機能はあっても良いかもしれませんね。。。 時間があればライブラリにして公開します。。。
guest

0

APIリクエストにaxios使っているのであれば、こんなコンポーネントがありました。
https://github.com/xzag/vue-auth-image

これは、Vue用みたいですが、実装内容を見ると、他にも流用できそうです。

投稿2021/08/30 07:01

MizukiKatagiri

総合スコア16

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問