上官雨泽

心灵驿站,与你分享成长

Luci多级用户管理

目录

目录 Luci的多级用户管理 实现方法 indexlua dispatcherlua servicectllua controllermultiUserlua modelcbimultiUserlua 防止用户删除本用户操作cbilua 思路 想法

Luci的多级用户管理

Openwrt的web管理是用luci来实现的,但是luci本身不支持多级用户管理,并实现不同用户显示不同的界面。因为工作需要所以花了点时间把这个功能完成了。

实现方法

1
看了网上的一些文档,基本实现的都是把root改成别的用户登录,但是都没有实现多级用户的管理。根据这些文档,自己又做了些更改,主要更改的文件有:
1
2
3
/user/lib/lua/luci/controller/admin/index.lua
/user/lib/lua/luci/dispatcher.lua
/user/lib/lua/luci/controller/admin/servicectl.lua
1
添加的文件有:
1
2
/user/lib/lua/luci/model/cbi/multiUser.lua
/user/lib/lua/luci/controller/multiUser.lua

index.lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
@@ -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中防止本用户删除本用户的操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
        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

1
2
3
4
5
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

1
2
3
4
5
6
7
8
9
10
11
12
13
@@ -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

1
2
3
4
5
6
7
8
9
10
11
12
+--m = Map("multiUser", translate("
 
 
s.template里面指定了显示的格式为用户名和密码同一列的格式
s.addremove=true显示了添加和删除按钮
s.anonymous=true是隐藏了标题
m.before_save(map)这个函数需要在cbi.lua声明使用,代码如下:
 
 
 
 
</abbr>
1
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 </abbr>

防止用户删除本用户操作:cbi.lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@@ -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
</abbr>
禁止删除本用户的操作,当点击删除TypedSection类型的section的按钮时,会执行这个函数。

思路

1
2
整体的思路很简单,就是当用户登录时判断这个用户的等级,如果等级为2,那么把一些页面的3个属性值改掉。
关键点:动态的实现系统sysauth的值动态改变</abbr>
阅读更多
文章标签: luci多级用户管理
个人分类: openwrt
想对作者说点什么? 我来说一句

OpenWRT_LuCI

2014年09月24日 775KB 下载

luci开发使用手册

2012年02月03日 160KB 下载

OpenWRT之旅-LuCI探究

2016年11月22日 165KB 下载

没有更多推荐了,返回首页

不良信息举报

Luci多级用户管理

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭