Firebase HostingにはBasic認証かけたりIP制限等の機能が標準では提供されていません。
それを実現するためにはFunctionsの機能と連携して実現します。
方針
- まず、リクエストをpublicではなくfunctionsの(app)関数にリクエストを仕向ける。
- rewrite先の関数で何を表示するかを決める。
- 表示するまでに認証等の処理をかますことにより必要な処理を行う。
作業場所の準備
作業場所を作ってfirebase initをします。
cd
mkdir rewrite
cd rewrite
firebase init
FunctionsとHostingを選択。
下記のようなフォルダが作成されるはずです。
.
├── firebase.json
├── functions
└── public
まず、public内のindex.htmlを削除しておきます。ファイルが存在するとそちらが優先して表示されてしまうようです。
次にfunctionsでcreate-react-appを実行します。
いろいろ編集したらbuildして、buildフォルダを作成しておきます。
cd functions
create-react-app react-app
yarn build
公開サイト/ファイルはpublicではなく、functions/react-app/build/(index.html)に変更していきます。
実装
それぞれのファイルを編集していきます。
firebase.json(rewrite設定)
まず、firebase.jsonのrewritesを設定して全て(**)のリクエストをfunction, appに転送します。
{
"hosting": {
"public": "public",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"function": "app"
}
]
}
}
SPAをホスティング
認証を設定する前に、そもそもSPAアプリをfunction経由で表示する設定をします。
大きくは2つの設定を。
const functions = require('firebase-functions');
const express = require('express');
const path = require('path');
const app = express();
//とりあえずスタティックの場所指定
app.use(express.static(__dirname + '/react-app/build/'));
//それ以外の時もindex.htmlへ
app.all('*', (req, res, next) => {
res.sendFile(path.resolve(__dirname, 'react-app/build/index.html'));
})
exports.app = functions.https.onRequest(app);
deploy
一旦ここでdeployしておきます。
firebase deploy
reactの標準画面が見えればOKです。
一見、Hostingを利用しているのと変わりませんが、functions経由で表示されています。
Basic認証
Basic認証を設定します。まずモジュールをインストールします。
npm isntall --save basic-auth-connect
ここではID=admin, password=passwordに設定しています。
const functions = require('firebase-functions');
const express = require('express');
const path = require('path');
+const basicAuth = require('basic-auth-connect');
const app = express();
+app.use(basicAuth('admin','password'));
//とりあえずスタティックの場所指定
app.use(express.static(__dirname + '/react-app/build/'));
//それ以外の時もindex.htmlへ
app.all('*', (req, res, next) => {
res.sendFile(path.resolve(__dirname, 'react-app/build/index.html'));
})
exports.app = functions.https.onRequest(app);
firebase deploy
IP制限
ついでにIP制限をも追加設定してみます。
const functions = require('firebase-functions');
const express = require('express');
const path = require('path');
const basicAuth = require('basic-auth-connect');
+const requestIp = require('request-ip');
//許可IP 43.233.87.238
+const allowedIps = ['43.233.87.238'];
const app = express();
//basic認証
app.use(basicAuth('admin', 'password'));
//IPチェック
+app.all('*', (req, res, next) => {
+ //IPチェック
+ const clientIp = requestIp.getClientIp(req);
+ const isAllowed = allowedIps.indexOf(clientIp) !== -1;
+ if (!isAllowed) {
+ res.send("You can't access this site.")
+ } else {
+ next();
+ }
+})
//とりあえずスタティックの場所指定
app.use(express.static(__dirname + '/react-app/build/'));
//それ以外の時もindex.htmlへ
app.all('*', (req, res, next) => {
res.sendFile(path.resolve(__dirname, 'react-app/build/index.html'));
})
exports.app = functions.https.onRequest(app);