Spring Security实现用户认证二:前后端分离时自定义返回Json内容

Spring Security实现用户认证二:前后端分离时自定义返回Json内容

  • 1 前后端分离
  • 2 准备工作
    • 依赖
    • WebSecurityConfig配置类
  • 2 自定义登录页面
    • 2.1 Spring Security的默认登录页面
    • 2.2 自定义配置formLogin
  • 3 自定义登录成功处理器
  • 4 自定义登录失败处理器
  • 5 自定义登出处理器
  • 6 自定义回话过期处理器
  • 7 定义认证失败接入点

1 前后端分离

在现在大多数web开发中,采用的开发模式均是前后端分离类型的。往往后端给前端返回的数据格式为json类型:

{"code":"200","message":"success","data":"登录成功"
}

2 准备工作

依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency><dependency><groupId>org.thymeleaf.extras</groupId><artifactId>thymeleaf-extras-springsecurity6</artifactId>
</dependency><dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId>
</dependency>

WebSecurityConfig配置类

import com.alibaba.fastjson2.JSON;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;import java.io.IOException;
import java.util.HashMap;
import java.util.Map;public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {//为存储在内存中的基于用户名/密码的认证提供支持。@Beanpublic UserDetailsService userDetailsService() {InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();manager.createUser(User.withDefaultPasswordEncoder().username("root").password("root").roles("USER").build());return manager;}@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {//        ResultData<String> result = ResultData.success("登录成功");Map<String, Object> result = new HashMap<>();result.put("code", "200");result.put("message", "登录成功");result.put("data", "");//将结果转换成字符串String json = JSON.toJSONString(result);//返回json数据response.setContentType("application/json;charset=UTF-8");response.getWriter().println(json);}
}

2 自定义登录页面

2.1 Spring Security的默认登录页面

.httpBasic(withDefaults())
在这里插入图片描述
.formLogin(withDefaults())
在这里插入图片描述

2.2 自定义配置formLogin

注释掉原来的formLogin和httpBasic。

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.authorizeRequests(authorize ->authorize.anyRequest().authenticated());
//                .formLogin(withDefaults())
//                .httpBasic(withDefaults());http.formLogin(login ->login.loginPage("/login").permitAll() // 一定加上这个,不然会一直重定向,导致报错);return http.build();
}

在resources下创建目录templates,用来存放thymeleaf写的页面,在这个目录下面创建login.html页面

<html xmlns:th="https://www.thymeleaf.org">
<head><title>login</title>
</head>
<body>
<h1>Login</h1>
<div th:if="${param.error}">错误的用户名或密码.
</div>
<form th:action="@{/login}" method="post"><div><input type="text" name="username" placeholder="请输入用户名"></div><div><input type="password" name="password" placeholder="请输入密码"></div><input type="submit" value="登录">
</form>
</body>
</html>

创建LoginController :

@GetMapping("/login")
public String login(){return "login";
}

效果如下:
在这里插入图片描述

3 自定义登录成功处理器

定义MyAuthenticationSuccessHandler

import com.alibaba.fastjson2.JSON;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;import java.io.IOException;
import java.util.HashMap;
import java.util.Map;public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {Map<String, Object> result = new HashMap<>();result.put("code", "200");result.put("message", "登录成功");result.put("data", "");//将结果转换成字符串String json = JSON.toJSONString(result);//返回json数据response.setContentType("application/json;charset=UTF-8");response.getWriter().println(json);}
}

添加配置

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {// ...http.formLogin(login -> {login.loginPage("/login").permitAll();login.successHandler(new MyAuthenticationSuccessHandler());});return http.build();
}

效果
在这里插入图片描述

4 自定义登录失败处理器

定义MyAuthenticationFailureHandler

import com.alibaba.fastjson2.JSON;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;import java.io.IOException;
import java.util.HashMap;
import java.util.Map;public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {Map<String, Object> result = new HashMap<>();result.put("code", "401");result.put("message", "登录失败");result.put("data", "");//将结果转换成字符串String json = JSON.toJSONString(result);//返回json数据response.setContentType("application/json;charset=UTF-8");response.getWriter().println(json);}
}

添加配置

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {// ...http.formLogin(login -> {login.loginPage("/login").permitAll();login.successHandler(new MyAuthenticationSuccessHandler());login.failureHandler(new MyAuthenticationFailureHandler());});return http.build();
}

效果
在这里插入图片描述

5 自定义登出处理器

定义MyLogoutSuccessHandler

import com.alibaba.fastjson2.JSON;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;import java.io.IOException;
import java.util.HashMap;
import java.util.Map;public class MyLogoutSuccessHandler implements LogoutSuccessHandler {@Overridepublic void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {Map<String, Object> result = new HashMap<>();result.put("code", "200");result.put("message", "登出成功");//将结果转换成字符串String json = JSON.toJSONString(result);//返回json数据response.setContentType("application/json;charset=UTF-8");response.getWriter().println(json);}
}

添加配置

为了能够正确登出,需要将csrf配置关闭,否则只接受post请求登出。

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {// ...http.logout(logout -> {logout.logoutSuccessHandler(new MyLogoutSuccessHandler());});http.csrf(csrf->csrf.disable());return http.build();
}

效果
在这里插入图片描述

6 自定义回话过期处理器

这个当会话过期或者超出登录数量时。

定义MyLogoutSuccessHandler

import com.alibaba.fastjson2.JSON;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;import java.io.IOException;
import java.util.HashMap;
import java.util.Map;public class MyLogoutSuccessHandler implements LogoutSuccessHandler {@Overridepublic void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {Map<String, Object> result = new HashMap<>();result.put("code", "200");result.put("message", "登出成功");//将结果转换成字符串String json = JSON.toJSONString(result);//返回json数据response.setContentType("application/json;charset=UTF-8");response.getWriter().println(json);}
}

添加配置

将最大的session数限制为1,则只允许一个session在线。expiredSessionStrategy指定过期策略。

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {// ...http.sessionManagement(session ->{session.maximumSessions(1).expiredSessionStrategy(new MySessionInformationExpiredStrategy());});return http.build();
}

先登录一个浏览器,在登录另一个浏览器,在刷新第一个浏览器。
效果
在这里插入图片描述

7 定义认证失败接入点

创建:MyAuthenticationEntryPoint 实现 AuthenticationEntryPoint接口

import com.alibaba.fastjson2.JSON;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;import java.io.IOException;
import java.util.HashMap;
import java.util.Map;public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint {@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {String localizedMessage = authException.getLocalizedMessage();Map<String, Object> result = new HashMap<>();result.put("code", "500");result.put("message", localizedMessage);String jsonString = JSON.toJSONString(result);response.setContentType("application/json;charset=UTF-8");response.getWriter().println(jsonString);}
}

配置WebSecurityConfig:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {// ...http.exceptionHandling(exception ->{exception.authenticationEntryPoint(new MyAuthenticationEntryPoint());});return http.build();
}

在我们没有登录时。直接访问主页,会发生异常。

效果
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/12940.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

经济寒冬 | 品牌策划人还可以去哪些行业发展?

在这个经济寒冬下&#xff0c;咱们品牌策划人也需要考虑后路问题了。 随着市场竞争的加剧和消费者需求的不断变化&#xff0c;品牌策划人的工作不再只是简单的广告宣传和市场推广。 咱们需要重新思考自己的角色&#xff0c;寻找新的生存和发展之道。 当然&#xff0c;品牌策…

VUE之旅—day2

文章目录 Vue生命周期和生命周期的四个阶段created应用—新闻列表渲染mounted应用—进入页面搜索框就获得焦点账单统计&#xff08;Echarts可视化图表渲染&#xff09; Vue生命周期和生命周期的四个阶段 思考&#xff1a; 什么时候可以发送初始化渲染请求&#xff1f;&#xff…

前端本地调试云效上Vue项目的构建产物

一、问题背景 前两天前端小伙伴&#xff0c;在云效上构建了一个前端项目&#xff0c;构建结果显示成功&#xff0c;访问后发现Console控制台报错&#xff1a;ReferenceError: defineComponent is not defined 在此之前的版本&#xff0c;构建和访问并没有此异常&#xff0c;而…

【设计模式】JAVA Design Patterns——Abstract-document(抽象文档模式)

&#x1f50d; 目的 使用动态属性&#xff0c;并在保持类型安全的同时实现非类型化语言的灵活性。 &#x1f50d; 解释 抽象文档模式使您能够处理其他非静态属性。 此模式使用特征的概念来实现类型安全&#xff0c;并将不同类的属性分离为一组接口 真实世界例子 考虑由多个部…

eMMC和SD模式速率介绍

概述 在实际项目开发中我们常见的问题是有人会问,“当前项目eMMC、SD所使用模式是什么? 速率是多少?”。这些和eMMC、SD的协议中要求的,要符合协议。接下来整理几张图来介绍。 eMMC 模式介绍 一般情况下我们项目中都是会支持到HS400 8bit 1.8V,最大时钟频率为200MHZ,通…

会议邀请函:Prometheus开源无人机平台-无人机追踪无人车代码实战|第四届中国智能汽车创新大会

扫描上方海报二维码&#xff0c;参与报名 阿木实验室&#xff1a;为机器人研发提供开源软硬件工具和课程服务&#xff0c;让研发更高效&#xff01; 技术发展的日新月异&#xff0c;阿木实验室将紧跟技术的脚步&#xff0c;不断把机器人行业最新的技术和硬件推荐给大家。如果你…

C#【进阶】委托和事件

委托和事件 文章目录 1、委托1、委托概念2、基本语法3、定义自定义委托4、使用自定义委托5、委托变量可以存储多个函数6、系统定义好的委托思考 怪物死亡数据更新 2、事件1、事件概念2、事件的使用3、为什么有事件思考 热水器 3、匿名函数1、匿名函数概念2、基本语法3、使用4、…

iLogtail 社区开源之夏活动来了!

作者&#xff1a;玄飏 在这个充满活力的夏日&#xff0c;随着阳光一同灿烂的是开源精神的光辉与创新的火花。iLogtail 社区高兴地宣布&#xff0c;我们正式加入开源之夏 2024 的行列&#xff0c;诚邀每一位怀揣梦想与激情的学生开发者&#xff0c;共同开启一场探索技术前沿、贡…

机器学习入门介绍

各位大佬好 &#xff0c;这里是阿川的博客 &#xff0c; 祝您变得更强 个人主页&#xff1a;在线OJ的阿川 大佬的支持和鼓励&#xff0c;将是我成长路上最大的动力 阿川水平有限&#xff0c;如有错误&#xff0c;欢迎大佬指正 目录 三大方向机器学习产生的原因机器如何学习…

基于springboot+vue+Mysql的大学生社团活动平台

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

图文成片剪辑软件,分享3个专业的工具!

在数字化时代&#xff0c;图文成片剪辑软件成为了我们创作与表达的重要工具。无论是想要制作一段引人入胜的短视频&#xff0c;还是打造一幅精美的图文海报&#xff0c;这些软件都能助你一臂之力。那么&#xff0c;图文成片剪辑软件的方法有哪些&#xff1f;又有哪些值得一试的…

PHP开发中的不安全反序列化

序列化是开发语言中将某个对象转换为一串字节流的过程&#xff0c;转换后的字节流可以方便存储在数据库中&#xff0c;也可以方便在网络中进行传输。而反序列化则是将数据库取出的字节流或从网络上接收到的字节流反向转换为对象的过程。概念虽如此&#xff0c;但不同的开发语言…

ASP.NET在线二手交易系统的设计与实现

摘 要 随着当今社会信息技术的进步&#xff0c;基于互联网的各种应用日益受到了人们的重视&#xff0c;二手商品的重新利用也逐渐被人们关注&#xff0c;二手交易系统就在这种形势下产生了&#xff0c;它利用网络&#xff0c;改变了人们的购物方式。 本文是基于现代二手交易…

AC/DC电源模块的故障诊断与维修技巧

BOSHIDA AC/DC电源模块的故障诊断与维修技巧 AC/DC电源模块是一种常用的电力转换设备&#xff0c;用于将交流电转换为直流电供给电子设备。然而&#xff0c;由于使用环境和操作不当等原因&#xff0c;电源模块可能会出现故障。本文将介绍AC/DC电源模块的故障诊断与维修技巧。…

什么?你设计接口什么都不考虑?

如果让你设计一个接口&#xff0c;你会考虑哪些问题&#xff1f; 1.接口参数校验 接口的入参和返回值都需要进行校验。 入参是否不能为空&#xff0c;入参的长度限制是多少&#xff0c;入参的格式限制&#xff0c;如邮箱格式限制 返回值是否为空&#xff0c;如果为空的时候是…

不相交集合的数据结构

一、不相交集合的操作 不相交集合的数据结构维护了一组不相交动态集的集合 &#xff0c;用集合中的某个成员作为代表标识集合。 集合在没有修改的情况下每次访问代表得到的答案是相同的&#xff0c;此外在其它一些应用中&#xff0c;可能按照规定选择集合的代表&#xff0c;例如…

WebSocket or SSE?即时通讯的应用策略【送源码】

最近在研究H5推送&#xff0c;发现除了我们常用的WebSocket以外&#xff0c;其实还有一种协议也能实现H5推送&#xff0c;那就是SSE协议。 而且&#xff0c;当前主流的大模型平台&#xff0c;比如ChatGPT、通义千问、文心一言&#xff0c;对话时采用的就是SSE。 什么是SSE协议…

100m/s高速轧制钢材 八轴测径仪检测毫无压力

关键词&#xff1a;八轴测径仪,在线测径仪,钢材测径仪,高速轧制 随着技术的提升&#xff0c;钢材的生产速度越来越快&#xff0c;一些高速生产的钢材&#xff0c;生产速度甚至达到了100m/s&#xff0c;这是一个非常快的速度。 如果汽车以120公里/小时的速度行驶&#xff0c;那么…

Unity WebGL全屏显示

一、删除footer节点 二、删除最下面点击事件绑定 修改Canvas宽高 canvas.style.width "960px"; canvas.style.height "600px"; 改成 canvas.style.width document.documentElement.clientWidth"px"; canvas.style.height document.document…

行为驱动开源免费接口测试框架:karate

什么是行为驱动测试&#xff1a; 行为驱动测试&#xff08;Behavior-Driven Testing&#xff0c;简称 BDT&#xff09;是一种测试方法&#xff0c;旨在通过描述系统行为和功能来编写测试用例。BDT的重点是从用户的角度出发&#xff0c;描述系统应该如何行为&#xff0c;而不是专…