Spring Security 前后端分离

article/2025/10/5 19:42:00

前后端分离概述

前后端分离指的就是前后端分离部署前端 调用后端API后端 返回 JSON格式数据页面是由前端渲染并展示到浏览器中。

相比较传统的单体项目页面是由后端渲染完成后返回给浏览器的。(jsp、thymeleaf、html…)

Spring Security 现状

我们在 SpringSecurity入门篇,快速搭建一个安全Web服务 已经搭建了一个基本的示例。其中的关键的流程如下:

  1. 当未登录用户访问项目时,会重定向到登录页(/login)。
  2. 登录成功后,会重定向到首页(也就是 / 路径)。
  3. 登录失败的话,会重定向到登录页。
  4. 登出后,会重定向到登录页。
  5. 登录后,鉴权失败(访问权限不足)时,会返回403响应。

可以看出来,这妥妥的很不’前后端分离’,后端还会返回html页面并且各种重定向。好在 Spring Security 扩展性足够好,支持替换默认的实现,下文便来掰扯掰扯。

Spring Security 前后端分离改造

前后端分离的要点就是,后端的响应统一通过 JSON 格式返回,而不是html或者重定向。 基于这个出发点,我们将替换原有的实现类。

定义统一的响应格式

改造的第一点,则是定义一个统一的响应格式:

  • 统一的响应格式
@Data
@Accessors(chain = true)
public class RestResult<T> {private int code;private T data;private String msg;private RestResult() {}public static RestResult success() {return new RestResult().setCode(200);}public static RestResult success(Object data) {return success().setData(data);}public static RestResult error() {return new RestResult().setCode(500);}public static RestResult error(String errMsg) {return error().setMsg(errMsg);}public static RestResult error(int code, String errMsg) {return new RestResult().setCode(code).setMsg(errMsg);}public static RestResult error(Exception ex) {return error(ex.getMessage());}public String toJsonString() {return JsonUtils.toJsonString(this);}}

重写默认实现,并替换(重点)

涉及到的扩展点:

  • 登录成功处理:AuthenticationSuccessHandler
  • 登录失败处理:AuthenticationFailureHandler
  • 登出成功处理:LogoutSuccessHandler
  • 未登录处理:AuthenticationEntryPoint
  • 鉴权失败处理:AccessDeniedHandler

注意看代码中的注释,改造点对应上文中提到的原有流程的序号!

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated().and()// 表单登录.formLogin()// 登录成功处理(对应流程2).successHandler(new AuthenticationSuccessHandler() {@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {response.setContentType("application/json;charset=utf-8");response.getWriter().write(RestResult.success().toJsonString());}})// 登录失败处理(对应流程3).failureHandler(new AuthenticationFailureHandler() {@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {response.setContentType("application/json;charset=utf-8");response.getWriter().write(RestResult.error(exception).toJsonString());}}).and()//登出.logout()//登出成功处理(对应流程4).logoutSuccessHandler(new LogoutSuccessHandler() {@Overridepublic void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {response.setContentType("application/json;charset=utf-8");response.getWriter().write(RestResult.success().toJsonString());}}).and()//异常处理.exceptionHandling()//未登录处理(对应流程1).authenticationEntryPoint(new AuthenticationEntryPoint() {@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {response.setContentType("application/json;charset=utf-8");response.getWriter().write(RestResult.error(HttpServletResponse.SC_UNAUTHORIZED, "未登录").toJsonString());}})//没有权限处理(对应流程5).accessDeniedHandler(new AccessDeniedHandler() {@Overridepublic void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {response.setContentType("application/json;charset=utf-8");response.getWriter().write(RestResult.error(HttpServletResponse.SC_FORBIDDEN, "没有权限").toJsonString());}}).and().csrf().disable();}}

测试

直接测试原有流程,看看效果如何:

  1. 未登录时访问接口
    在这里插入图片描述
    很好,达到我们目的了,改造后,它并不是重定向到登录页,而是通过json响应回来401。ok

  2. 登录失败
    在这里插入图片描述
    同样的以json格式响应。nice

  3. 登录成功
    在这里插入图片描述
    输入正确的帐号密码,登录成功,json响应200。perfect

  4. 登出
    在这里插入图片描述
    over over

另外

项目还是利用 cookie-session 机制维持会话状态。
统一响应格式利用code判断请求是否成功。(还有一种方式是利用 HTTP状态码)

源码

https://gitee.com/markix/spring-security-example/tree/master/spring-security-simple-restful


end


http://chatgpt.dhexx.cn/article/oIUgxknK.shtml

相关文章

实现前后端分离

对目前的web来说&#xff0c;前后端分离已经变得越来越流行了&#xff0c;越来越多的企业/网站都开始往这个方向靠拢。那么&#xff0c;为什么要选择前后端分离呢&#xff1f;前后端分离对实际开发有什么好处呢? 为什么选择前后端分离 1. 在以前传统的网站开发中&#xff0c…

何为前后端分离?一文搞懂前后端分离发展史

目录 一、前言 二、前后端分离的演进过程 2.1 发展的三个阶段 2.2 前后端不分离阶段&#xff08;Java的JSP作为前端视图时代&#xff09; 2.3 前后端半分离阶段&#xff08;前后端使用Ajax交互的半分离时代&#xff09; 2.4 前后端完全分离阶段&#xff08;前后端使…

前后端分离架构概述

1、背景 前后端分离已成为互联网项目开发的业界标准使用方式&#xff0c;通过nginxtomcat的方式&#xff08;也可以中间加一个nodejs&#xff09;有效的进行解耦&#xff0c;并且前后端分离会为以后的大型分布式架构、弹性计算架构、微服务架构、多端化服务&#xff08;多种客户…

前后端分离架构,超全面详解~

此文通俗易懂&#xff0c;全面讲解前后端分离架构核心思想与作用&#xff0c;对学习微服务、开发企业项目大有裨益&#xff0c;建议收藏细品&#xff0c;好好领悟&#xff01;~ 一、简介 前后端分离已成为互联网项目开发的业界标准使用方式&#xff0c;通过nginxtomcat的方式&a…

到底什么是前后端分离

1、到底什么是前后端分离&#xff1f; 前后端分离的"前"特指浏览器端(或客户端)&#xff0c;直接呈现给用户的&#xff1b;后端是服务器端&#xff0c;处理业务逻辑和数据&#xff0c;不呈现给用户。 Java服务器端初学者最容易引起误解的一个概念就是&#xff1a;J…

c语言 链表基本操作

对于c语言的单链表来说&#xff0c;应该是数据结构中比较简单的一类结构&#xff0c;我们只要认识链表结构&#xff0c;对指针和结构体掌握好&#xff0c;其实编写代码并不算太难。 链表结构&#xff1a; 对于链表中的每一个结点&#xff0c;我们可以定义如下的结构体&#xf…

C语言——反转链表

大家好&#xff0c;本人第一次发布博客&#xff0c;目前正在学习数据结构&#xff0c;写博客的目的是一是想分享自己的学习过程&#xff0c;二也是每次写完代码后进行总结。希望大家一起共同学习&#xff01; 现在我正在看《大话数据结构》这本书&#xff0c;每次学习过后我都会…

C语言数据结构之链表

前面的文章我们就一直说&#xff0c;学一个新东西之前一定要弄明白它的作用是什么&#xff0c;我们为什么要用它。之前讲C语言时我们讲到数组&#xff0c;数组的实质是一种顺序储存、随机访问、存储单元连续的线性表&#xff0c;既然存储单元连续&#xff0c;那么对其进行插入和…

C语言来实现链表创建

链表原理理解 链表作为一种线性数据&#xff0c;通过前后节点的指针指向&#xff0c;将所有数据串联起来。为了实现链表数据域的整体耦合&#xff0c;需要额外的指针域来标定前后数据的连接。通过下面的链表结构图&#xff0c;可以非常容易的理解链表的组成结构 头节点作为链表…

链表C语言和C++两种方式实现

一、C语言版本链表&#xff1a; 方向1&#xff1a;无表头 法一&#xff1a;尾插法 #include<stdio.h> #include<malloc.h> //打印 创建 释放 删除某个数 插入某个数 &#xff08;T_T&#xff09;5个功能 struct Node {int data;struct Node* next; }; typedef st…

C语言实现链表创建

C语言实现链表的创建 链表:是一种物理存储单元上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点链表中每一个元素称为结点&#xff09;组成&#xff0c;结点可以在运行时动态生成。每个结点包括两个部分&#xf…

链表(c语言实现)

1.链表的分类 实际中链表的结构非常多样&#xff0c;以下情况组合起来就有8种链表结构&#xff1a; &#xff08;1&#xff09;单向或者双向 &#xff08;2&#xff09;带头或者不带头 &#xff08;3&#xff09;循环或者非循环 虽然有这么多的链表的结构&#xff0c;但是我们…

用c语言写链表

链表是数据结构的一种&#xff0c;是其他三个数据结构栈&#xff0c;树&#xff0c;图的基础&#xff0c;只有将链表这一数据结构弄懂&#xff0c;才能理解其他三种数据结构。 举一个例子&#xff0c;老师让你设计一个联系人系统&#xff0c;其中包括姓名&#xff0c;电话号&am…

C语言链表超详解

✅作者简介&#xff1a;嵌入式入坑者&#xff0c;与大家一起加油&#xff0c;希望文章能够帮助各位&#xff01;&#xff01;&#xff01;&#xff01; &#x1f4c3;个人主页&#xff1a;rivencode的个人主页 &#x1f525;系列专栏&#xff1a;玩转数据结构 &#x1f4ac;保持…

C语言——链表简单介绍

一、链表的引入 我们至少可以通过两种结构存储数据。 数组&#xff1a;数组是一个固定长度的存储相同数据类型的数据结构&#xff0c;数组中的元素被存储在一段连续的内存空间中。 优点&#xff1a;存取速度快。 缺点&#xff1a;需要一个连续的很大的内存&#xff1b; 插入和…

c语言链表示例

链表是一种常见的基础数据结构&#xff0c;结构体指针在这里得到了充分的利用。链表可以动态的进行存储分配&#xff0c;也就是说&#xff0c;链表是一个功能极为强大的数组&#xff0c;他可以在节点中定义多种数据类型&#xff0c;还可以根据需要随意增添&#xff0c;删除&…

反转链表c语言

反转链表 初始化三个指针 循环执行 temp cur→next cur→next pre pre cur ; cur temp 对于单链表&#xff0c;所有操作都是从头指针开始 // An highlighted block struct ListNode* ReverseList(struct ListNode* pHead ) {// 三指针法struct ListNode* pre pHead;s…

链表C语言实现--单向链表

线性结构的链式存储也称为链表&#xff0c;相比于顺序表&#xff0c;链表能够解决顺序表中空间资源浪费问题以及空间不足的问题。链表的每一个结点包含数据域和指针域&#xff0c;而每一个结点在内存中的地址是不连续的&#xff0c;且能适应动态变化。在数据插入和数据删除操作…

循环链表C语言实现

本文介绍循环链表中的单向循环链表&#xff0c;双向循环链表两种 第一种&#xff1a;单向循环链表&#xff0c;是在单向链表的基础上&#xff0c;尾结点不再指向NULL&#xff0c;而是指向头结点从而构成循环。如下图&#xff1a; 所以相比单向链表最大的特点就是可以从尾快速循…

C语言基础入门:链表详解篇

链表概述 链表是一种常见的重要的数据结构。它是动态地进行存储分配的一种结构。它可以根据需要开辟内存单元。链表有一个“头指针”变量&#xff0c;以head表示&#xff0c;它存放一个地址。该地址指向一个元素。链表中每一个元素称为“结点”&#xff0c;每个结点都应包括两个…