从 PHP 到 AI + Golang,程序员自救转型手记(十七):登录接口完善,登录页接口整合,解决跨域
这是一个系列 Blog作者将以一个 PHP 全栈工程师的身份利用 AI 工具claude code、codex、deepseek、豆包等从零开始学习 golang 语言并最终完成 ai-go-mallgithub | gitee开源项目的制作全程记录分享。在上一期我们已经完成 “目录结构更新、完善 token 系统”本期将完成登录接口完善登录页接口整合解决跨域登录接口完善为什么使用有状态的 DB token 而不是 jwtjwt 无法即时作废是最大硬伤就算发现泄露也无法立即吊销风险致命仅这一点它就不适合后台管理系统jwt 信息只是 Base64 编码不是加密任何人解码就能看到里面用户 ID 等数据续期逻辑别扭要么滑动续期、要么双 TokenAccessRefresh方案增加复杂度密钥管理不当一旦泄露攻击者可伪造任意用户令牌来个服务器二次验证额外维护黑名单那就失去无状态的特性了何必jwt登录接口完善规划internal/service/admin/admin_service.go 中的 LoginRequest 增加 remember记住我字段管理员登录成功使用github.com/google/uuid的NewV7方法生成token值并使用 token 管理器internal\infra\token\token.go创建 tokenremember 为真时token 有效期为 30 天否则 token 有效期为 3 天未来考虑增加配置项可自定义修改 token 有效期将规划发给 cc这次的需求简单明确实现的核心代码如下增加了github.com/google/uuid依赖internal\service\admin\admin_service.go文件内管理员登录成功后增加了生成 token 的代码// 增加导入import(timeai-go-mall/internal/infra/tokengithub.com/google/uuid)// 登录方法中登录成功后增加生成令牌的代码tokenStr:uuid.Must(uuid.NewV7()).String()// 计算过期时间记住登录为 30 天否则为 3 天expiredAt:time.Now().Add(3*24*time.Hour)ifreq.Remember{expiredAttime.Now().Add(30*24*time.Hour)}// 创建令牌tk:model.Token{Token:tokenStr,Type:admin_login,UserID:admin.ID,CreatedAt:time.Now(),ExpiredAt:expiredAt,}iferr:token.Instance().Create(c.Request.Context(),tk);err!nil{returnnil,errors.New(保存令牌失败)}登录页接口整合完成登录页接口的整合于web/src/api/admin文件夹合理位置建立登录页的登录请求函数web/src/views/admin/login.vue完成登录请求的发送登录请求响应结构体是internal/service/admin/admin_service.go的LoginResponse请求后将响应的数据填充到adminInfo状态商店若登录请求成功跳转至/adminAI 工作时顺便手动操作数据库增加一个管理员以便后续测试密码密文可以让另外的 AI 生成提示词如golang 中验证密码使用 bcrypt.CompareHashAndPassword帮我生成一个密码为 “123456” 的密文登录接口整合已完成以下是变更总结1. 新增 web/src/api/admin/login.ts — 登录 API 请求函数 - 定义了 LoginRequest请求参数、LoginResponse响应数据两个 TypeScript 接口 - adminLogin()使用 URLSearchParams 以 application/x-www-form-urlencoded 格式提交与后端 Gin form 标签绑定方式匹配 - 请求路径POST /admin/login2. 更新 web/src/views/admin/login.vue — 接入真实登录 onSubmit 函数变更 // 之前占位代码 await new Promise((resolve)setTimeout(resolve,1500))// 之后真实 API 调用 const resawait adminLogin(loginForm)useAdminInfo().dataFill(res.data.data,false)router.push(/admin)完整流程1. 表单校验通过后调用 adminLogin(loginForm)发送登录请求2. 请求成功 → 通过 dataFill(res.data.data,false)将后端返回的管理员信息 token 全部填充到 adminInfo Pinia storefalse 表示不排除任何字段token 也会被持久化3. 填充完成后 → router.push(/admin)跳转到后台首页4. 请求失败code ≠0或网络错误→ 由 request.ts 拦截器自动弹出 ElMessage.error无需额外处理首先还是检查文件加减和目录结构调整是否正确后经过人工review后整理出第二轮需要优化的地方如下web/src/api/admin/login.ts改为index.ts后续将后台登录、首页接口等较为公共的请求函数都放入其中不应该使用特定的login命名删除LoginRequest请求参数、LoginResponse响应数据两个TypeScript接口PS前者由 login.vue 提供本身就带有类型定义后者如果请求函数需要复用保留的价值才能对等调用 API 请求函数时使用 then 的语法而不是 awaituseAdminInfo在顶层合适的位置提前定义变量而不是直接调用它的dataFill登录失败由request拦截器自动提示就直接不要catch了全部改完总结变更 web/src/api/admin/login.ts → web/src/api/admin/index.ts - 删除 LoginRequest、LoginResponse 两个接口参数类型内联为{username: string;password: string;remember: boolean}- 文件名改为 index.ts后续后台公共请求首页等都放入此文件 login.vue 变更 -import路径改为 //api/admin - router 和 adminInfo 在顶层就近定义不再在 onSubmit 内部调用 useAdminInfo()- 使用 .then().finally()链式语法替代 await - 移除 catch失败由 request 拦截器统一提示目检代码OK测试发现了一个计划之外的情况浏览器提示跨域直接问不收费的 AIgolang 里边解决跨域问题什么库最好用star 最多。解决跨域PS此时工作区已经有 登录页接口整合 尚未提交的代码作者一般喜欢保持工作区干净这里使用 git stash 保存工作现场先 add 再 stash 可以将新增文件也储藏起来否则只是修改部分最终决定整合 cors 库提示词如下现在解决跨域问题整合 https://github.com/gin-contrib/cors 跨域库仍旧是直接提供 github 仓库地址这是必须的具体原因可以参见第八期的热重载配置一章新建一个配置文件用于配置允许跨域的域名列表默认允许所有请求头、请求方法等只对域名做限制预检请求最大缓存时间 24 小时在合适位置单独建立跨域中间件文件其中使用以上跨域库结合跨域配置文件实现 CORS 处理中间件直接于 api/main.go 注册review时发现设定允许的请求方法时AI 将GET, POST, PUT, DELETE......逐一列出我们的要求是默认允许所有请求方式先问 AI允许所有请求方法能否使用 * 代替其次目录结构有改动增加了config/cors.yaml和internal\middleware\cors.go都是合理的。接下来整理出了第二轮需要优化的地方将AllowMethod、AllowHeaders、MaxAge等配置项都放入配置文件内原需求较为模糊它只放了域名列表默认只允许localhost和127.0.0.1而不是*允许域名列表只需要填写域名即可无需携带协议中间件中实现同时允许该域名的http和https还有一点比较重要的默认值设置到config/cors.yaml而不是如果config/cors.yaml为空则硬编码指定的那些默认值这一点算是 AI 造的坑它对默认值的理解是硬编码到代码中而我是希望默认值配置到config/cors.yaml中即可如果我修改了config/cors.yaml默认值也会随之修改才行它是这样写的// 应用默认值methods:cfg.Methodsiflen(methods)0{methods[]string{GET,POST,PUT,PATCH,DELETE,HEAD,OPTIONS}}headers:cfg.Headersiflen(headers)0{headers[]string{*}}// ...这意味着我清空了配置文件中的配置它反而又会应用上一些默认值而我希望的是清空了配置就不再允许该类请求 Methods 和 Headers。这次意外刚好在一定程度上证明了review的重要性本次虽然是跨域配置但一不小心就可能是重要数据泄露或权限意外提升跨域中间件和实现完整代码放在文末。继续测试登录页接口整合情况PS在解决跨域问题之前我们使用git stash保存了工作现场先恢复一下执行git stash popPS这里测试还是跨域原来 gin-contrib/cors 库配置的域名还得加上端口号这里又退回去让 AI 改为允许一个域名跨域就允许它的所有端口。经人工测试发现了两个问题登录请求参数使用的是 form 绑定// LoginRequest 登录请求参数typeLoginRequeststruct{// 使用了 formUsernamestringform:username binding:requiredPasswordstringform:password binding:requiredRememberboolform:remember}请求的Content-Type为application/x-www-form-urlencoded或multipart/form-data使用才使用表单绑定。而我们是application/json所以需要改为json绑定才更正规使用ShouldBind时会自动选择绑定引擎所以错误的 tag 目前没有影响值绑定修改如下// LoginRequest 登录请求参数typeLoginRequeststruct{// 改为 jsonUsernamestringjson:username binding:requiredPasswordstringjson:password binding:requiredRememberbooljson:remember}服务端输出的字段是PascalCase的命名方式 如Username、CreatedAt这些字段名和我们前端状态商店的字段名无法一一对应且几乎所有主流 API 都不会使用PascalCase大写开头作为 JSON 字段命名行业标准是snake_case这里暂时还是不建立DTO直接让AI修改模型的tag。// internal\model\admin.go 文件所有字段都加上了 json tag且敏感字段忽略typeAdminstruct{IDuintgorm:comment:ID;primarykey;autoIncrement json:idUsernamestringgorm:comment:用户名;type:varchar(64) json:usernameNicknamestringgorm:comment:昵称;type:varchar(64) json:nicknameAvatarstringgorm:comment:头像;type:varchar(255) json:avatarEmailstringgorm:comment:邮箱;type:varchar(128) json:emailMobilestringgorm:comment:手机号;type:varchar(16) json:mobileLoginFailureuintgorm:comment:连续登录失败次数;not null;default:0 json:-LastLoginAt time.Timegorm:comment:上次登录时间 json:last_login_atLastLoginIPstringgorm:comment:上次登录IP;type:varchar(64) json:last_login_ipPasswordstringgorm:comment:密码;type:varchar(255) json:-Biostringgorm:comment:个人简介;type:varchar(255) json:bioStatusstringgorm:comment:状态:enable启用,disable禁用;type:varchar(64) json:statusUpdatedAt time.Timegorm:comment:更新时间 json:updated_atCreatedAt time.Timegorm:comment:创建时间 json:created_atDeletedAt gorm.DeletedAtgorm:comment:删除时间;index json:-}状态商店src\stores\adminInfo.ts的dataFill方法批量填充状态时会填充state中没有的字段需要让 AI 进行过滤你的 AdminInfo 接口定义了8个字段id、username、nickname、avatar、last_login_at、last_login_ip、token、super。 this.$patch(state)的问题在于Pinia 的$patch会将传入对象的所有可枚举自有属性合并到 store 状态中。如果后端返回了 AdminInfo 中不存在的字段比如 email、phone 等它们会被悄无声息地写入 store。 解决方案在$patch之前用 Object.keys(this.$state)做白名单过滤只保留 store 中已定义的字段 const validKeysObject.keys(this.$state)const filtered: Recordstring, any{}Object.keys(state).forEach((key){ if(validKeys.includes(key)!exclude.includes(key)){filtered[key]state[key]}})以上方案看起来不错不过我们项目已经引入了lodash-es所以让 AI 不要手搓查找lodash-es中的可用函数两种写法 写法一_.pick _.omit 链式import{pick, omit}fromlodash-esconst filteredomit(pick(state, validKeys), exclude)写法二_.difference _.pick一次 pick更清晰import{pick, difference}fromlodash-esconst allowedKeysdifference(validKeys, exclude)const filteredpick(state, allowedKeys)推荐写法二一次 pick 同时完成白名单过滤和排除比手写 forEach includes 更简洁也比我之前的写法更易读。需要我更新代码吗最终改动大概是这样的// 白名单过滤只保留 $state 中已定义的字段并排除指定字段// exclude 是开发者调用函数时传入的排除字段列表constallowedKeysdifference(Object.keys(this.$state),exclude)this.$patch(pick(state,allowedKeys))

相关新闻

3步搞定网页视频下载:Video Download Helper完全指南

3步搞定网页视频下载:Video Download Helper完全指南

3步搞定网页视频下载:Video Download Helper完全指南 【免费下载链接】VideoDownloadHelper Chrome Extension to Help Download Video for Some Video Sites. 项目地址: https://gitcode.com/gh_mirrors/vi/VideoDownloadHelper 还在为无法保存网页视频而烦…

2026/7/3 8:49:37阅读更多 →
Appium自动化测试环境搭建全攻略:从零到一避坑指南

Appium自动化测试环境搭建全攻略:从零到一避坑指南

1. 项目概述:为什么Appium环境搭建是自动化测试的第一道坎搞移动端自动化测试,Appium是绕不开的一个工具。它支持Android和iOS,能用多种语言写脚本,社区生态也成熟。但几乎所有新手,包括我当年,都会在第一步…

2026/7/3 8:49:37阅读更多 →
代理GEO全栈服务接单范围有哪些

代理GEO全栈服务接单范围有哪些

代理商在面对不同客户时,客户的需求深度和预算规模各不相同。有些客户只需要轻量问答口碑优化,有些客户则需要全套的AI搜索获客体系建设。代理商代理GEO全栈服务,到底能接哪些范围的单?答案是:覆盖从基础到高端的完整频…

2026/7/3 8:44:36阅读更多 →
纪元1800模组加载器:用XML魔法打造你的个性化游戏世界

纪元1800模组加载器:用XML魔法打造你的个性化游戏世界

纪元1800模组加载器:用XML魔法打造你的个性化游戏世界 【免费下载链接】anno1800-mod-loader The one and only mod loader for Anno 1800, supports loading of unpacked RDA files, XML merging and Python mods. 项目地址: https://gitcode.com/gh_mirrors/an/…

2026/7/3 16:06:05阅读更多 →
IIM-42652与STM32F303RC实现6DoF运动跟踪方案

IIM-42652与STM32F303RC实现6DoF运动跟踪方案

1. 从3D到6DoF:IMU与MCU的硬件搭档在运动追踪和姿态感知领域,IIM-42652与STM32F303RC的组合堪称黄金搭档。IIM-42652是TDK InvenSense推出的新一代6轴MEMS惯性测量单元(IMU),集成了3轴陀螺仪和3轴加速度计,能够提供高精度的运动数…

2026/7/3 16:06:05阅读更多 →
InvenTree开源库存管理系统实战指南:从零搭建智能库存管理平台

InvenTree开源库存管理系统实战指南:从零搭建智能库存管理平台

InvenTree开源库存管理系统实战指南:从零搭建智能库存管理平台 【免费下载链接】InvenTree Open Source Inventory Management System 项目地址: https://gitcode.com/GitHub_Trending/in/InvenTree 你是否正在为零件管理混乱、库存数据不准确、采购流程繁琐…

2026/7/3 16:06:05阅读更多 →
Mac视频预览革命:让Finder秒变全能播放器的终极方案

Mac视频预览革命:让Finder秒变全能播放器的终极方案

Mac视频预览革命:让Finder秒变全能播放器的终极方案 【免费下载链接】QuickLookVideo This package allows macOS Finder to display thumbnails, static QuickLook previews, cover art and metadata for most types of video files. 项目地址: https://gitcode.…

2026/7/3 16:06:05阅读更多 →
HEIF Utility:5分钟掌握Windows平台HEIF图片查看与转换的终极解决方案

HEIF Utility:5分钟掌握Windows平台HEIF图片查看与转换的终极解决方案

HEIF Utility:5分钟掌握Windows平台HEIF图片查看与转换的终极解决方案 【免费下载链接】HEIF-Utility HEIF Utility - View/Convert Apple HEIF images on Windows. 项目地址: https://gitcode.com/gh_mirrors/he/HEIF-Utility HEIF Utility是一款专为Window…

2026/7/3 16:06:05阅读更多 →
三轴运动追踪方案:WSEN-ISDS与TM4C129XKCZAD硬件实现

三轴运动追踪方案:WSEN-ISDS与TM4C129XKCZAD硬件实现

1. 项目概述:三轴运动追踪的硬件选型与实现 在工业自动化和消费电子领域,精确测量物体在三维空间中的运动和姿态一直是个经典需求。这次我选用Wrth Elektronik的WSEN-ISDS三轴加速度计搭配TI的TM4C129XKCZAD微控制器,搭建了一套完整的空间运动…

2026/7/3 16:01:05阅读更多 →
AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

6个月前的2025年12月,Boris Cherny 公开宣布自己卸载了 IDE。一时间,Vibe Coding 成了全行业最热的话题。6个月后,当我们回过头来拉一份真实账本,发现事情远没有"一句话生成一个App"那么浪漫。本文从产品经理和研发两个…

2026/7/3 14:18:39阅读更多 →
审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

引言:审计结束三个月了,审计员的权限还没关某城商行每年按照监管要求开展至少一次数据安全审计。审计期间,内审部门需要抽样检查各类业务数据——交易流水、客户信息、员工操作日志、权限配置记录。这些数据分布在不同系统中,审计…

2026/7/3 14:38:35阅读更多 →
LV3296与PIC18F45K22的UART通信与USB扩展方案

LV3296与PIC18F45K22的UART通信与USB扩展方案

1. LV3296与PIC18F45K22的硬件搭档解析在嵌入式数据采集系统中,LV3296条形码扫描模块与PIC18F45K22微控制器的组合堪称经典搭配。LV3296作为一款工业级条码扫描头,其核心是一颗高性能CMOS图像传感器,配合专用解码芯片,能自动识别包…

2026/7/3 0:03:41阅读更多 →
AI初创生存指南:6个月完成可信度验证闭环

AI初创生存指南:6个月完成可信度验证闭环

1. 这不是“逆袭指南”,而是一份AI初创公司真实生存手记“How To Beat Odds As an AI Startup?”——这个标题乍看像一句热血口号,但在我带过7个从0到1的AI产品团队、亲手踩过融资失败、技术债崩盘、客户POC卡在最后一公里等23类典型坑之后,…

2026/7/3 0:03:41阅读更多 →
多模态+推理链+RAG 2.0+智能体:工业级AI系统落地四支柱

多模态+推理链+RAG 2.0+智能体:工业级AI系统落地四支柱

1. 这不是又一篇“AI趋势速览”,而是一份实操者手记:当多模态、推理链、检索增强与智能体协作真正撞进工程现场“LAI #73”这个编号本身就像一个暗号——它不属于某家大厂的白皮书,也不是学术会议的议程表,而是长期泡在模型训练集…

2026/7/3 0:03:41阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/3 1:12:46阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/3 1:36:36阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/3 2:08:15阅读更多 →