当前位置: 首页 > news >正文

Spring Security(第五篇):从单体到前后端分离 —— JSON 响应与处理器实战

欢迎来到我的博客,代码的世界里,每一行都是一个故事


在这里插入图片描述

🎏:你只管努力,剩下的交给时间

🏠 :小破站

Spring Security(第五篇):从单体到前后端分离 —— JSON 响应与处理器实战

    • 功能清单与路径一览
    • 关键实现(与代码严格对应)
    • 可视化演示页:左右布局便于截图
    • 实操指南(含你的测试过程)
      • 登录成功(JSON,不重定向)
      • 登录失败(用户名或密码错误)
      • 访问受保护接口(已登录)
      • 权限不足(403)
      • 注销成功(JSON)
    • 单体 vs 前后端分离:Handler 层面的差异对照
    • 常见问题与排查
    • 总结
    • 感谢

我们把“怎么进来”(认证来源:配置/内存/数据库)讲清楚了。进入系统之后,单体应用(服务端渲染)和前后端分离的最大差异并不是“如何认证”,而是“响应形式”:

  • 单体:表单提交,重定向/渲染页面
  • 分离:JSON API 请求,返回 JSON(不重定向,不渲染页面)

本篇聚焦“响应处理器(Handler)”在前后端分离场景下的落地:登录成功、登录失败、未登录访问、权限不足、注销成功,都返回一致的 API JSON。


功能清单与路径一览

  • 登录(API):POST /api/login(表单键 username/password)
  • 注销(API):POST /api/logout
  • 公开接口:GET /api/public(无需登录)
  • 用户接口:GET /api/user、GET /api/me(需登录)
  • 管理员接口:GET /api/admin(需 ADMIN 角色)
  • 经理接口:GET /api/manager(需 MANAGER 角色)
  • 演示页面:GET /api-demo(可视化操作与查看 JSON 响应)

安全配置采用两条过滤器链:

  • /api/** 使用 JSON 响应(JsonAuthenticationHandler/JsonAccessDeniedHandler)
  • 其他路径沿用页面流(登录页、控制台等)

关键实现(与代码严格对应)

  • API 过滤器链(只匹配 /api/**)

    http.securityMatcher("/api/**").authorizeHttpRequests(a->a.requestMatchers("/api/public").permitAll().requestMatchers("/api/admin").hasRole("ADMIN").requestMatchers("/api/manager").hasRole("MANAGER").anyRequest().authenticated()).formLogin(f->f.loginProcessingUrl("/api/login").successHandler(jsonAuthenticationHandler).failureHandler(jsonAuthenticationHandler))
    
  • 统一 JSON 返回结构

    @Data @Builder
    public class ApiResponse<T> {private int code; private String message; private T data; private long timestamp;
    }
    
  • 登录成功/失败/未认证/注销的 JSON 处理器(节选)

    @Override public void onAuthenticationSuccess(..., Authentication auth){var info = Map.of("username",auth.getName(),"loginTime",System.currentTimeMillis());writeJsonResponse(resp,200, ApiResponse.success("登录成功", info));
    }
    
  • 权限不足(403)处理(节选)

    @Override public void handle(...){write403(ApiResponse.forbidden("权限不足,无法访问该资源"));
    }
    

可视化演示页:左右布局便于截图

  • 页面:/api-demo
  • 左侧:API 登录表单与说明;右侧:JSON 响应结果实时显示

页面片段(布局 CSS 已调整为“左侧操作,右侧响应”):

<div class="login-response-container"><div class="login-section">...</div><div class="response-section"><div id="responseArea"></div></div>
</div>

实操指南(含你的测试过程)

前置:启动应用(端口 18080),使用数据库认证模式(已内置三类账户):

  • dbuser/db123(USER)
  • dbadmin/dbadmin123(USER,ADMIN)
  • dbmanager/dbmanager123(USER,MANAGER)

登录成功(JSON,不重定向)

  • 打开 /api-demo

  • 左侧输入:用户名 dbuser,密码 db123

  • 点击“API 登录”

  • 预期:右侧显示

    { "code":200, "message":"登录成功", "data":{"username":"dbuser", ...} }

  • image-20250813230721564

登录失败(用户名或密码错误)

  • 仍在 /api-demo

  • 输入:用户名 dbuser,密码 wrong

  • 点击“API 登录”

  • 预期:右侧显示

    { "code":401, "message":"用户名或密码错误" }

  • image-20250813230811129

访问受保护接口(已登录)

  • 点击“调用用户接口”或“获取当前用户信息”

  • 预期:右侧显示 200 JSON,包含当前用户名与权限集合

    image-20250813230927843

权限不足(403)

  • 以 dbuser 登录(无 ADMIN)

  • 点击“调用管理员接口”

  • 预期:右侧显示

    { "code":403, "message":"权限不足,无法访问该资源" }

    image-20250813231048594

注销成功(JSON)

  • 点击“API 注销”

  • 预期:右侧显示

    { "code":200, "message":"注销成功" }

  • image-20250813231136934


单体 vs 前后端分离:Handler 层面的差异对照

  • 单体(页面流)
    • 登录成功:302 重定向到 /dashboard
    • 登录失败:302 重定向到 /login?error
    • 未认证:302 到 /login
    • 权限不足:渲染 403 页面
    • 注销成功:302 到首页
  • 分离(JSON 流,本篇 /api/**)
    • 登录成功:200 JSON(不重定向)
    • 登录失败:401 JSON
    • 未认证:401 JSON
    • 权限不足:403 JSON
    • 注销成功:200 JSON

常见问题与排查

  • 401 但你“自认为登录了”:确认是否在 /api/login 登录;/login 与 /api/login 分属两条链
  • 403 但你觉得自己是管理员:核对登录账号是否具备 ROLE_ADMIN(dbadmin)
  • 跨域(CORS):本项目演示同源访问,若前端独立域名,请在 API 链路上配置 CORS
  • CSRF:/api/** 关闭 CSRF;如采用 Cookie 场景,请按需启用并前后配合

总结

  • 本篇实现了“相同认证模型,不同响应形态”的演示:/api/** 走 JSON,不影响原页面流
  • 通过可视化页面 /api-demo,你可以一屏操作并截图:登录成功、失败、权限不足、注销成功

感谢

感谢你读到这里,说明你已经成功地忍受了我的文字考验!🎉
希望这篇文章没有让你想砸电脑,也没有让你打瞌睡。
如果有一点点收获,那我就心满意足了。

未来的路还长,愿你
遇见难题不慌张,遇见bug不抓狂,遇见好内容常回访
记得给自己多一点耐心,多一点幽默感,毕竟生活已经够严肃了。

如果你有想法、吐槽或者想一起讨论的,欢迎留言,咱们一起玩转技术,笑对人生!😄

祝你代码无bug,生活多彩,心情常青!🚀
在这里插入图片描述

http://www.xdnf.cn/news/1363519.html

相关文章:

  • 0826xd
  • QtExcel/QXlsx
  • 力扣82:删除排序链表中的重复元素Ⅱ
  • 《Password Guessing Using Large Language Models》——论文阅读
  • 离线可用的网络急救方案
  • JavaScript Intl.RelativeTimeFormat:自动生成 “3 分钟前” 的国际化工具
  • [React]Antd Select组件输入搜索时调用接口
  • 基于RFM模型的客户群体大数据分析及用户聚类系统的设计与实现
  • 【Flink】运行模式
  • 文献阅读笔记:KalmanNet-融合神经网络和卡尔曼滤波的部分已知动力学状态估计
  • Zabbix Vs. Grafana
  • win11中系统的WSL安装Centos以及必要组件
  • nmcli命令详解
  • Docker:网络连接
  • SQL性能调优
  • 2025年8月25日-8月31日(qtopengl+ue独立游戏)
  • 告别“复制粘贴”式换肤:我用Adobe XD组件变体与CC库,构建多品牌设计系统架构
  • THM Bricks Heist靶机
  • 新的 macOS 安装程序声称能够快速窃取数据,并在暗网上销售
  • 文入门Ubuntu:从零到精通的Linux之旅
  • 【ARM】MDK在debug模式下断点的类型
  • 中介者模式及优化
  • 使用EasyExcel根据模板导出文件
  • imx586手册和相机寄存器部分解读
  • 【Springboot】依赖注入方式
  • Linux 离线安装lrzsz(rz、sz上传下载小插件)
  • IntelliJ IDEA 新手入门教程-Java、Web、Maven创建(带图解)
  • 疯狂星期四文案网第49天运营日记
  • 使用现代 <img> 元素实现完美图片效果(2025 深度实战版)
  • 【图像处理基石】基于Real-ESRGAN的实时图像超分辨率技术实现