teratail header banner
teratail header banner
質問するログイン新規登録

質問編集履歴

5

参考サイトを追記

2018/06/21 02:52

投稿

tarotarosu
tarotarosu

スコア114

title CHANGED
File without changes
body CHANGED
@@ -157,4 +157,9 @@
157
157
  なので理想としては、
158
158
  「ユーザ認証をパスしたユーザにのみCloud Storage上の画像を表示させる。しかも画像を表示させるためのダウンロードURLは末尾のトークンを抜いた形式で」
159
159
  という手法です。
160
- この手法を実現する方法はないでしょうか?...
160
+ この手法を実現する方法はないでしょうか?...
161
+
162
+
163
+ 下記リンク先で同じ疑問を持った方がいるようなのですが、回答にあるようなセキュリティルールでは誰でもアクセスできてしまうので...
164
+
165
+ [Access url without token in Firebase Storage - Stack Overflow](https://stackoverflow.com/questions/46153828/access-url-without-token-in-firebase-storage?rq=1)

4

追記2_1

2018/06/21 02:51

投稿

tarotarosu
tarotarosu

スコア114

title CHANGED
File without changes
body CHANGED
@@ -136,4 +136,25 @@
136
136
  ```
137
137
 
138
138
  を利用して画像を表示させようとしていることに問題があるのではないかと思っています。
139
- (末尾のトークン(?)を省いているのが原因なのかどうなのか...)
139
+ (末尾のトークン(?)を省いているのが原因なのかどうなのか...)
140
+
141
+ ### 追記2_1
142
+ ダウンロードURLの末尾のトークンを省いていることに問題がありそうだったので、
143
+
144
+ ```javascript
145
+ downloadUrl: `https://firebasestorage.googleapis.com/v0/b/${bucketName}/o/${encodeURIComponent(filePath)}?alt=media&token=hogehoge...`
146
+ ```
147
+
148
+ のように(コンソールから確認できるダウンロードURLで)記述したところ、認証状態によって画像の表示・非表示ができました。
149
+ (ただこのトークンが何なのかを今一つ理解せずに実験してみての結果なのでトークンによるものなのかは断言できないです...)
150
+
151
+ しかし、末尾のトークンを正しくつけてやればいいのではないかということは分かったのですが、個人的に考える重大な問題があります。
152
+ それは「ダウンロードURLを`<img>`に突っ込んでいるわけなので、ブラウザのディベロッパツールなどからダウンロードURLを見れば、簡単に外部からでもアクセスできてしまう」というものです。
153
+ ユーザ認証をパスした者が悪意あるユーザにダウンロードURLを教えた場合、そのダウンロードURLにアクセスしまくり、Firebaseの料金に影響を及ぼすことはできるわけですよね?
154
+
155
+ ちなみにですが、末尾のトークンを含まないダウンロードURLで外部からアクセスした場合は403が返ってき、アクセスできません。
156
+
157
+ なので理想としては、
158
+ 「ユーザ認証をパスしたユーザにのみCloud Storage上の画像を表示させる。しかも画像を表示させるためのダウンロードURLは末尾のトークンを抜いた形式で」
159
+ という手法です。
160
+ この手法を実現する方法はないでしょうか?...

3

試したことを追記

2018/06/21 02:10

投稿

tarotarosu
tarotarosu

スコア114

title CHANGED
File without changes
body CHANGED
@@ -110,4 +110,30 @@
110
110
  imageDatas: datas,
111
111
  });
112
112
  });
113
- ```
113
+ ```
114
+
115
+ ### 追記2
116
+
117
+ 色々と試しているのですが、下記のように`getDownloadURL()`を使って画像のダウンロードURLを取得し、表示させようとすると、ちゃんとユーザの認証状態によって画像の表示・非表示ができます。
118
+
119
+ ```javascript
120
+ const storage = firebase.storage();
121
+ const fileRef = storage.ref().child('path to file');
122
+ fileRef.getDownloadURL().then((url) => {
123
+ this.setState({
124
+ downloadUrl: url,
125
+ });
126
+ }).catch((err) => {
127
+ console.log(err);
128
+ });
129
+ ```
130
+
131
+ つまり、`getDownloadURL()`で画像を表示せずに、
132
+ Firestoreに記述された
133
+
134
+ ```javascript
135
+ downloadUrl: `https://firebasestorage.googleapis.com/v0/b/${bucketName}/o/${encodeURIComponent(filePath)}?alt=media`
136
+ ```
137
+
138
+ を利用して画像を表示させようとしていることに問題があるのではないかと思っています。
139
+ (末尾のトークン(?)を省いているのが原因なのかどうなのか...)

2

誤字修正

2018/06/21 00:58

投稿

tarotarosu
tarotarosu

スコア114

title CHANGED
File without changes
body CHANGED
@@ -88,7 +88,7 @@
88
88
  }
89
89
  ```
90
90
 
91
- そして、`uid`が表示できた場合に表示するコンポーネントの中で、
91
+ そして、`uid`が取得できた場合に表示するコンポーネントの中で、
92
92
 
93
93
  ```javascript
94
94
  downloadUrl: `https://firebasestorage.googleapis.com/v0/b/${bucketName}/o/${encodeURIComponent(filePath)}?alt=media`

1

コメントを受けての追記

2018/06/20 13:30

投稿

tarotarosu
tarotarosu

スコア114

title CHANGED
File without changes
body CHANGED
@@ -37,4 +37,77 @@
37
37
  このようなセキュリティルールに書き換えたところ、ユーザ認証をパスしたユーザであっても画像を表示できなくなってしまいました(403エラーが返ってきます)。
38
38
 
39
39
  ユーザ認証をパスしているはずなのになぜ画像が表示できなくなってしまったのでしょうか?
40
- 何かご回答を頂けると助かります<(_ _)>
40
+ 何かご回答を頂けると助かります<(_ _)>
41
+
42
+ ### 追記
43
+ Reactのコードですが、
44
+ ユーザ認証を行う下記コンポーネント内で`uid`が取得出来たら配下のコンポーネントを表示し、取得できなければログインページへリダイレクトさせるという処理をし確認しています。
45
+
46
+ ```jsx
47
+ export default class Auth extends React.Component {
48
+ constructor(props) {
49
+ super(props);
50
+ this.state = {
51
+ uid: null,
52
+ loading: true,
53
+ };
54
+ }
55
+
56
+ componentDidMount() {
57
+ this.removeListener = firebase.auth().onAuthStateChanged((user) => {
58
+ if (user) {
59
+ this.setState({
60
+ uid: user.uid,
61
+ loading: false,
62
+ });
63
+ } else {
64
+ this.setState({
65
+ loading: false,
66
+ });
67
+ }
68
+ });
69
+ }
70
+
71
+ render() {
72
+ if (this.state.loading) {
73
+ return (
74
+ <p>Now Loading...</p>
75
+ );
76
+ }
77
+
78
+ if (!this.state.uid) {
79
+ return (
80
+ <Redirect to="/" />
81
+ );
82
+ }
83
+
84
+ return (
85
+ this.props.children
86
+ );
87
+ }
88
+ }
89
+ ```
90
+
91
+ そして、`uid`が表示できた場合に表示するコンポーネントの中で、
92
+
93
+ ```javascript
94
+ downloadUrl: `https://firebasestorage.googleapis.com/v0/b/${bucketName}/o/${encodeURIComponent(filePath)}?alt=media`
95
+ ```
96
+
97
+ が格納されたFirestoreのドキュメントを下記のようにまとめて取得し、`<img>`に突っ込んでいっています。
98
+
99
+ ```javascript
100
+ const db = firebase.firestore();
101
+ const datas = [];
102
+
103
+ db.collection('images').get()
104
+ .then((snapshot) => {
105
+ snapshot.forEach((doc) => {
106
+ const data = doc.data();
107
+ datas.push(data);
108
+ });
109
+ this.setState({
110
+ imageDatas: datas,
111
+ });
112
+ });
113
+ ```