Compare commits

...

3 Commits

10 changed files with 232 additions and 70 deletions

View File

@ -13,7 +13,7 @@ http {
client_max_body_size 1024M; #允许最大100k的请求体
client_body_buffer_size 1024M; #设置缓冲区大小
lua_code_cache on; #代码缓存
#lua_code_cache on; #代码缓存
lua_package_path '$prefix/src/?/?.lua;$prefix/src/?.lua;/home/frankly/work/AuthPlatform/src/?/?.lua;/home/frankly/work/AuthPlatform/src/?.lua;;';
lua_package_cpath '$prefix/src/share/lib/?.so;/home/frankly/work/AuthPlatform/src/share/lib/?.so;;';

View File

@ -48,6 +48,11 @@ location /yum/v1/system/users {
content_by_lua_file '${APP_PATH}/src/api/system/user.lua';
}
#登陆时图片验证码相关
location /yum/v1/system/captcha {
content_by_lua_file '${APP_PATH}/src/api/system/captcha.lua';
}
######################################################
### oauth2.0 + openIDC 接口文件处理 ###
######################################################

View File

@ -13,12 +13,6 @@ local routes = {
--------------------------------------------
------------ OIDC OAuth2.0认证相关路由配置 ---
--------------------------------------------
--OP端点配置
{
paths = { "/yum/v1/.well-known/openid-configuration" },
methods = { "GET", "POST" },
handler = oauthService.openidConfig,
},
--获取授权码
{
paths = { "/yum/v1/oauth/v2/authorize" },

View File

@ -0,0 +1,43 @@
---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by admin.
--- DateTime: 2025/11/21 11:50
--- 验证码图片接口
--解析url路由过滤库
local radix = require("resty.radixtree")
--数据表业务处理
local systemCaptcha = require("service.system.captcha")
--定义相关路由前端接口url地址
local routes = {
--验证码图片相关路由接口
{
paths = { "/yum/v1/system/captcha" },
methods = { "GET" },
handler = systemCaptcha.getCaptcha,
},
}
-- 初始化路由
local rx, err = radix.new(routes)
if not rx then
ngx.say("Not Found")
ngx.exit(ngx.HTTP_NOT_FOUND)
end
--获取访问的uri地址
local uri = ngx.var.uri
local opts = {
host = ngx.var.host,
method = ngx.var.request_method,
remote_addr = ngx.var.remote_addr,
matched = {}
}
-- 进行路由匹配和相关函数调用
local ok = rx:dispatch(uri, opts, opts.matched)
if not ok then
ngx.say("Not Found")
ngx.exit(ngx.HTTP_NOT_FOUND)
end

View File

@ -100,7 +100,10 @@ end
--根据客户端id和重定向地址获取应用程序
function _M.getApplicationByClientId(client_id, redirect_uri)
--print("getApplicationByClientId client_id:", client_id, " redirect_uri:", redirect_uri)
return applicationModel:where('app_id', '=', client_id):where('redirect_uris', '=', redirect_uri):get()
if redirect_uri == nil then
return applicationModel:where('client_id', '=', client_id):get()
end
return applicationModel:where('client_id', '=', client_id):where('redirect_uri', '=', redirect_uri):get()
end
function _M.getApplicationByUserid(user_id, client_id, client_secret)

View File

@ -45,18 +45,18 @@ function _M:authorize()
local ok = validator.validateAuthorize(args)
--验证失败则返回
if not ok then
return ngx.exit(ngx.HTTP_BAD_REQUEST)
ngx.exit(ngx.HTTP_BAD_REQUEST)
end
-- 校验 response_type 必须为 "code"(授权码模式)
if args.response_type ~= "code" then
return ngx.exit(ngx.HTTP_BAD_REQUEST)
ngx.exit(ngx.HTTP_BAD_REQUEST)
end
-- 1、校验客户端id和redirect_uri是否存在数据库
local client_id = args.client_id
local redirect_uri = args.redirect_uri
local code, res = oauthDao.getApplicationBy(client_id)
if code ~= 0 or not res then
return ngx.exit(ngx.HTTP_UNAUTHORIZED)
ngx.exit(ngx.HTTP_UNAUTHORIZED)
end
--判断redirect_uri是否在重定向组里面
local redirect_uris = res[1].redirect_uri
@ -75,7 +75,7 @@ function _M:authorize()
--local login_url = "/login?redirect=" .. ngx.escape_uri(ngx.var.request_uri)
--print("authorize login_url:", login_url)
--ngx.redirect(login_url)
resp:response(ngx.HTTP_MOVED_TEMPORARILY, login_url)
resp:response(status.USER_NOT_LOGIN)
return
end
-- 4. 生成授权码随机字符串确保唯一性用户ID、客户端ID、scope、生成时间

View File

@ -0,0 +1,44 @@
---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by admin.
--- DateTime: 2025/11/21 11:55
--- 验证码相关函数
local _M = {}
local status = require("util.status")
local resp = require("util.response")
local genpic = require("util.generatechaptcha")
local red = require("share.redis")
--生成图片文件
function _M.getCaptcha()
local filename, base64_data, captchaText = genpic.get_captcha_base64()
--将文件名存储到redis中 超时时间5分钟
local key = "captcha-"..filename
red:set(key, captchaText)
red:expire(key, 5 * 60)
-- 4.返回结果
local ret = {
picgid = filename,
pic = base64_data
}
resp:response(status.SUCCESS, ret)
end
--验证图片上的验证码
function _M.checkCaptcha()
end
--验证码删除
function _M.deleteCaptcha()
--获取请求中参数
local args = ngx.req.get_uri_args()
--其中image为要删除的验证码图片的picgid。
local picgid = args["picgid"]
red:del(picgid)
end
return _M

BIN
src/share/lib/gd.so Executable file

Binary file not shown.

View File

@ -31,6 +31,74 @@ local status = val or STATUS_CODE.UNKNOWN_ERROR
local msg = status.message
ngx.say("message:"..msg)
local ok, gd = pcall(require, "gd")
if not ok then
ngx.say("加载失败"..gd)
return
end
function enabled(res, desc)
local str = " " .. desc .. " "
str = str .. string.rep(".", 37 - string.len(str))
if res then
ngx.say(str .. " Enabled")
else
ngx.say(str .. " Disabled")
end
end
ngx.say("Lua-GD version: " .. gd.VERSION)
ngx.say("Lua-GD features:")
--[[
local iSeed = os.time() + os.clock() * 10000
math.randomseed(iSeed)
function CheckCode(nChars, iWidth, iHeight)
local sTab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
local iTabLen = string.len(sTab)
local idx, x, y, clr
local im = gd.create(iWidth, iHeight)
im:colorAllocate(255, 255, 255) -- background color
for i=1, nChars do
clr = im:colorAllocate(math.random(0, 100), math.random(0, 150), math.random(0, 200))
idx = math.random(1, iTabLen)
x = math.random(1, 8) + iWidth * (i-1) / 4
y = math.random(1, iHeight / 4)
im:string(gd.FONT_LARGE, x, y, string.sub(sTab, idx, idx), clr)
end
for i=1, 3 do
clr = im:colorAllocate(math.random(0, 255), math.random(0, 255), math.random(0, 255))
im:line(math.random(1, iWidth), math.random(1, iHeight), math.random(1, iWidth), math.random(1, iHeight), clr)
end
return im
end
local im = CheckCode(4, 60, 20)
print("Content-type: image/png")
print("Pragma: no-cache")
print("Expires: Thu Jan 01 00:00:00 UTC 1970")
print("")
io.write(im:pngStr())
--]]
local uuid = require("util.uuid")
local uid = uuid.generateUuid()
ngx.say("uuid:"..uid)
local genpic = require("util.generatechaptcha")
local filename, fp = genpic.getChaptcha()
--redis中添加picgid为key,string为value的记录
--setRedis(filename, stringmark)
--response header中传参picgid
ngx.header.content_type = "text/plain"
ngx.header.picgid = filename
--页面返回pic
ngx.say(fp)
--nginx退出
--ngx.exit(200)
--do return end
--local openssl = require("openssl")
--

View File

@ -4,69 +4,74 @@
--- DateTime: 2025/11/19 20:18
--- 生成校验码图片
--设置随机种子
local resty_uuid = require("resty.uuid")
math.randomseed(tonumber(resty_uuid.gennum20()))
--在32个备选字符中随机筛选4个作为captcha字符串
local dict={'A','B','C','D','E','F','G','H','J','K','L','M','N','P','Q','R','S','T','U','V','W','X','Y','Z','2','3','4','5','6','7','8','9'}
local stringmark = ""
for i = 1, 4 do
stringmark = stringmark..dict[math.random(1,32)]
end
--图片基本info
--picgid
local filename = "1"..resty_uuid.gen20()..".png"
--图片78x26
local xsize = 78
local ysize = 26
--字体大小
local wsize = 17.5
--干扰线(yes/no)
local line = "yes"
--加载模块
local gd = require('gd')
--创建面板
local im = gd.createTrueColor(xsize, ysize)
--定义颜色
local black = im:colorAllocate(0, 0, 0)
local grey = im:colorAllocate(202, 202, 202)
local color = {}
for c = 1, 100 do
color[c] = im:colorAllocate(math.random(100), math.random(100), math.random(100))
end
--画背景
x, y = im:sizeXY()
im:filledRectangle(0, 0, x, y, grey)
--画字符
gd.useFontConfig(true)
for i = 1, 4 do
k = (i - 1) * 16 + 3
im:stringFT(color[math.random(100)], "Arial:bold", wsize, math.rad(math.random(-10,10)), k, 22, string.sub(stringmark, i, i))
end
--干扰线点
if line == "yes" then
for j = 1, math.random(3) do
im:line(math.random(xsize), math.random(ysize), math.random(xsize), math.random(ysize), color[math.random(100)])
local uuid = require("util.uuid")
local _M = {}
--在32个备选字符中随机筛选4个作为captcha字符串
local dict = {'A','B','C','D','E','F','G','H','J','K','L','M','N','P','Q','R','S','T','U','V','W','X','Y','Z','2','3','4','5','6','7','8','9'}
-- 生成验证码图片
local function generate_captcha()
--图片基本info
local uid = uuid.generateUuid()
--picgid
local filename = uid
--图片78x26
local width = 78
local height = 26
-- 创建画布
local im = gd.createTrueColor(width, height)
-- 设置背景色(白色)
local white = im:colorAllocate(255, 255, 255)
im:filledRectangle(0, 0, width, height, white)
-- 设置文本颜色(黑色)
local black = im:colorAllocate(0, 0, 0)
-- 生成随机验证码4位数字字母
math.randomseed(os.time())
local captcha_text = ""
for i = 1, 4 do
captcha_text = captcha_text..dict[math.random(1,32)]
end
for p = 1, 20 do
im:setPixel(math.random(xsize), math.random(ysize), color[math.random(100)])
-- 在图片上绘制验证码文本
gd.useFontConfig(true)
for i = 1, 4 do
local char = string.sub(captcha_text, i, i)
local x = 10 + (i-1)*25 + math.random(-5,5)
local y = 10 + math.random(-5,5)
local angle = math.random(-20, 20)
im:stringFT(black, "Arial:bold", 18, angle, x, 30, char)
end
-- 添加干扰线
for i = 1, 5 do
local line_color = im:colorAllocate(math.random(0,255), math.random(0,255), math.random(0,255))
im:line(math.random(0, height), math.random(0, width), math.random(0,height), math.random(0, width), line_color)
end
-- 添加噪点
for i = 1, 100 do
local dot_color = im:colorAllocate(math.random(0,255), math.random(0,255), math.random(0,255))
im:setPixel(math.random(0, height), math.random(0, width), dot_color)
end
-- 将图片转换为PNG格式的二进制数据
local png_data = im:pngStr(75)
return filename, captcha_text, png_data
end
--流输出
local fp = im:pngStr(75)
--redis中添加picgid为key,string为value的记录
--setRedis(filename, stringmark)
-- 生成验证码并返回Base64编码
function _M.get_captcha_base64()
local filename, captcha_text, png_data = generate_captcha()
--response header中传参picgid
ngx.header.content_type = "text/plain"
ngx.header.picgid = filename
if not png_data then
ngx.log(ngx.ERR, "Failed to generate captcha image")
return nil, nil, nil
end
-- 对图片数据进行Base64编码
local base64_data = ngx.encode_base64(png_data)
return filename, base64_data, captcha_text
end
--页面返回pic
ngx.say(fp)
--nginx退出
ngx.exit(200)
return _M