Luci的多级用户管理
来源:互联网 发布:琅琊榜出口数据 编辑:程序博客网 时间:2024/05/01 22:54
目录
- 目录
- Luci的多级用户管理
- 实现方法
- indexlua
- dispatcherlua
- servicectllua
- controllermultiUserlua
- modelcbimultiUserlua
- 防止用户删除本用户操作cbilua
- 思路
- 想法
- 实现方法
Luci的多级用户管理
Openwrt的web管理是用luci来实现的,但是luci本身不支持多级用户管理,并实现不同用户显示不同的界面。因为工作需要所以花了点时间把这个功能完成了。
实现方法
看了网上的一些文档,基本实现的都是把root改成别的用户登录,但是都没有实现多级用户的管理。根据这些文档,自己又做了些更改,主要更改的文件有:
/user/lib/lua/luci/controller/admin/index.lua/user/lib/lua/luci/dispatcher.lua/user/lib/lua/luci/controller/admin/servicectl.lua
添加的文件有:
/user/lib/lua/luci/model/cbi/multiUser.lua/user/lib/lua/luci/controller/multiUser.lua
index.lua
function index()+ local fs = require "nixio.fs"+ local UCI = require("luci.model.uci")+ local uci = UCI.cursor()+ local multiUser = { }+ local root = node() if not root.target then root.target = alias("admin")@@ -14,7 +19,19 @@ function index() page.target = firstchild() page.title = _("Administration") page.order = 10- page.sysauth = "root"+ page.sysauth = { "root" }+ if fs.access("/etc/config/multiUser") then+ multiUser = uci:get_all("multiUser")+ for k, v in pairs(multiUser) do+ if type(v) == "table" then+ for j, l in pairs(v) do+ if j == "user" then+ table.insert(page.sysauth, l)+ end+ end+ end+ end+ end
- page.sysauth的属性是整个页面需要验证的的用户名,当登录的用户名不存在这个表里面,那么luci将进入一个空的界面。
- uci:get_all(“multiUser”)是获取/etc/config/multiUser下的配置在uci缓存里面的内容,并以表的形式放入到multiUser变量里面。
注:这个函数获是用uci方式获取的,所以表的结果并不一定等于配置文件的内容。通过uci set命令可以设置配置文件让结果不相等。所以luci界面上应该禁止删除本用户,防止出现删除后配置文件还没保存,但是已经登录不上去的情况,这个下面的代码会有说到 - 功能说明:根据multiUser的配置文件获取所有用户配置的用户名然后追加到page.syauth表里面,让luci的系统验证支持这些用户名。
dispatcher.lua
@@ -108,20 +108,86 @@ end function authenticator.htmlauth(validator, accs, default) local user = http.formvalue("luci_username") local pass = http.formvalue("luci_password")+ local user_table = ""+ local pass_table = ""+ local level_table = ""+ local fs = require "nixio.fs"+ local UCI = require("luci.model.uci")+ local uci = UCI.cursor()+ local multiUser = { }+ local file=io.open("/var/luci/shadow","w")+ + if fs.access("/etc/config/multiUser") then+ multiUser = uci:get_all("multiUser")+ for k, v in pairs(multiUser) do+ if type(v) == "table" then+ user_table = ""+ pass_table = ""+ level_talbe = ""+ for j, l in pairs(v) do+ if j == "user" then+ user_table = l+ end+ if j == "pwd" then+ pass_table = l+ end+ if j == "level" then+ level_table = l+ end+ end+ if user_table == user and pass_table == pass then+ if not file then+ luci.util.exec("mkdir -p /var/luci/")+ file = io.open("/var/luci/shadow", "w")+ end+ file:write(user)+ file:write("\n")+ file:write(level_table)+ file:close()+ return user+ end+ end+ end+ end- if user and validator(user, pass) then+ --[[ if user and validator(user, pass) then file=io.open("/tmp/current_user","w") file:write(user) file:close() return user- end+ end ]]--
- 改变用户名密码的判断方式,如果仍想用系统的用户名密码,那么需要写一个程序在multiUser配置变化时后执行adduer命令,把用户名添加到系统即可
- 把当前用户写到文件里面的作用是在luci中防止本用户删除本用户的操作
if context.urltoken.stok then context.urltoken.stok = nil@@ -343,6 +408,62 @@ function dispatch(request) authen = function() return eu end end end+ --[[+ context.tree.nodes.admin.nodes.status.title=""+ context.tree.nodes.admin.nodes.system.title=""+ context.tree.nodes.admin.nodes.services.title=""+ context.tree.nodes.admin.nodes.network.title=""+ ]]--+ if level == "1" then+ --context.tree.nodes.admin.nodes.services.title=""+ elseif level == "2" then+ for j, k in pairs(context.tree.nodes.admin.nodes.network.nodes) do+ if j == "wireless"+ or j == "hosts"+ --or j == "firewall"+ or j == "diagnostics"+ or j == "dhcp"+ or j == "routes"+ then+ k.title=""+ k.leaf=true+ k.target=""+ end+ end+ context.tree.nodes.admin.nodes.services.title=""+ context.tree.nodes.admin.nodes.services.leaf=true+ for j, k in pairs(context.tree.nodes.admin.nodes.system.nodes) do+ if j == "admin"+ or j == "system"+ or j == "packages"+ or j == "startup"+ or j == "leds"+ or j == "multiUser"+ or j == "crontab"+ or j == "fstab"+ then+ k.title=""+ k.leaf=true+ k.target=""+ end+ end+ for j, k in pairs(context.tree.nodes.admin.nodes.status.nodes) do+ if j == "dmesg"+ or j == "routes"+ or j == "iptables"+ or j == "realtime"+ or j == "syslog"+ or j == "processes"+ then+ k.title=""+ k.leaf=true+ k.target=""+ end+ end+ end
- 隐藏页面的关键是把page.target 和page.title属性写成空,page.leaf属性官方文档上写的是防止更新的意思,我也没怎么搞明白,如果有人明白的请留言给我。
- 注释的内容显示了所有能显示的page的表。
servicectl.lua
module("luci.controller.admin.servicectl", package.seeall) function index()- entry({"servicectl"}, alias("servicectl", "status")).sysauth = "root"+ entry({"servicectl"}, alias("servicectl", "status"))
- 因为是多级用户管理,所以用户名不是单个。只需要顶层的表admin的sysauth属性是正确的即可。
controller/multiUser.lua
@@ -0,0 +1,12 @@+module("luci.controller.multiUser", package.seeall)++++function index()+ local fs = require "nixio.fs"+ if fs.access("/etc/config/multiUser") then+ entry({"admin", "system","multiUser"}, cbi("multiUser"), translate("Multi-leve User Configuration"), 12)+ end++end+
model/cbi/multiUser.lua
+--m = Map("multiUser", translate("<abbr title=\"Light Emitting Diode\">LED</abbr> Configuration"), translate("Customizes the behaviour of the device <abbr title=\"Light Emitting+m = Map("multiUser", translate("Multi-leve User Configuration"), translate("Multi-level user management"))++s = m:section(TypedSection, "multiUser", "")+s.anonymous = true+s.addremove = true+s.template = "cbi/tblsection"++user = s:option(Value, "user", translate("Username"))+user.rmempt=true++pwd = s:option(Value, "pwd", translate("Password"))+pwd.password = true+pwd.rmempt=true++level = s:option(ListValue, "level", translate("Level"))+level:value("1", translate("Administrator"))+level:value("2", translate("Ordinary User"))++function m.before_save(map)+ local x = luci.http.formvalue(section)+ local name = {}+ local i = 0+ for k, v in pairs(x) do+ if string.find(k, "multiUser.+user") ~= nil then+ local t = type(v)+ if t ~= 'table' then+ name[i] = v+ i = i + 1+ end+ end+ end+ for k, v in pairs(name) do+ for k_inter, v_inter in pairs(name) do+ if k ~= k_inter then+ if v == v_inter then+ m.message = translate("User name is conflict!")+ return false+ end+ end+ end+ end+ return true++end++++return m
- s.template里面指定了显示的格式为用户名和密码同一列的格式
- s.addremove=true显示了添加和删除按钮
- s.anonymous=true是隐藏了标题
- m.before_save(map)这个函数需要在cbi.lua声明使用,代码如下:
Node.parse(self, ...) if self.save then + local run_hooks_return = +self:run_hooks("before_save")+ if run_hooks_return ~= nil then+ if run_hooks_return == false then + return+ end + end
防止用户删除本用户操作:cbi.lua
@@ -1156,16 +1165,33 @@ function TypedSection.depends(self, option, value) end function TypedSection.parse(self, novld)+ local fs = require "nixio.fs"+ local UCI = require("luci.model.uci")+ local uci = UCI.cursor()+ local multiUser = { }++ if fs.access("/etc/config/multiUser") then+ multiUser = uci:get_all("multiUser")+ end if self.addremove then -- Remove local crval = REMOVE_PREFIX .. self.config local name = self.map:formvaluetable(crval) for k,v in pairs(name) do+ local deluser = ""+ local cuser = luci.util.exec("cat /tmp/luci/shadow | head -1 | tr -d '\n' 2> /dev/null") if k:sub(-2) == ".x" then k = k:sub(1, #k - 2) end+ for a, b in pairs(multiUser) do+ if a == k then+ deluser = b.user+ end+ end if self:cfgvalue(k) and self:checkscope(k) then- self:remove(k)+ if deluser ~= cuser then+ self:remove(k)+ end end end end
- 禁止删除本用户的操作,当点击删除TypedSection类型的section的按钮时,会执行这个函数。
思路
整体的思路很简单,就是当用户登录时判断这个用户的等级,如果等级为2,那么把一些页面的3个属性值改掉。关键点:动态的实现系统sysauth的值动态改变
想法
初次写博客,如有错误请指正。
1 0
- Luci的多级用户管理
- OpenWrt LuCI多级用户设计
- openwrt luci管理的Web界面实例
- luci+ricci集群管理
- OpenWrt Luci更换登陆用户
- 访问控制-代码的多级管理
- luci框架的简介
- luci框架的简介
- ubuntu LuCI 的搭建
- luci的context
- Luci的工作流程
- luci
- Luci
- LuCI - 网页用户配置界面开发
- openwrt ---Luci - 网页用户配置界面开发
- openwrt web管理luci界面修改
- openwrt web管理luci界面修改
- openwrt web管理luci界面修改
- 开源GIS_JDK的安装
- ListView嵌套GridView
- [转]Troubleshooting Error 18456
- Scrollview嵌套listView出现listItem.measure(0, 0)报空指针异常原因
- iOS-tableView联动你就看我
- Luci的多级用户管理
- Codeforces Round #219 (Div. 2 )-----贪心--思维
- Java中Map的遍历
- 正则表达式 简单小记
- web 网站优化分析
- js常用校验
- 领域模型的架构问题
- 出版商后台登陆登出的分析
- 后端线上服务监控与报警方案