Compare commits
3 Commits
614dfdfbf0
...
4869731a99
| Author | SHA1 | Date | |
|---|---|---|---|
| 4869731a99 | |||
| 7c22e73f66 | |||
|
|
836d908f4c |
|
|
@ -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;;';
|
||||
|
|
|
|||
|
|
@ -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 接口文件处理 ###
|
||||
######################################################
|
||||
|
|
|
|||
|
|
@ -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" },
|
||||
|
|
|
|||
43
src/api/system/captcha.lua
Normal file
43
src/api/system/captcha.lua
Normal 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
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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、生成时间)
|
||||
|
|
|
|||
44
src/service/system/captcha.lua
Normal file
44
src/service/system/captcha.lua
Normal 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
BIN
src/share/lib/gd.so
Executable file
Binary file not shown.
|
|
@ -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")
|
||||
--
|
||||
|
|
|
|||
|
|
@ -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
|
||||
Loading…
Reference in New Issue
Block a user