LoginSignup
1
0

shinymanagerパッケージを使ってログインページを持つアプリを作成する

Last updated at Posted at 2024-03-17

shinymanagerパッケージはshinyアプリにログインの仕組みを組み込むためのライブラリです。

shinymanagerをデータベースを利用して用いる場合には、keyringパッケージが必要となりますので、keyringパッケージもインストールします。

install.packages("shinymanager")
install.packages("keyring")

shinymanagerでパスワードを設定する方法は主に2つあります。

  1. Rスクリプト上にデータフレームとしてパスワードを設定して用いる
  2. データベースを用いてパスワードを管理する

まずは1について説明し、次に2について説明します。

データフレームでパスワードを設定する

データフレームでパスワードを設定する場合には、userpasswordstartexpireadmincommentadminを除いてそれぞれ文字列としたデータフレームを作成します。必須なのはuserpasswordです。このデータフレームを後ほど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.

次に、uiserverにログインページに必要となるものを付け加えます。このプロセスは簡単で、uisequre_appの引数とするだけ、serverにはres_authという変数を設定するだけです。

app.R
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を引数として設定しなければよいでしょう。

shinymanager_loginimage.png

データベースを用いてパスワードを設定する

上記のように、パスワードを直書きすると簡単にログイン機構を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パッケージで認証情報を管理する

事前に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の引数を以下のように設定します。データベースのパスは相対パスではなく、絶対パスで書く必要があります。

app.R
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を実行すると以下のイメージのように、アプリの右下から管理者ページに入ることができます。管理者ページではユーザー・パスワードの管理ができます。

adminmode.png

adminmode_1.png

Dockerでshinymanagerを動かす

shinyアプリをデプロイするため、Dockerでshinymanagerが動くようにします。keyringのインストールには上記のkeyringの記事に記載の通り、libssl-devlibsodium-devlibsecret-1-devの3つが必要です。この3つを加えてDockerfileを準備します。

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.Rserver内のデータベースの絶対パスは/srv/shiny-server/password.sqliteとします。

app.R
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 builddocker runとすることで、ログインページ付きのshinyをDockerから走らせることができます。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0