luci-base: remove security token from urls
Now that sensitive urls require post requests and only accept them if a valid security token is sent along the request, we can drop the global random url token to improve LuCI usability. The main improvement is the ability to use multiple tabs with the same login session, but also deep linking to specific urls without the need for another login becomes feasible, e.g. for documentation purposes. Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
This commit is contained in:
parent
f23f7b8751
commit
86326e0def
1 changed files with 14 additions and 38 deletions
|
@ -113,24 +113,11 @@ function authenticator.htmlauth(validator, accs, default)
|
||||||
return user
|
return user
|
||||||
end
|
end
|
||||||
|
|
||||||
if context.urltoken.stok then
|
require("luci.i18n")
|
||||||
context.urltoken.stok = nil
|
require("luci.template")
|
||||||
|
context.path = {}
|
||||||
local cookie = 'sysauth=%s; expires=%s; path=%s/' %{
|
http.status(403, "Forbidden")
|
||||||
http.getcookie('sysauth') or 'x',
|
luci.template.render("sysauth", {duser=default, fuser=user})
|
||||||
'Thu, 01 Jan 1970 01:00:00 GMT',
|
|
||||||
build_url()
|
|
||||||
}
|
|
||||||
|
|
||||||
http.header("Set-Cookie", cookie)
|
|
||||||
http.redirect(build_url())
|
|
||||||
else
|
|
||||||
require("luci.i18n")
|
|
||||||
require("luci.template")
|
|
||||||
context.path = {}
|
|
||||||
http.status(403, "Forbidden")
|
|
||||||
luci.template.render("sysauth", {duser=default, fuser=user})
|
|
||||||
end
|
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
@ -151,18 +138,8 @@ function httpdispatch(request, prefix)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local tokensok = true
|
|
||||||
for node in pathinfo:gmatch("[^/]+") do
|
for node in pathinfo:gmatch("[^/]+") do
|
||||||
local tkey, tval
|
r[#r+1] = node
|
||||||
if tokensok then
|
|
||||||
tkey, tval = node:match(";(%w+)=([a-fA-F0-9]*)")
|
|
||||||
end
|
|
||||||
if tkey then
|
|
||||||
context.urltoken[tkey] = tval
|
|
||||||
else
|
|
||||||
tokensok = false
|
|
||||||
r[#r+1] = node
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local stat, err = util.coxpcall(function()
|
local stat, err = util.coxpcall(function()
|
||||||
|
@ -311,13 +288,14 @@ function dispatch(request)
|
||||||
resource = luci.config.main.resourcebase;
|
resource = luci.config.main.resourcebase;
|
||||||
ifattr = function(...) return _ifattr(...) end;
|
ifattr = function(...) return _ifattr(...) end;
|
||||||
attr = function(...) return _ifattr(true, ...) end;
|
attr = function(...) return _ifattr(true, ...) end;
|
||||||
token = ctx.urltoken.stok;
|
|
||||||
url = build_url;
|
url = build_url;
|
||||||
}, {__index=function(table, key)
|
}, {__index=function(table, key)
|
||||||
if key == "controller" then
|
if key == "controller" then
|
||||||
return build_url()
|
return build_url()
|
||||||
elseif key == "REQUEST_URI" then
|
elseif key == "REQUEST_URI" then
|
||||||
return build_url(unpack(ctx.requestpath))
|
return build_url(unpack(ctx.requestpath))
|
||||||
|
elseif key == "token" then
|
||||||
|
return ctx.authtoken
|
||||||
else
|
else
|
||||||
return rawget(table, key) or _G[key]
|
return rawget(table, key) or _G[key]
|
||||||
end
|
end
|
||||||
|
@ -340,20 +318,17 @@ function dispatch(request)
|
||||||
local def = (type(track.sysauth) == "string") and track.sysauth
|
local def = (type(track.sysauth) == "string") and track.sysauth
|
||||||
local accs = def and {track.sysauth} or track.sysauth
|
local accs = def and {track.sysauth} or track.sysauth
|
||||||
local sess = ctx.authsession
|
local sess = ctx.authsession
|
||||||
local verifytoken = false
|
|
||||||
if not sess then
|
if not sess then
|
||||||
sess = http.getcookie("sysauth")
|
sess = http.getcookie("sysauth")
|
||||||
sess = sess and sess:match("^[a-f0-9]*$")
|
sess = sess and sess:match("^[a-f0-9]*$")
|
||||||
verifytoken = true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local sdat = (util.ubus("session", "get", { ubus_rpc_session = sess }) or { }).values
|
local sdat = (util.ubus("session", "get", { ubus_rpc_session = sess }) or { }).values
|
||||||
local user
|
local user, token
|
||||||
|
|
||||||
if sdat then
|
if sdat then
|
||||||
if not verifytoken or ctx.urltoken.stok == sdat.token then
|
user = sdat.user
|
||||||
user = sdat.user
|
token = sdat.token
|
||||||
end
|
|
||||||
else
|
else
|
||||||
local eu = http.getenv("HTTP_AUTH_USER")
|
local eu = http.getenv("HTTP_AUTH_USER")
|
||||||
local ep = http.getenv("HTTP_AUTH_PASS")
|
local ep = http.getenv("HTTP_AUTH_PASS")
|
||||||
|
@ -390,8 +365,8 @@ function dispatch(request)
|
||||||
sess, build_url()
|
sess, build_url()
|
||||||
})
|
})
|
||||||
|
|
||||||
ctx.urltoken.stok = token
|
|
||||||
ctx.authsession = sess
|
ctx.authsession = sess
|
||||||
|
ctx.authtoken = token
|
||||||
ctx.authuser = user
|
ctx.authuser = user
|
||||||
|
|
||||||
http.redirect(build_url(unpack(ctx.requestpath)))
|
http.redirect(build_url(unpack(ctx.requestpath)))
|
||||||
|
@ -403,6 +378,7 @@ function dispatch(request)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
ctx.authsession = sess
|
ctx.authsession = sess
|
||||||
|
ctx.authtoken = token
|
||||||
ctx.authuser = user
|
ctx.authuser = user
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -414,7 +390,7 @@ function dispatch(request)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if http.formvalue("token") ~= ctx.urltoken.stok then
|
if http.formvalue("token") ~= ctx.authtoken then
|
||||||
http.status(403, "Forbidden")
|
http.status(403, "Forbidden")
|
||||||
luci.template.render("csrftoken")
|
luci.template.render("csrftoken")
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in a new issue