Implement URL tokens
Add basic XSRF protection
This commit is contained in:
parent
509a3daadb
commit
271c53a4af
2 changed files with 83 additions and 20 deletions
|
@ -47,7 +47,7 @@ local fi
|
||||||
-- @param ... Virtual path
|
-- @param ... Virtual path
|
||||||
-- @return Relative URL
|
-- @return Relative URL
|
||||||
function build_url(...)
|
function build_url(...)
|
||||||
return luci.http.getenv("SCRIPT_NAME") .. "/" .. table.concat(arg, "/")
|
return context.scriptname .. "/" .. table.concat(arg, "/")
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Send a 404 error code and render the "error404" template if available.
|
--- Send a 404 error code and render the "error404" template if available.
|
||||||
|
@ -123,6 +123,8 @@ function dispatch(request)
|
||||||
--context._disable_memtrace = require "luci.debug".trap_memtrace()
|
--context._disable_memtrace = require "luci.debug".trap_memtrace()
|
||||||
local ctx = context
|
local ctx = context
|
||||||
ctx.path = request
|
ctx.path = request
|
||||||
|
ctx.scriptname = luci.http.getenv("SCRIPT_NAME") or ""
|
||||||
|
ctx.urltoken = ctx.urltoken or {}
|
||||||
|
|
||||||
require "luci.i18n".setlanguage(require "luci.config".main.lang)
|
require "luci.i18n".setlanguage(require "luci.config".main.lang)
|
||||||
|
|
||||||
|
@ -137,8 +139,21 @@ function dispatch(request)
|
||||||
ctx.args = args
|
ctx.args = args
|
||||||
ctx.requestargs = ctx.requestargs or args
|
ctx.requestargs = ctx.requestargs or args
|
||||||
local n
|
local n
|
||||||
|
local t = true
|
||||||
|
local token = ctx.urltoken
|
||||||
|
local preq = {}
|
||||||
|
|
||||||
for i, s in ipairs(request) do
|
for i, s in ipairs(request) do
|
||||||
|
local tkey, tval
|
||||||
|
if t then
|
||||||
|
tkey, tval = s:match(";(%w+)=(.*)")
|
||||||
|
end
|
||||||
|
|
||||||
|
if tkey then
|
||||||
|
token[tkey] = tval
|
||||||
|
else
|
||||||
|
t = false
|
||||||
|
preq[#preq+1] = s
|
||||||
c = c.nodes[s]
|
c = c.nodes[s]
|
||||||
n = i
|
n = i
|
||||||
if not c then
|
if not c then
|
||||||
|
@ -151,6 +166,7 @@ function dispatch(request)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if c and c.leaf then
|
if c and c.leaf then
|
||||||
for j=n+1, #request do
|
for j=n+1, #request do
|
||||||
|
@ -158,6 +174,13 @@ function dispatch(request)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
for k, v in pairs(token) do
|
||||||
|
ctx.scriptname = ctx.scriptname .. "/;" .. k .. "=" ..
|
||||||
|
http.urlencode(v)
|
||||||
|
end
|
||||||
|
|
||||||
|
ctx.path = preq
|
||||||
|
|
||||||
if track.i18n then
|
if track.i18n then
|
||||||
require("luci.i18n").loadc(track.i18n)
|
require("luci.i18n").loadc(track.i18n)
|
||||||
end
|
end
|
||||||
|
@ -177,17 +200,23 @@ function dispatch(request)
|
||||||
assert(media, "No valid theme found")
|
assert(media, "No valid theme found")
|
||||||
end
|
end
|
||||||
|
|
||||||
local viewns = setmetatable({}, {__index=_G})
|
local viewns = setmetatable({}, {__index=function(table, key)
|
||||||
|
if key == "controller" then
|
||||||
|
return ctx.scriptname
|
||||||
|
elseif key == "REQUEST_URI" then
|
||||||
|
return ctx.scriptname .. "/" .. table.concat(ctx.requested, "/")
|
||||||
|
else
|
||||||
|
return rawget(table, key) or _G[key]
|
||||||
|
end
|
||||||
|
end})
|
||||||
tpl.context.viewns = viewns
|
tpl.context.viewns = viewns
|
||||||
viewns.write = luci.http.write
|
viewns.write = luci.http.write
|
||||||
viewns.include = function(name) tpl.Template(name):render(getfenv(2)) end
|
viewns.include = function(name) tpl.Template(name):render(getfenv(2)) end
|
||||||
viewns.translate = function(...) return require("luci.i18n").translate(...) end
|
viewns.translate = function(...) return require("luci.i18n").translate(...) end
|
||||||
viewns.striptags = util.striptags
|
viewns.striptags = util.striptags
|
||||||
viewns.controller = luci.http.getenv("SCRIPT_NAME")
|
|
||||||
viewns.media = media
|
viewns.media = media
|
||||||
viewns.theme = fs.basename(media)
|
viewns.theme = fs.basename(media)
|
||||||
viewns.resource = luci.config.main.resourcebase
|
viewns.resource = luci.config.main.resourcebase
|
||||||
viewns.REQUEST_URI = (luci.http.getenv("SCRIPT_NAME") or "") .. (luci.http.getenv("PATH_INFO") or "")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
track.dependent = (track.dependent ~= false)
|
track.dependent = (track.dependent ~= false)
|
||||||
|
@ -202,9 +231,22 @@ 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 or luci.http.getcookie("sysauth")
|
local sess = ctx.authsession
|
||||||
|
local verifytoken = true
|
||||||
|
if not sess then
|
||||||
|
sess = luci.http.getcookie("sysauth")
|
||||||
sess = sess and sess:match("^[A-F0-9]+$")
|
sess = sess and sess:match("^[A-F0-9]+$")
|
||||||
local user = sauth.read(sess)
|
end
|
||||||
|
|
||||||
|
local sdat = sauth.read(sess)
|
||||||
|
local user
|
||||||
|
|
||||||
|
if sdat then
|
||||||
|
sdat = loadstring(sdat)()
|
||||||
|
if not verifytoken or ctx.urltoken.stok == sdat.token then
|
||||||
|
user = sdat.user
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if not util.contains(accs, user) then
|
if not util.contains(accs, user) then
|
||||||
if authen then
|
if authen then
|
||||||
|
@ -215,7 +257,13 @@ function dispatch(request)
|
||||||
local sid = sess or luci.sys.uniqueid(16)
|
local sid = sess or luci.sys.uniqueid(16)
|
||||||
luci.http.header("Set-Cookie", "sysauth=" .. sid.."; path=/")
|
luci.http.header("Set-Cookie", "sysauth=" .. sid.."; path=/")
|
||||||
if not sess then
|
if not sess then
|
||||||
sauth.write(sid, user)
|
local token = luci.sys.uniqueid(16)
|
||||||
|
sauth.write(sid, util.get_bytecode({
|
||||||
|
user=user,
|
||||||
|
token=token,
|
||||||
|
secret=luci.sys.uniqueid(16)
|
||||||
|
}))
|
||||||
|
ctx.scriptname = ctx.scriptname .. "/;stok="..token
|
||||||
end
|
end
|
||||||
ctx.authsession = sid
|
ctx.authsession = sid
|
||||||
end
|
end
|
||||||
|
@ -223,6 +271,8 @@ function dispatch(request)
|
||||||
luci.http.status(403, "Forbidden")
|
luci.http.status(403, "Forbidden")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
ctx.authsession = sess
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -52,20 +52,33 @@ function rpc_auth()
|
||||||
local http = require "luci.http"
|
local http = require "luci.http"
|
||||||
local sys = require "luci.sys"
|
local sys = require "luci.sys"
|
||||||
local ltn12 = require "luci.ltn12"
|
local ltn12 = require "luci.ltn12"
|
||||||
|
local util = require "luci.util"
|
||||||
|
|
||||||
local loginstat
|
local loginstat
|
||||||
|
|
||||||
local server = {}
|
local server = {}
|
||||||
server.login = function(user, pass)
|
server.challenge = function(user, pass)
|
||||||
local sid
|
local sid, token, secret
|
||||||
|
|
||||||
if sys.user.checkpasswd(user, pass) then
|
if sys.user.checkpasswd(user, pass) then
|
||||||
sid = sys.uniqueid(16)
|
sid = sys.uniqueid(16)
|
||||||
|
token = sys.uniqueid(16)
|
||||||
|
secret = sys.uniqueid(16)
|
||||||
|
|
||||||
http.header("Set-Cookie", "sysauth=" .. sid.."; path=/")
|
http.header("Set-Cookie", "sysauth=" .. sid.."; path=/")
|
||||||
sauth.write(sid, user)
|
sauth.write(sid, util.get_bytecode({
|
||||||
|
user=user,
|
||||||
|
token=token,
|
||||||
|
secret=secret
|
||||||
|
}))
|
||||||
end
|
end
|
||||||
|
|
||||||
return sid
|
return sid and {sid=sid, token=token, secret=secret}
|
||||||
|
end
|
||||||
|
|
||||||
|
server.login = function(...)
|
||||||
|
local challenge = server.challenge(...)
|
||||||
|
return challenge and challenge.sid
|
||||||
end
|
end
|
||||||
|
|
||||||
http.prepare_content("application/json")
|
http.prepare_content("application/json")
|
||||||
|
|
Loading…
Reference in a new issue