はじめに
こちらの記事でcoesite3レポジトリがローカルでうまく動くか試してみましたが、ダメでした。おそらく、自己署名証明書はEntra IDでは使用できないのだろうと思われますので、レンタルサーバで試してみたいと思います。
レンタルサーバの環境については、こちらの記事に記載しています。
MySQLの設定
インストール
sudo dnf install -y @mysql
バージョン8.0.36がインストールされました。
MySQL を起動 & 自動起動設定
sudo systemctl enable --now mysqld
enable --now は サービスの自動起動 も設定します。
状態確認
sudo systemctl status mysqld
MySQLにログイン
mysql -u root
セッション用のデータベースを作成
CREATE DATABASE coesite3_db;
MySQL ユーザーを作成
CREATE USER 'coesite3_user'@'%' IDENTIFIED BY 'coesite3pass';
今回はIPアドレスで絞りたくないので、「%」を指定しています。
※接続元を絞る場合は「%」ではなく、任意のIPアドレスを使用します。
セッション用データベースの権限を付与
GRANT ALL PRIVILEGES ON coesite3_db.* TO 'coesite3_user'@'%';
FLUSH PRIVILEGES;
データベースの設定が正しくできたか確認
SHOW DATABASES;
coesite3_db がデータベースに含まれています。
ユーザの設定が正しくできたか確認
SELECT user, host FROM mysql.user;
hostが%となっていることが確認できました。
変更を確実に反映するために MySQL を再起動します。
sudo systemctl restart mysqld
こちらの記事を参照して、エラーが発生した箇所について認証方式を確認しました。
SELECT user, host, plugin FROM mysql.user;
plugin の列が mysql_native_password になっていたので、問題なさそうです。
coesite3のクローン
git clone https://github.com/unvt/coesite3
としてレポジトリをローカルにクローンします。
npm install
HTTPSのための設定
.envの設定
sample.envを.envに名称変更して、さらに設定を変更します。
特に
OAUTH_REDIRECT_URI=https://k96mz.com:3000/unvt/auth/callback
とします。unvtが含まれていることに注意が必要です。
さらにEntra IDにも上記URLをRedirect URIsに加えておきます。
MySQLの設定は以下としています。
MYSQL_USER=coesite3_user
MYSQL_PASSWORD=coesite3pass
MYSQL_DATABASE=coesite3_db
default.hjsonの設定
以下の通りの設定とします。
privkeyPath: ./key/privkey.pem
fullchainPath: ./key/cert.pem
port: 3000
証明書の場所もパスに合わせて変更し、さらにフォルダ及びファイルの所有者を変更します。
デフォルトページを表示する
node app.js
として、
https://k96mz.com:3000/unvt/
にアクセスします。
エラーが出ています。
ClientAuthError: no_account_in_silent_request: Please pass an account object, silent flow is not supported without account information
acquireTokenSilent() を実行しようとしていますが、account オブジェクトが指定されていないということでした。確かに、routes/index.jsのコードを見てみると、まだサインインしていないのに、userAccountの値を取ろうとしています。
default.hjsonのfullchainPath: ./key/cert.pem
の部分をfullchain.pemの名前を変更して、cert.pemとして試してみましたが、解決しませんでした。
別記事のcoesiteのコードでも試してみましたが、同様の結果でした。
こちらの記事に記載されている通り、index.jsのいらない部分をコメントアウトしてみます。
これで実行してみると、先程のエラーはなくなりました。
しかし、
https://k96mz.com:3000/unvt/
の読み込みに対して、以下のエラーが発生しました。
(failed)net::ERR_HTTP2_PROTOCOL_ERROR
リバースプロキシでやってみる
app_reverse.js
を作成して、リバースプロキシとNode.js間は、http接続に切り替えました。
app.listen(8080, () => {
console.log("running at port 8080 ...");
});
.envファイルは以下に変更しています。
OAUTH_REDIRECT_URI=https://k96mz.com/unvt/auth/callback
https://k96mz.com/unvt/
にアクセスします。
無事に表示されました。
この後、再度
routes/index.js
のコードをオリジナルのものにして試すと、問題なく動きました。
今から思えば、キャッシュが残っているときには、こちらのコードでないと、再度サインインしないといけなくなるので、これで正しいのかもしれません。
サインインしようとしましたが、以下のようなエラーが出ました。
PKCEが必要な認証フローに適切な設定がされていない 場合に発生するエラーらしいです。
PKCE (Proof Key for Code Exchange, ピクシー) は、OAuth 2.0 の 認可コードフロー において、コードインジェクション攻撃を防ぐためのセキュリティ強化手法らしいです。
Entra IDのページを見ていたら、以下の通り設定されていました。間違って登録したのかもしれません。とりあえず、削除して再度試してみます。
ようやく無事に表示されました。
MySQLに保存されているか確認
MySQLにログイン
mysql -u root
データベースを選択
USE coesite3_db;
sessionsテーブルを表示
SELECT * FROM sessions;
以下のようにきちんと記録されていました。
地図を表示する
Simple Web Map APP
にアクセスしてみましたが、エラーが発生しました。
(failed)net::ERR_NAME_NOT_RESOLVED
は、ブラウザが 指定されたドメイン名を解決できない(DNSルックアップに失敗した)ことを示しています。
おそらく、職場環境にあるサーバなので、外部からは接続できない設定になっているからだと思われます。
style-std.jsonを修正する
style-std.jsonのsprite、glyphs、tilesのルートURLを以下に変更します。
https://k96mz.com/unvt/
mbtilesファイルを持ってくる
職場サーバのcoesite3レポジトリから複数個のmbtilesファイルをコピーしてきます。
再度、地図をみてみます。無事に、HTTP/2で表示されました。
Geoportalで表示する
以下のとおり修正して、レイヤをGeoportalに登録できるようにします。
app.use("/unvt/rest/services/esriIF", esriIFRouter);
"tiles": [
"https://k96mz.com/unvt/VT/zxy/UniteStreetMapVector/{z}/{x}/{y}.pbf"
],
"maxLOD": 15, //Map Viewerで表示可能とするため
"sprite": "https://k96mz.com/unvt/sprite-rev/sprite_S",
"glyphs": "https://k96mz.com/unvt/font/{fontstack}/{range}.pbf",
"url": "https://k96mz.com/unvt/rest/services/esriIF/UniteStreetMapVector/VectorTileServer",
node app_reverse.js
として、以下にアクセスします。
https://k96mz.com/unvt/
以下のURLをMap Viewerで読み込んでみます。
https://k96mz.com/unvt/rest/services/esriIF/UniteStreetMapVector/VectorTileServer
レイヤ読み込みが出来ましたが、以下の通り、
Status Code: 401 Unauthorized
となります。
https://k96mz.com/unvt/VT/zxy/UniteStreetMapVector/2/1/1.pbf
は読み込まれているので、ルーティングは問題ないように思います。
Geoportalでのタイル読み込みに関して、
Geoportalの認証と、Azure認証が同時?にある中で、参照するタイルが
https://geoportal.un.org/
以外のタイルを参照することができないのではないかと考えられます。
タイルへのルーティングを追加して実験する
Azure認証がある場合には、タイルへのルーティングが、
https://k96mz.com/unvt/VT/zxy/UniteStreetMapVector/{z}/{x}/{y}.pbf
となっているのが原因かもしれないと考えました。
esriIF.jsにタイルへのルーティングのコードを追加して試してみようかと思いましたが、これはpbfファイルの場合で、mbtilesファイルの場合はVT.jsを使用する必要があるので、どうしたら良いかよく分かりませんでした。
ひとまず、index.jsonにおいて、tilesに/rest/servicesをつけてました。
さらに、app_reverse_restservices.jsというファイルを作り、以下の設定としました。
app.use("/unvt/rest/services/VT", VTRouter);
しかし、結果はおなじく、レイヤ読み込みが出来ましたが、Status Code: 401 Unauthorized
が返ってきて、タイルが読み込めませんでした。
まとめ
レンタルサーバでcoesite3レポジトリを利用してみました。MySQLを使用してユーザ認証がうまくいくことが確認されました。
リバースプロキシなしだと、index.jsを修正しないとエラーが発生することが分かりました。リバースプロキシを設定することで、うまくいったので、本番環境でもリバースプロキシを利用したほうが確実な気がします。
地図表示については、Geoportalでのタイル読み込みに関して、401エラーが返ってきて表示出来ませんでした。
Reference