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.hqwc.cn/news/705433.html

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

相关文章

org.springframework.jdbc.BadSqlGrammarException

Cause: java.sql.SQLSyntaxErrorException: Table ‘web.emp’ doesn’t exist 产生原因&#xff1a;web表找不到&#xff0c;所以可能数据库配置错误 spring.datasource.urljdbc:mysql://localhost:3306/web02 更改完成后运行成功

slugify,slug格式转换工具

目录 前言 安装 特性 基本功能 生成简单的Slug 处理特殊字符 Unicode支持 高级功能 自定义替换规则 过滤停用词 使用不同的分隔符 处理多种语言 实际应用场景 网站和博客的SEO优化 电子商务平台的产品链接 数据清洗和预处理 总结 前言 在Web开发中&#xff0c;生成易于…

【Linux】进程间通信(IPC)

在Linux操作系统中&#xff0c;进程间通信&#xff08;Inter-Process Communication, IPC&#xff09;是多任务编程中的核心概念之一。它允许不同进程之间共享数据、传递消息和同步执行&#xff0c;是构建复杂应用程序的基础。本文将深入浅出地介绍Linux下的几种主要IPC机制&am…

这个notebook集合,赞

这几天在Github上看到一个数据科学仓库&#xff0c;汇总了很多Python notebook代码&#xff0c;主要是数据方向。 项目地址&#xff1a; https://github.com/donnemartin/data-science-ipython-notebooks 其中包括了pandas、numpy、matplotlib、scikit-learn、tensorflow、sp…

提升用户体验:Xinstall免邀请码功能详解

在移动互联网时代&#xff0c;App的推广和运营显得尤为重要。然而&#xff0c;传统的App推广方式往往需要用户填写繁琐的邀请码&#xff0c;这不仅降低了用户体验&#xff0c;还影响了推广效果。幸运的是&#xff0c;Xinstall作为国内专业的App全渠道统计服务商&#xff0c;推出…

线上网页点击菜单没有反应 报错ChunkLoadError:Loading chunk chunk-***** failed

现象 点击菜单无反应并且控制台报错Loading chunk chunk-***** failed 具体错误现象截图如下 分析 在线上页面已经打开的情况下&#xff0c;重新打包部署了前端项目。每次打包&#xff0c;js文件的hash值都会发生改变&#xff0c;因为我们的路由采用了懒加载&#xff0c;未…

Android Studio kotlin 转 Java

一. 随笔记录 java代码可以转化成kotlin代码&#xff0c;当然 Kotlin 反过来也可以转java 在Android Studio中 可以很方便的操作 AS 环境&#xff1a;Android Studio Iguana | 2023.2.1 二. 操作步骤 1.步骤 顶部Tools ----->Kotlin ------>Show Kotlin Bytecode 步…

在另外一个页面,让另外一个页面弹框显示操作(调佣公共的弹框)vue

大概意思是&#xff0c;登录弹框在另外一个页面中&#xff0c;而当前页面不存在&#xff0c;在当前页面中判断如果token不存在&#xff0c;就弹框出登录的弹框 最后一行 window.location.href … 如果当前用户已登录&#xff0c;则执行后续操作(注意此处&#xff0c;可不要)

EDA设计学习笔记2:STM32F103C8T6最小系统板的仿绘

今日开始仿制练习一个STM32F103C8T6最小系统板&#xff0c;通过对这个最小系统板的仿制&#xff0c;达到对自己PCB设计的练习的目的&#xff0c;最终目标是自己设计出一块PCB&#xff0c;做一个OLED的桌面小摆件...... 也不知道画出来能不能用..... 目录 主控芯片的搜索与放置…

战网国际服加速器用哪个好 暴雪战网好用加速器介绍

战网国际版&#xff0c;又称Battle.net环球版&#xff0c;是暴雪娱乐操盘的全球性游戏互动平台&#xff0c;它跨越地理界限&#xff0c;服务于全球游戏爱好者。与地区限定版本相异&#xff0c;国际版赋予玩家自由进入暴雪旗下众多经典游戏的权利&#xff0c;无论身处何方&#…

Sql Server 2016数据库定时备份

一、 配置备份计划任务 选中“维护计划“--右键--“维护计划向导” 完成

uniapp小程序控制页面元素滚动指定距离

要实现页面元素滚动&#xff0c;最好还是使用 scroll-view 来实现&#xff0c;官方文档地址&#xff1a;scroll-view | uni-app官网 通过设置scroll事件来实现滚动监听&#xff0c;当滚动的元素的时候&#xff0c;就会触发这个事件&#xff0c;并且事件里面包含有滚动距离&…