-- vim: set ts=4 sw=4 sts=4 noai noet: --[[ MySQL-Auth - IQ lighttpd-mod-magnet lua-socket lua-sql-mysql *************************** 1. row *************************** id: 1 login: Fritz password: a8e13417253337017fb29cbe1a647bba2d7dca95b232f70f782bd64da49855606d122e5715d6a63754d88d1ea3fe561af26260fedd7b2425044c7e565fa1dfa0 ]] --[[ https://redmine.lighttpd.net/projects/lighttpd/wiki/AbsoLUAtion#Do-basic-HTTP-Auth-against-a-MySQL-DBTable Known Problems: This Script is blocking!!! Lighttpd will hang, if there are MySQL connection problems. Additionally, a whole new MySQL Connection is created with every request! So you shouldn't use this on High-Traffic Sites. Passwords are stored plain in MySQL - well, easy to fix. Look for MySQL's PASSWORD function.... ]] -- nur "/geheim.php" soll passwortgeschützt sein if ( string.format('%s', lighty.env["uri.path"]) == "/geheim.php" ) then -- Force https if (lighty.env["uri.scheme"] == "http") then lighty.header["Location"] = "https://" .. lighty.env["uri.authority"] .. lighty.env["request.uri"] return 302 end --[[ Config Variables ]] local dbConf = {} dbConf.database = 'authdb' dbConf.username = 'dbuser' dbConf.password = 'geheim' dbConf.hostname = '192.168.2.10' dbConf.port = "3306" --[[ dbConf.users_table = "dealer_logins" dbConf.col_user = "login" dbConf.col_pass = "password" ]] --[[ Requires ]] -- Debian package: liblua5.1-socket2 -- required for Base64 De-/encoding. See: http://w3.impa.br/~diego/software/luasocket/home.html require("mime") -- Debian package: liblua5.1-sql-mysql-2 -- Lua Mysql Driver luasql = require("luasql.mysql") --[[ Function to send HTTP-Auth request ]] function doAuth() lighty.header["WWW-Authenticate"] = string.format('Basic realm="%s"', lighty.env["uri.authority"]) return 401 end --[[ Function to check Auth Creds against MySQL Database ]] local env = assert(luasql.mysql()) local con = assert(env:connect ( dbConf.database ,dbConf.username ,dbConf.password ,dbConf.hostname ,dbConf.port )) function checkAuthMySQL(user,pass) local res = con:execute(string.format([[ SELECT login, password FROM `dealer_logins` WHERE `login` = '%s' AND `password` = '%s' ]], user, pass) ) -- Die Tabelle wir in ein Array gespeichert local row = res:fetch ({}, "a") -- print(type(row)) -- close everything -- res:close() -- already closed because all the result set was consumed con:close() -- env:close() if (not row) then return false else lighty.req_env['REMOTE_USER'] = user return true end end -- MAIN --[[ Check for Authorization Header and force Basic Auth if not set. ]] if (not lighty.request.Authorization) then return doAuth() end --[[ Header found: check string for "Basic" and base64 encoded username & password - upb = User Password Base64 encoded ]] _, _, upb = string.find(lighty.request.Authorization, "^Basic%s+(.+)$") up = mime.unb64(upb) -- Base64 Decode _, _, username, password = string.find(up, "^(.+):(.+)$") -- split by ":" to get username and password supplied -- ============================================================================= -- In der DB steht das Passwort nicht im klartext drin, sondern verschlüsselt -- deshalb muss auch der Passwort-Hash und nicht das Passwort verglichen werden. -- -- hier wird aus dem Passwort der Passwort-Hash generiert -- -- /var/www/webauftritt/libs/WebServices/Ovp/Authentication/Encrypt.php local start = ("/usr/bin/php /etc/lighttpd/sha512crypt.php " .. password) datei = assert (io.popen (start)) pwhash = datei:read ("*l") -- read one line -- ============================================================================= if (not checkAuthMySQL(username, pwhash)) then return doAuth() end end -- return nothing to proceed normal operation return