分享 Shiny 的用户和角色权限管理方案
楚新元 / 2023-03-09
最近做了一个自动生成制式化 Word 文档的 Shiny app1,顺便用 shinyauthr 包做了一个用户登录界面,但是要实现用户修改密码的功能困扰了我好久,主要问题是 session 一旦起来后只修改配置文件里的用户密码是不行了,因为内存中的密码没有变,后来我终于想到了解决方案,把读取配置文件放在 server function 里面,每次修改配置文件密码后立马通过 session$reload()
重启会话,这样就会重新读取配置文件的用户信息,从而刷新内存中的密码信息,问题得到解决。
用户登录的问题解决了,现在要给不同的用户分配不同的访问权限。首先生成配置文件,这个配置文件包括所有用户账号、密码、有效期和访问权限信息。这个可以用如下代码生成:
# 加载 R 包
library(RSQLite)
# 连接数据库
con = dbConnect(SQLite(), "./config/config.sqlite")
# 创建用户信息
user_group = data.frame(
name = c("管理员", "张三", "李四", "王五", "赵六"),
user = c("admin", "user1", "user2", "user3", "user4"),
password = c(
"admin", "666666", "666666", "666666", "666666"
),
permissions = c(
"admin", "standard", "standard", "standard", "standard"
),
expire = c(
"9999-12-31", "2100-12-31", "2100-12-31",
"2100-12-31", "2023-12-31"
),
page1 = c("yes", "yes", "no", "yes", "yes"),
page2 = c("yes", "no", "yes", "yes", "yes")
)
# 用户信息写入到配置文件
dbWriteTable(
conn = con,
name = "user_group",
value = user_group,
overwrite = TRUE
)
# 关闭连接
dbDisconnect(config)
配置文件里包含 5 个用户,代表了 5 种典型的情况:
- 管理员:具有所有的访问权限,账户永不过期。
- 张三:只有访问 page1 页面的权限,不能访问 page2。
- 李四:只有访问 page2 页面的权限,不能访问 page2。
- 王五:具有访问 page1 和 page2 页面的权限。但是他和管理员账户相比没有导入和导出配置文件的权限。
- 赵六:具有访问 page1 和 page2 页面的权限。和王五权限相同,但是账号处于过期状态。
Shiny app 在获取配置文件的用户信息后,只需要在每个菜单前用 if()
进行判断即可,下面是控制用户菜单访问权限的处理逻辑:
shinyServer(function(input, output, session) {
# 打开配置文件
config = dbConnect(SQLite(), "./config/config.sqlite")
# 查询用户组信息
user_group = dbGetQuery(config, "select * from user_group")
# 关闭数据库
dbDisconnect(config)
#-------------------------------------------------------------------------
# 定义凭证信息
credentials = loginServer(
id = "login",
data = user_group,
user_col = user,
pwd_col = password,
log_out = reactive(logout_init())
)
# 用户退出
logout_init = logoutServer(
id = "logout",
active = reactive(credentials()$user_auth)
)
# 捕获登录用户信息
user_info = reactive({
credentials()$info
})
# 判断用户状态
my_condition = reactive({
all(
credentials()$user_auth,
as.Date(user_info()$expire) >= Sys.Date()
)
})
#-------------------------------------------------------------------------
# 账号密码正确且没有过期时,登录后后打开侧边栏
observe({
if(my_condition()) {
removeClass(
selector = "body",
class = "sidebar-collapse")
} else {
addClass(
selector = "body",
class = "sidebar-collapse")
}
})
#-------------------------------------------------------------------------
# 设置侧边菜单栏 UI
output$sidebar = renderMenu({
req(my_condition())
sidebarMenu(
id = "tabs",
if (user_info()$page1 == "yes") {
menuItem(
"图示页面",
tabName = "page1",
icon = icon("chart-simple")
)
},
if (user_info()$page2 == "yes") {
menuItem(
"报表页面",
tabName = "page2",
icon = icon("table")
)
},
if (user_info()$permissions == "admin") {
menuItem(
"参数配置",
tabName = "setting",
icon = icon("wrench")
)
},
menuItem(
"修改密码",
tabName = "resetpasswd",
icon = icon("key")
),
menuItem(
"软件说明",
tabName = "about",
icon = icon("podcast")
)
)
})
})
下面是一个带用户和角色权限管理功能的 Shiny app 示例:
-
需要体验的读者可以给我发邮件,我需要先配置用户登陆信息。 ↩︎