Last active
February 10, 2022 12:44
-
-
Save chaosong/7038017 to your computer and use it in GitHub Desktop.
sso in nginx (by openresty)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local cjson = require('cjson') | |
local util = require('login_util') | |
if ngx.var.request_method ~= 'POST' then | |
ngx.log(ngx.WARN, 'request method is not post') | |
ngx.exit(400) | |
end | |
ngx.req.read_body() | |
local args = ngx.req.get_post_args() | |
if not args then | |
ngx.log(ngx.WARN, 'failed to get post args') | |
ngx.exit(400) | |
end | |
local token = args['token'] | |
if not token then | |
ngx.log(ngx.WARN, 'token is nil') | |
ngx.exit(400) | |
end | |
local ref = args['ref'] | |
if not ref then | |
ngx.log(ngx.WARN, 'ref is nil') | |
ngx.exit(400) | |
end | |
local resp = ngx.location.capture('/auth_verify', { args = { token = token } }) | |
if resp.status ~= ngx.HTTP_OK then | |
ngx.log(ngx.WARN, 'verify token error: ', resp.status) | |
ngx.exit(500) | |
end | |
local js = cjson.decode(resp.body) | |
if not js['ret'] then | |
ngx.log(ngx.WARN, 'invalid token: ', token) | |
ngx.redirect(util.login_page) | |
end | |
local u = js['userId'] | |
if not u then | |
ngx.log(ngx.WARN, 'invalid userId: ', u) | |
ngx.redirect(util.login_page) | |
end | |
util.set_auth(u) | |
local url = ngx.decode_base64(ref) | |
if util.is_safe_url(url) then | |
ngx.redirect(url) | |
else | |
ngx.redirect(util.default_page) | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module(..., package.seeall) | |
login_page = '/login' | |
default_page = '/secret' | |
local salt = 'a_very_secret_key' | |
local expires = 24 * 3600 | |
function encrypt(u, t) | |
local s = ngx.md5(u .. t .. salt) | |
return string.sub(s, 0, #s / 2) | |
end | |
function set_auth(u) | |
local nt = ngx.now() + expires | |
local t = tostring(nt) | |
local v = encrypt(u, t) | |
ngx.header['Set-Cookie'] = { | |
string.format('auth=%s|%s|%s; Expires=%s', u, t, v, ngx.cookie_time(nt)) | |
} | |
end | |
function del_auth() | |
ngx.header['Set-Cookie'] = { 'auth=0|0|0; Expires=Thu, 01-Jan-1970 00:00:01 GMT' } | |
end | |
function check_auth(auth) | |
if not auth then | |
ngx.log(ngx.WARN, 'auth is empty') | |
return false | |
end | |
local r = {} | |
string.gsub(auth, '[^|]+', function(w) table.insert(r, w) end ) | |
if not r or #r ~= 3 then | |
ngx.log(ngx.WARN, 'auth is malformed') | |
return false | |
end | |
local u, t, v = r[1], r[2], r[3] | |
local nt = tonumber(t) | |
if not nt or nt < ngx.now() then | |
ngx.log(ngx.WARN, 'auth is expired') | |
return false | |
end | |
if encrypt(u, t) ~= v then | |
ngx.log(ngx.WARN, 'auth is modified') | |
return false | |
end | |
return true | |
end | |
function is_safe_url(url) | |
if url and #url > 0 and url:sub(1, 1) == '/' then | |
return true | |
end | |
ngx.log(ngx.WARN, 'url error: ', url) | |
return false | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
access_by_lua " | |
local util = require('login_util') | |
local auth = ngx.var.cookie_auth | |
if not util.check_auth(auth) then | |
ngx.redirect(util.login_page .. '?ref=' .. ngx.encode_base64(ngx.var.request_uri)) | |
end | |
ngx.log(ngx.WARN, auth, ' is logging in') | |
"; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
location /secret { | |
include need_login.conf; | |
default_type text/plain; | |
content_by_lua " | |
ngx.say('我是默认页啦~ 登录后可以正常跳转回来到此。') | |
local args = ngx.req.get_uri_args() | |
for key, val in pairs(args) do | |
if type(val) == 'table' then | |
ngx.say(key, ': ', table.concat(val, ', ')) | |
else | |
ngx.say(key, ': ', val) | |
end | |
end | |
"; | |
} | |
location /auth_callback { | |
rewrite_by_lua_file 'conf/auth_callback.lua'; | |
} | |
resolver 114.114.114.114; | |
location /auth_verify { | |
internal; | |
proxy_pass http://qsso.corp.qqqqq.com/api/verifytoken.php?token=$arg_token; | |
} | |
location /login { | |
default_type text/html; | |
set_by_lua $t 'return ngx.now()'; | |
echo " | |
<html> | |
<head> | |
<script src='https://qsso.corp.qqqqq.com/lib/qsso-auth.js?t=$t'></script> | |
</head> | |
<body> | |
<button id='qsso-login'>QSSO Login</button> | |
<script type='text/javascript'> | |
QSSO.attach('qsso-login','/auth_callback', { 'ref': '$arg_ref' }); | |
</script> | |
</body> | |
</html> | |
"; | |
} | |
location /logout { | |
rewrite_by_lua " | |
local util = require('login_util') | |
util.del_auth() | |
ngx.redirect(util.login_page) | |
"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment