shinymanager
パッケージはshinyアプリにログインの仕組みを組み込むためのライブラリです。
shinymanager
をデータベースを利用して用いる場合には、keyring
パッケージが必要となりますので、keyring
パッケージもインストールします。
install.packages("shinymanager")
install.packages("keyring")
shinymanager
でパスワードを設定する方法は主に2つあります。
- Rスクリプト上にデータフレームとしてパスワードを設定して用いる
- データベースを用いてパスワードを管理する
まずは1について説明し、次に2について説明します。
データフレームでパスワードを設定する
データフレームでパスワードを設定する場合には、user
、password
、start
、expire
、admin
、comment
をadmin
を除いてそれぞれ文字列としたデータフレームを作成します。必須なのはuser
とpassword
です。このデータフレームを後ほどserver
側で呼び出し、パスワードとして設定します。
credentials <- data.frame(
user = c("shiny", "shinymanager"), # ユーザー名
password = c("azerty", "12345"), # パスワード
start = c("2019-04-15"),
expire = c(NA, "2026-12-31"),
admin = c(FALSE, TRUE),
comment = "Simple and secure authentification mechanism
for single ‘Shiny’ applications.",
stringsAsFactors = FALSE
)
credentials
## user password start expire admin comment
## 1 shiny azerty 2019-04-15 <NA> FALSE Simple and secure authentification mechanism \n for single ‘Shiny’ applications.
## 2 shinymanager 12345 2019-04-15 2026-12-31 TRUE Simple and secure authentification mechanism \n for single ‘Shiny’ applications.
次に、ui
とserver
にログインページに必要となるものを付け加えます。このプロセスは簡単で、ui
はsequre_app
の引数とするだけ、server
にはres_auth
という変数を設定するだけです。
ui <- fluidPage(...)
ui <- secure_app(ui, language="ja") # ログインページの表示
server <- function(input, output, session) {
res_auth <- secure_server( # 認証をおこなう部分
check_credentials = check_credentials(credentials)
)
...
}
shinyApp(ui, server)
設定してapp.R
を起動すると、以下のようにログインページが表示されます。sequre_app
のヘルプには日本語が使えるような記載はありませんが、ver.1.0.410から日本語が使用できるようになっています。フォントと記載がやや不自然なような気もしますので、英語のままでよければlanguage
を引数として設定しなければよいでしょう。
データベースを用いてパスワードを設定する
上記のように、パスワードを直書きすると簡単にログイン機構をshinyに追加することができます。また、データベースを用いてパスワードを管理することもできます。データベースを用いてパスワードを管理するためには、まずsqliteを用いてデータベースファイルを作成します(sqlite以外のデータベースを用いることもできます)。
credentials <- data.frame(
user = c("shiny", "shinymanager"),
password = c("azerty", "12345"),
admin = c(FALSE, TRUE),
stringsAsFactors = FALSE
)
# データベースのキーを設定する
library(keyring)
if(keyring_list() |> _$keyring |> str_detect("foo") |> sum() < 1){
keyring_create("foo", password="obiwankenobi")
}
key_set_with_value("R-shinymanager-key", "obiwankenobi", password = "obiwankenobi", keyring="foo")
# データベースを作成する
create_db(
credentials_data = credentials,
sqlite_path = "password.sqlite",
passphrase = key_get("R-shinymanager-key", "obiwankenobi")
# passphrase = "passphrase_wihtout_keyring"
)
データベースのキーとパスワードの設定にはkeyring
パッケージを用います。keyring
については以下のページに説明があります。OS側の仕組みを用いてパスワードを隠蔽することができるパッケージです。
事前にkeyring_create
関数でキーとして保存するkeyring
というものを設定しておきます。次に、keyring
でキーとパスワードを設定するには、key_set
関数を用います。key_set
関数ではポップアップするUIでパスワードを設定することになります。UIではなくパスワードを直書きする場合には、key_set_with_value
関数を用います。パスワードを管理するデータベースはcreate_db
関数で作成します。create_db
関数の引数として、パスワードをデータフレームとして設定したcredentials_data
、データベースのパスであるsqlite_path
(ファイル名だけの時はワーキングディレクトリに作成)、キーとパスワードを設定するpassphrase
の3つです。passphrase = "passphrase_wihtout_keyring"
を設定するとkeyring
無しでのデータベースも利用できます。
データベースが準備できたら、app.Rに認証機構を付け加えます。sequre_app
関数内でenable_admin=TRUE
と設定すると、管理者権限を与えたユーザーではAdministration modeを利用することができます。server側では、sequre_server
の引数を以下のように設定します。データベースのパスは相対パスではなく、絶対パスで書く必要があります。
ui <- fluidPage(...)
ui <- secure_app(ui, enable_admin = TRUE, language="ja") # ログインページの表示
server <- function(input, output, session) {
res_auth <- secure_server(
check_credentials = check_credentials(
"path/password.sqlite", # データベースまでの絶対パス
passphrase = key_get("R-shinymanager-key", "obiwankenobi", keyring = "foo")
# passphrase = "passphrase_wihtout_keyring"
)
)
...
}
上のapp.R
を実行すると以下のイメージのように、アプリの右下から管理者ページに入ることができます。管理者ページではユーザー・パスワードの管理ができます。
Dockerでshinymanagerを動かす
shinyアプリをデプロイするため、Dockerでshinymanager
が動くようにします。keyring
のインストールには上記のkeyringの記事に記載の通り、libssl-dev
、libsodium-dev
、libsecret-1-dev
の3つが必要です。この3つを加えてDockerfile
を準備します。
# get shiny server plus tidyverse packages image
FROM rocker/shiny-verse:latest
# system libraries of general use
RUN apt-get update && apt-get install -y \
curl \
sudo \
pandoc \
pandoc-citeproc \
libcurl4-gnutls-dev \
libcairo2-dev \
libxt-dev \
libssl-dev \
libssh2-1-dev\
libssl3 \
libsecret-1-dev \
libsodium-dev \
## clean up
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/ \
&& rm -rf /tmp/downloaded_packages/ /tmp/*.rds
# install R packages required
# (change it depending on the packages you need)
RUN R -e "install.packages('shiny')"
RUN R -e "install.packages('shinymanager')"
RUN R -e "install.packages('keyring')"
# clean up
RUN rm -rf /tmp/downloaded_packages/ /tmp/*.rds
# Copy configuration files into the Docker image
COPY shiny-server.conf /etc/shiny-server/shiny-server.conf
# Copy shiny app into the Docker image
COPY app /srv/shiny-server/
RUN rm /srv/shiny-server/index.html
# Make the ShinyApp available at port 3838
EXPOSE 5000
# Copy shiny app execution file into the Docker image
COPY shiny-server.sh /usr/bin/shiny-server.sh
RUN ["chmod", "+x", "/usr/bin/shiny-server.sh"]
USER shiny
CMD ["/usr/bin/shiny-server"]
パスワードを保存したデータベースファイルはapp
フォルダ内に保存し、/srv/shiny-server/
にコピーしています。ですので、app.R
のserver
内のデータベースの絶対パスは/srv/shiny-server/password.sqlite
とします。
library(shiny)
library(tidyverse)
library(shinymanager)
library(keyring)
if(keyring_list() |> _$keyring |> str_detect("foo") |> sum() < 1){
keyring_create("foo", password="obiwankenobi")
}
key_set_with_value("R-shinymanager-key", "obiwankenobi", "obiwankenobi", keyring="foo")
...
server <- function(input, output, session) {
res_auth <- secure_server(
check_credentials = check_credentials(
"/srv/shiny-server/password.sqlite", # データベースまでの絶対パス
passphrase = key_get("R-shinymanager-key", "obiwankenobi", keyring = "foo")
# passphrase = "passphrase_wihtout_keyring"
)
)
...
}
app.R
内でkeyring
を設定しているのはイケてないので、別途Rファイルを準備し、Dockerfile
内で実行後、Rファイルを削除するような形の方が良いでしょう。フォルダ構造は以下のような形とします。
shinymanager_trial
|- app
| |- app.R
| |- password.sqlite
| - Dockerfile
| - shiny-server.conf
| - shiny-server.sh
この形でdocker build
→ docker run
とすることで、ログインページ付きのshinyをDockerから走らせることができます。