diff --git a/src/api/oauth/oauth.lua b/src/api/oauth/oauth.lua index bf9a3cb..e61ee90 100644 --- a/src/api/oauth/oauth.lua +++ b/src/api/oauth/oauth.lua @@ -34,7 +34,7 @@ local routes = { --回收token { paths = { "/yum/v1/oauth/v2/logout" }, - methods = { "POST" }, + methods = { "GET", "POST" }, handler = oauthService.logout, }, } diff --git a/src/service/oauth/oauth.lua b/src/service/oauth/oauth.lua index 018df3e..d090c49 100644 --- a/src/service/oauth/oauth.lua +++ b/src/service/oauth/oauth.lua @@ -179,7 +179,7 @@ local function authorizateCode(args) local ret = {} ret.access_token = new_access_token ret.token_type = "Bearer" - ret.expires_in = 10 * 60 + ret.expires_in = conf.access_token_ttl ret.refresh_token = new_refresh_token ret.id_token = new_id_token -- 6.将生成的数据存储到数据库中 @@ -224,7 +224,7 @@ local function authorizateRefresh(args) local ret = {} ret.access_token = new_access_token ret.token_type = "Bearer" - ret.expires_in = 10 * 60 + ret.expires_in = conf.access_token_ttl ret.id_token = new_id_token -- 4.返回结果 local result = resp:json(ngx.HTTP_OK, ret) @@ -347,11 +347,80 @@ end --回收token function _M:logout() - -- 假设从会话中获取用户 ID(sub) - local sub = "user123" -- 实际应从登录会话中获取 + -- 1. 解析请求参数(支持 form-data 和 json) + local content_type = ngx.req.get_headers()["Content-Type"] or "" + local args = {} + print("logout token content_type:", content_type) + if string.find(content_type, "application/json") then + -- 读取请求体的数据 + ngx.req.read_body() + -- 获取请求数据 + local body_data = ngx.req.get_body_data() + if not body_data then + return ngx.exit(ngx.HTTP_BAD_REQUEST) + end + -- 验证json数据是否正确 + local ok, data = pcall(cjson.decode, body_data) + if not ok then + return ngx.exit(ngx.HTTP_BAD_REQUEST) + end + args = data + else + if ngx.req.get_method() == "POST" then + -- 默认解析 form-urlencoded + args = ngx.req.get_post_args() + elseif ngx.req.get_method() == "GET" then + args = ngx.req.get_uri_args() + end + end + -- 1、校验客户端id和redirect_uri是否存在数据库 + local ok = validator.validateLogout(args) + if not ok then + print("validateLogout:", args) + local result = resp:json(0x000001) + resp:send(result) + return + end + local token = args.access_token + print("logout token:", token) + -- 4.对token进行验证 + --print("userinfo pubkey:", pub_key) + local pub_key = conf.secret_key + local jwt_obj = jwt:verify(pub_key, token) + --如果校验结果中的verified==false,则表示令牌无效 + if jwt_obj.verified == false then + ngx.log(ngx.WARN, "Invalid token: ".. jwt_obj.reason) + ngx.status = ngx.HTTP_UNAUTHORIZED + ngx.exit(ngx.HTTP_UNAUTHORIZED) + end + --判断token是否超时 --令牌已过期 + if jwt_obj.payload.exp and ngx.time() > jwt_obj.payload.exp then + ngx.log(ngx.WARN, "token timeout ".. jwt_obj.reason) + ngx.status = ngx.HTTP_UNAUTHORIZED + ngx.exit(ngx.HTTP_UNAUTHORIZED) + end + --通过用户id获取用户信息 + --print("-- get jwt_obj.payload value --") + --for key, value in pairs(jwt_obj.payload) do + -- print("jwt_obj.payload: ", key, " ", value) + --end + local sub = jwt_obj.payload.sub -- 遍历所有 refresh_token(生产环境建议用 Redis 哈希存储用户与 rt 的映射) - local keys = red:keys("oidc:refresh_token:*") + --获取redis中所有匹配的数据内容 + local pattern = "oidc:refresh_token:*" + local cursor = "0" + local keys = {} + repeat + local result, err = red:scan(cursor, 'MATCH', pattern) + if not result then + break + end + cursor = result[1] + for _, key in ipairs(result[2]) do + table.insert(keys, key) + end + until cursor == "0" for _, key in ipairs(keys) do local rt_data_str = red:get(key) if rt_data_str and rt_data_str ~= ngx.null then @@ -363,6 +432,10 @@ function _M:logout() end end end + -- 5.获取token中的信息进行所需用户的信息返回 + local ret = {} + local result = resp:json(ngx.HTTP_OK, ret) + resp:send(result) end return _M \ No newline at end of file diff --git a/src/validator/oauth/oauth.lua b/src/validator/oauth/oauth.lua index fb60023..4bc5b09 100644 --- a/src/validator/oauth/oauth.lua +++ b/src/validator/oauth/oauth.lua @@ -102,4 +102,22 @@ function _M.validateRefresh(jsonData) return result end +local schemaLogout = { + type = "object", + properties = { + access_token = { type = "string" }, + client_id = { type = "string" }, + client_secret = { type = "string" }, + }, + required = { "access_token", "client_id", "client_secret" } +} + +--回收Token +function _M.validateLogout(jsonData) + -- 验证数据是否符合schema + local validator = jsonschema.generate_validator(schemaLogout) + local result = validator(jsonData) + return result +end + return _M \ No newline at end of file