第三方登录接口增加通过用户名和密码进行登录接口,返回对应的code和redirect_uri地址数据,同时通过用户id、clientid和clientsecret进行数据库校验的业务逻辑进行处理

This commit is contained in:
wanglei 2025-11-14 13:44:18 +08:00
parent 54cc8fbfbf
commit b286ecf891
5 changed files with 170 additions and 56 deletions

View File

@ -8,6 +8,29 @@ local applicationDao = require("dao.system.application")
local _M = {}
--通过用户名和密码进行认证
function _M.authenticateUserPasswd(username, passwd)
--验证用户名是否为空
local code, res = userDao:getUserByUsername(username) --authenticate(name, passwd)
if code ~= 0 then
return 0x000001, res
end
local num = 0
if res ~= nil then
num = table.getn(res)
end
--用户不存在时返回
if num <= 0 then
return 0x01000C,nil
end
--进行密码验证 获取数据库的密码
local pwdMd5 = ngx.md5(res[1].password)
if pwdMd5 ~= passwd then
return 0x000001,res --密码错误
end
return 0, res
end
--用户登录业务逻辑处理
function _M.login(jsonData)
--解析json中的键和数据值
@ -65,4 +88,9 @@ function _M.getApplicationBy(client_id, redirect_uri)
return applicationDao.getApplicationByClientId(client_id, redirect_uri)
end
function _M.getApplicationByUserid(user_id, client_id, client_secret)
--print("getApplicationBy user_id:", user_id, " client_id:", client_id, "client_secret", client_secret)
return applicationDao.getApplicationByUserid(user_id, client_id, client_secret)
end
return _M

View File

@ -110,4 +110,10 @@ function _M.getApplicationByClientId(client_id, redirect_uri)
return applicationModel:where('app_id', '=', client_id):where('redirect_uris', '=', redirect_uri):get()
end
function _M.getApplicationByUserid(user_id, client_id, client_secret)
local sql = [[SELECT "A".user_id,"B".* FROM sys_user_application AS "A" INNER JOIN sys_application AS "B" ON "A".application_id = "B"."id"
WHERE "A".user_id =']]..user_id..[[' AND "B".client_id=']]..client_id..[[' AND "B".client_secret=']]..client_secret.."'"
return applicationModel:exec(sql)
end
return _M

View File

@ -77,10 +77,107 @@ function _M:authorize()
rest.state = args.state
local result = resp:json(ngx.HTTP_OK, rest)
resp:send(result)
return
end
--根据授权码获取Access-Token
-- 通过用户名认证用户和应用是否存在状态
local function authorizatePassword(args)
-- 1.校验必填参数验证数据是否符合json
local ok = validator.validateLogin(args)
if not ok then
local result = resp:json(0x000001)
resp:send(result)
return
end
-- 2.验证用户名和密码应用程序id和应用程序密钥
local code, res = oauthDao.authenticateUserPasswd(args.username, args.password)
if code ~= 0 or res == nil then
local result = resp:json(0x000001)
resp:send(result)
return
end
-- 3.对当前用户的持有的应用程序进行验证
local userid = res[1].id
local client_id = args.client_id
local client_secret = args.client_secret
code, res = oauthDao.getApplicationByUserid(userid, client_id, client_secret)
if code ~= 0 or res == nil then
local result = resp:json(0x000001)
resp:send(result)
return
end
local redirect_uri = res[1].redirect_uris
-- 4.生成授权码随机字符串确保唯一性用户ID、客户端ID、scope、生成时间
local auth_code, err = authcode.create(userid, client_id, redirect_uri)
if not auth_code then
ngx.log(ngx.ERR, "生成授权码失败: ", err)
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
-- 5.存储用户信息,证明用户已经登陆
-- 6.返回结果
local rest = {}
rest.redirect_uri = redirect_uri
rest.code = auth_code
local result = resp:json(ngx.HTTP_OK, rest)
resp:send(result)
end
-- 通过code形式进行认证
local function authorizateCode(args)
-- 1.校验必填参数验证数据是否符合json
local ok = validator.validateToken(args)
if not ok then
local result = resp:json(0x000001)
resp:send(result)
return
end
-- 2.校验 code 有效性
local code_data, err = authcode.consume(args.code)--, args.client_id)
if not code_data then
ngx.log(ngx.ERR, "授权码验证失败: ", err)
ngx.exit(ngx.HTTP_BAD_REQUEST)
end
-- 3.验证redirect_url地址的正确性
local request_uri = code_data.redirect_uri
print("token request_uri:", request_uri)
if request_uri ~= args.redirect_uri then
print("token redirect_url:", request_uri, args.redirect_uri)
local login_url = "/login?redirect=" .. ngx.escape_uri(request_uri)
local result = resp:json(ngx.HTTP_MOVED_TEMPORARILY, login_url)
resp:send(result)
return
end
-- 4.生成密钥对
local pub_key, priv_key, err = rsa.generate_rsa_keys(2048)
if err then
print("密钥生成失败: ", err)
local result = resp:json(0x00001)
resp:send(result)
return
end
print("token pubkey:", pub_key)
local user_id = code_data.user_id
local client_id = code_data.client_id
local scope = code_data.scope
-- 5.生成新 Access Token
local new_access_token = token.generate_access_token(priv_key, user_id, client_id, scope)
-- 生成新 Refresh Token滚动刷新
local new_refresh_token = token.generate_refresh_token(priv_key, user_id, client_id, scope)
-- 生存id_token
local new_id_token = token.generate_id_token(priv_key, user_id, client_id, scope)
--ngx.say("Generated JWT: ", jwt_obj)
-- 6.返回结果
local ret = {}
ret.access_token = new_access_token
ret.token_type = "Bearer"
ret.expires_in = 10 * 60
ret.refresh_token = new_refresh_token
ret.id_token = new_id_token
local result = resp:json(ngx.HTTP_OK, ret)
resp:send(result)
end
-- 根据授权码获取Access-Token
function _M:token()
-- 1. 解析请求参数(支持 form-data 和 json
local content_type = ngx.req.get_headers()["Content-Type"] or ""
@ -101,61 +198,20 @@ function _M:token()
end
args = data
else
-- 默认解析 form-urlencoded
args = ngx.req.get_post_args()
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
-- 2. 校验必填参数验证数据是否符合json
local ok = validator.validateToken(args)
if not ok then
local result = resp:json(0x000001)
resp:send(result)
return
local grant_type = args.grant_type
if grant_type == "password" then
authorizatePassword(args)
elseif grant_type == "authorization_code" then
authorizateCode(args)
end
-- 3. 校验 code 有效性
local code_data, err = authcode.consume(args.code)--, args.client_id)
if not code_data then
ngx.log(ngx.ERR, "授权码验证失败: ", err)
ngx.exit(ngx.HTTP_BAD_REQUEST)
end
-- 4、验证redirect_url地址的正确性
local request_uri = code_data.redirect_uri
print("token request_uri:", request_uri)
if request_uri ~= args.redirect_uri then
print("token redirect_url:", request_uri, args.redirect_uri)
local login_url = "/login?redirect=" .. ngx.escape_uri(request_uri)
local result = resp:json(ngx.HTTP_MOVED_TEMPORARILY, login_url)
resp:send(result)
return
end
-- 5. 生成密钥对
local pub_key, priv_key, err = rsa.generate_rsa_keys(2048)
if err then
print("密钥生成失败: ", err)
local result = resp:json(0x00001)
resp:send(result)
return
end
print("token pubkey:", pub_key)
local user_id = code_data.user_id
local client_id = code_data.client_id
local scope = code_data.scope
-- 6 生成新 Access Token
local new_access_token = token.generate_access_token(priv_key, user_id, client_id, scope)
-- 7 生成新 Refresh Token滚动刷新
local new_refresh_token = token.generate_refresh_token(priv_key, user_id, client_id, scope)
-- 8、生存id_token
local new_id_token = token.generate_id_token(priv_key, user_id, client_id, scope)
--ngx.say("Generated JWT: ", jwt_obj)
-- 9. 返回结果
local ret = {}
ret.access_token = new_access_token
ret.token_type = "Bearer"
ret.expires_in = 10 * 60
ret.refresh_token = new_refresh_token
ret.id_token = new_id_token
local result = resp:json(ngx.HTTP_OK, ret)
resp:send(result)
end
--根据Access-Token获取相应用户的账户信息
@ -188,7 +244,7 @@ function _M:userinfo()
resp:send(result)
return
end
-- 5.对token进行验证
-- 4.对token进行验证
print("userinfo pubkey:", pub_key)
local jwt_obj = jwt:verify(pub_key, token)
--如果校验结果中的verified==false则表示令牌无效
@ -204,7 +260,7 @@ function _M:userinfo()
ngx.status = ngx.HTTP_UNAUTHORIZED
ngx.exit(ngx.HTTP_UNAUTHORIZED)
end
-- 6.获取token中的信息进行所需用户的信息返回
-- 5.获取token中的信息进行所需用户的信息返回
local ret = {}
ret.sub = 248289761001
ret.name = "Jane Doe"

View File

@ -36,6 +36,9 @@ end
-- 验证并消费授权码(一次性有效)
function _M.consume(code, client_id)
if code == nil then
return nil, "无效的授权码"
end
local code_key = "auth_code-"..code
local shared_dict = ngx.shared.codeDict
local data = shared_dict:get(code_key)

View File

@ -28,6 +28,27 @@ function _M.validateAuthorize(jsonData)
return result
end
-- 定义一个JSON Schema
local schemaLogin = {
type = "object",
properties = {
grant_type = { type = "string" },
client_id = { type = "string" },
client_secret = { type = "string" },
username = { type = "string" },
password = { type = "string" },
},
required = { "grant_type", "client_id", "client_secret", "username", "password" }
}
--通过用户名和密码进行认证
function _M.validateLogin(jsonData)
-- 验证数据是否符合schema
local validator = jsonschema.generate_validator(schemaLogin)
local result = validator(jsonData)
return result
end
local schemaToken = {
type = "object",
properties = {