前言
GoAdmin是一个基于 golang
面向生产的数据可视化管理平台搭建框架,可以让你使用简短的代码在极短时间内搭建起一个管理后台,虽然我也会去修改和新增一些功能页面,但是它给我的感觉总像一个黑盒子,大概是我对Web开发的知识了解甚少,总是照葫芦画瓢的完成一些工作,最近在鉴权和会话过期的处理上遇到了一点点问题,直接GET访问页面在会话过期时会自动跳转到登录页面,而点击按钮提交表单时如果已经会话过期了却没有任何反应,我觉得是少设置了一些东西,绕了一大圈才算勉强解决,但这应该不是最优的方案,先记录一下,后续找到好的解决方案再优化。
问题的发现与解决
使用GoAdmin搭建的后台网站,如果长时间停留在一个页面,点击菜单中的其他页面时会自动跳转到登录页面,但是点击页面表单上的提交按钮却没有反应,这种情况会让人迷惑,不知道刚刚这个操作到底有没有执行成功,要解决这个问题就先查代码吧?实际上时候发现,这时点击提交按钮时报了一个js错误,只有在浏览器的控制台才能看到,起初没发现也是走了一些弯路。
一开始我认为两种情况一个表现正常、一个表现不正常是因为GET和POST的缘故,所以我对比了两种请求处理从注册路由开始的逻辑代码,尽最大可能保持一样,但没有解决。
注册路由的方式,GoAdmin开源项目中有相关代码
1 | authRoute.POST("/menu/edit", admin.guardian.MenuEdit, admin.handler.EditMenu).Name("menu_edit") |
我简单的理解就是,告诉框架当访问到前面这个路径的时候,依次调用后面的处理函数就行了,当然这也是我这两天跟踪代码时领取的,最后的 Name
函数是为这个路由命令,而我的应用不管是GET路由还是POST路由都使用了 auth.Middleware(admin.Conn)
这个鉴权函数,按道理说肯定都进行了鉴权处理,不应该有差异的,最开始有一些包装函数逻辑顺序的差异,我调整成一样的依旧不生效。
我使用断点,单步调试查看GET和POST的区别,但是没有发现差异,两者都返回了302状态码表示重定向,但是GET成功跳转了,而POST没有变化
1 | // Middleware is the default auth middleware of plugins. |
两种方式函数最终都走到了下面这个分支,结果却不相同
1 | if (ctx.Headers(constant.PjaxHeader) == "" && ctx.Method() != "GET") || |
没办法,这时我只能打开浏览器按下F12开始调试,渐渐发现了一些端倪,无论是点击菜单还是点击提交按钮,都收到了302也进行了跳转,但是点提交按钮这种情况收到302后虽然跳转成功了,但是页面没有切换,赶紧问了一下ChatGPT,他告诉我很可能是Ajax的锅。
Ajax究竟是个啥,虽然之前听过,但是我却说不上来,继续搜索吧。
AJAX(Asynchronous JavaScript and XML)是一种用于创建快速动态网页的技术。通过使用 AJAX,网页能够与服务器进行异步交互,而无需重新加载整个页面。AJAX 允许在后台与服务器进行通信,并使用 JavaScript 更新网页的部分内容。
使用 AJAX 的优势很多,比如:
- 提高用户体验:AJAX 允许在后台加载数据,从而使网页更流畅,用户不需要等待整个页面重新加载。
- 减少服务器负载:只请求所需的数据,而不是重新加载整个页面,降低了数据传输量。
- 更快的响应时间:通过部分更新页面内容,用户能够更快地看到更新结果。
常见的 AJAX 应用场景如下:
- 表单提交:在用户提交表单时,AJAX 可以异步提交数据,避免页面刷新。
- 动态内容加载:在用户滚动或点击时加载更多内容,例如无限滚动。
- 实时数据更新:如聊天应用、股票价格更新等实时信息。
这里的表单提交我确实使用了AJAX,这就导致它没有正确处理302状态码,我当时是这么想的,也是朝着这个方向努力的
找到页面上中设置Ajax回调函数的逻辑
1 | panel.EnableAjaxData(types.AjaxData{ |
我开始拿 panel.AjaxErrorJS
开刀,我分析了前面的代码,以为这个字段是空的,准备替换成如下代码:
1 | function(data) { |
很遗憾不太好用,有时好使有时不好使,并且页面一直在上方显示着加载中的进度条,没办法继续问ChatGPT吧,有一项相关提醒:
错误处理逻辑:确保在 error 函数中正确处理请求失败的情况。如果没有适当地处理错误,进度条可能会一直显示。
所以我又看了一下控制台,发现错误提醒,告诉我没有函数名:
1 | Uncaught SyntaxError: Function statements require a function name |
所以我改成了下面这样
1 | function alala(data) { |
但这次一点也不好使了,我查看页面源码一看,原来变成了下面这样,能好使才怪了
1 | function (data) { |
进一步分析我发现 panel.AjaxSuccessJS
和 panel.AjaxErrorJS
都不是空的,不能简单覆盖,需要做一步调整,这两个变量的初始化代码在 EnableAjaxData
函数
1 | func (f *FormPanel) EnableAjaxData(data AjaxData) *FormPanel { |
仿照着它的逻辑,在设置Ajax回调函数时我直接写function之中的内容,反正最后function和大括号它会自动生成,改完AjaxErrorJS
后满心欢喜的测试,心想马上就解决了,但是发现居然没有什么效果,打开控制台一开又报错了
1 | VM4407:2 Uncaught SyntaxError: Unexpected token '<', " |
什么意思呢?分析过后其实是调用Ajax回调函数 AjaxSuccessJS
时,执行 data = JSON.parse(data);
这一句报了错,这里有点奇怪,起初以为302会调用到error的回调函数,现在一看跑到success函数中去了
大概分析原因如下:
302 是一个重定向状态码,表示所请求的资源临时位于不同的 URI。通常,响应中会包含一个 Location 头,指示新位置。当 AJAX 请求收到 302 状态码时,浏览器会处理重定向,通常会自动跟随新的 URL。
如果重定向的目标是一个 HTML 页面(如登录页面),浏览器会将该页面的内容返回给 AJAX 请求的 success 回调,而不是将其处理为错误。换句话说,AJAX 请求会成功接收到重定向目标的 HTML 内容,因为 HTTP 状态码 302 仍被视为“成功”请求的一部分(尽管它表示需要重定向)。
知道了这些就明白怎么去解决问题了,既然返回的是登录界面的HTML不是json数据,那么我就先判断,如果是登录界面的时候跳转就可以了,为了提升体验,可以加一个弹窗提示和延迟跳转
1 | if (data.includes("!DOCTYPE html") && data.includes("登录")) { |
关于这个问题我又问了一下ChatGPT,得到的答案是这样的:
为什么浏览器已经收到了跳转而来的登录界面的内容,却没有跳转,而是继续保持在过期的页面呢
当浏览器发出 AJAX 请求并收到 302 重定向时,通常的行为是浏览器会自动向新的 URL 发起请求。但是,如果在 AJAX 请求的上下文中出现以下情况,可能导致浏览器没有自动跳转,而是显示重定向目标页面的内容,可能的原因如下:
AJAX 请求的响应处理:
- 当 AJAX 请求收到 302 响应时,浏览器会自动请求新的 URL,但这个行为通常不影响当前页面的 URL。相反,它只是在 AJAX 请求的上下文中更新了响应内容。
- 如果服务器返回的 302 重定向是指向一个 HTML 页面(如登录页面),并且这个 HTML 内容被返回到 AJAX 的
success
回调中,那么浏览器会将这个内容显示在当前页面,而不会自动进行 URL 更改。
AJAX 的特性:
- AJAX 的目的就是异步加载数据,而不影响页面的整体加载。因此,即使 AJAX 请求收到重定向,浏览器的行为是将新的内容注入到当前页面中,而不是直接改变当前页面的 URL。
浏览器行为:
- 在某些情况下(尤其是在使用 JavaScript 进行页面更新时),浏览器可能不会进行页面跳转,因为页面的 JavaScript 处理了新的 HTML 内容。开发者可以在 AJAX 请求的
success
回调中自定义如何处理这种情况。
- 在某些情况下(尤其是在使用 JavaScript 进行页面更新时),浏览器可能不会进行页面跳转,因为页面的 JavaScript 处理了新的 HTML 内容。开发者可以在 AJAX 请求的
总结
- GoAdmin是一个用
golang
编写的前后端一体的面向生产的数据可视化管理平台搭建框架 - AJAX是一种用于创建快速动态网页的技术,能够实现与服务器进行异步交互,更新网页的部分内容
swal
是 SweetAlert 库的一个函数,用于创建漂亮的弹出框(模态窗口)以显示消息、警告、提示等- SweetAlert有1和2两个版本,SweetAlert 2 的返回值支持 Promise,可以使用
then()
方法 - 当使用Ajax发送请求时入股遇到重定向返回给ajax回调函数success的数据是新页面的HTML内容
我饮人间二两酒,一饮无奈一饮空!我欠人间二两墨,一笔相思,一笔错!也许人生就是这样,不品人间酒,不知其中醉,不陷世间情,怎知其中泪。永远不用幻想着另一条路是美好的,那只是我们内心美化后的结果,经历过的才是真实~
2024-12-26 22:07:26