spring boot security自定义认证

前言

前置阅读

spring boot security快速使用示例
spring boot security之前后端分离配置

说明

实际场景,我们一般是把用户信息保存在db中(也可能是调用三方接口),需要自定义用户信息加载或认证部分的逻辑,下面提供一个示例。

代码示例

定义用户bean

@AllArgsConstructor
@Data
public class User {private String username;private String password;
}

定义Mapper

示例,代码写死了,并不是实际从数据库或某个存储查询用户信息:

@Component
public class UserMapper {public User select(String username) {return new User(username, "pass");}
}

定义加载用户数据的类

UserDetailsService 是spring security内置的加载用户信息的接口,我们只需要实现这个接口:

@Slf4j
@Component
public class UserDetailsServiceImpl implements UserDetailsService {public static final UserDetails INVALID_USER =new org.springframework.security.core.userdetails.User("invalid_user", "invalid_password", Collections.emptyList());private final UserMapper userMapper;public UserDetailsServiceImpl(UserMapper userMapper) {this.userMapper = userMapper;}@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {// 根据用户名从数据库查询用户信息User user = userMapper.select(username);if (user == null) {/*** 如果没查询到这个用户,考虑两种选择:* 1. 返回一个标记无效用户的常量对象* 2. 返回一个不可能认证通过的用户*/return INVALID_USER;
//            return new User(username, System.currentTimeMillis() + UUID.randomUUID().toString(), Collections.emptyList());}/*** 这里返回的用户密码是否为库里保存的密码,是明文/密文,取决于认证时密码比对部分的实现,每个人的场景不一样,* 因为使用的是不加密的PasswordEncoder,所以可以返回明文*/return new org.springframework.security.core.userdetails.User(username, user.getPassword(), Collections.emptyList());}
}

自定义认证的bean配置

@Configuration
public class WebConfiguration {@Beanpublic PasswordEncoder passwordEncoder() {// 示例,不对密码进行加密处理return NoOpPasswordEncoder.getInstance();}@Beanpublic AuthenticationManager authenticationManager(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {DaoAuthenticationProvider provider = new DaoAuthenticationProvider();// 设置加载用户信息的类provider.setUserDetailsService(userDetailsService);// 比较用户密码的时候,密码加密方式provider.setPasswordEncoder(passwordEncoder);return new ProviderManager(Arrays.asList(provider));}}

注意,因为这个是示例,AuthenticationProvider使用的是spring security的DaoAuthenticationProvider ,在实际场景中,如果不满足可以自定义实现或者继承DaoAuthenticationProvider ,重写其中的:additionalAuthenticationChecks方法,主要就是认证检查的,默认实现如下:

	@Override@SuppressWarnings("deprecation")protected void additionalAuthenticationChecks(UserDetails userDetails,UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {if (authentication.getCredentials() == null) {this.logger.debug("Failed to authenticate since no credentials provided");throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));}String presentedPassword = authentication.getCredentials().toString();// 就是比对下请求传过来的密码和根据该用户查询的密码是否一致,passwordEncoder是根据不同的加密算法进行加密,示例我们用的是NoOpPasswordEncoder,也就是原始明文比对if (!this.passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {this.logger.debug("Failed to authenticate since password does not match stored value");throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));}}

定义登录接口

@RequestMapping("/login")
@RestController
public class LoginController {private final AuthenticationManager authenticationManager;public LoginController(AuthenticationManager authenticationManager) {this.authenticationManager = authenticationManager;}@PostMapping()public Object login(@RequestBody User user) {try {// 使用定义的AuthenticationManager进行认证处理Authentication authenticate = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()));// 认证通过,设置到当前上下文,如果当前认证过程后续还有处理的逻辑需要的话。这个示例是没有必要了SecurityContextHolder.getContext().setAuthentication(authenticate);return "login success";}catch (Exception e) {return "login failed";}}/*** 获取验证码,需要的话,可以提供一个验证码获取的接口,在上面的login里把验证码传进来进行比对*/@GetMapping("/captcha")public Object captcha() {return "1234";}
}

自定义HttpSecurity

@Component
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {// 在这里自定义配置http.authorizeRequests()// 登录相关接口都允许访问.antMatchers("/login/**").permitAll().anyRequest().authenticated().and().exceptionHandling()// 认证失败返回401状态码,前端页面可以根据401状态码跳转到登录页面.authenticationEntryPoint((request, response, authException) ->response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase())).and().cors()// csrf是否决定禁用,请自行考量.and().csrf().disable()// 采用http 的基本认证..httpBasic();}
}

测试

示例中,用户密码写死是:pass,
用一个错误的密码试一下,响应登录失败:
在这里插入图片描述
使用正确的密码,响应登录成功:
在这里插入图片描述

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

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

相关文章

bug:file name too long文件名超出系统最大限制

各操作系统支持最长的文件和目录名称长度(Linux、Win、Mac) 今天开发需求的时候发现无法新建文件,提示file name too lang,于是翻阅和查询了一些资料,发现不同操作系统下文件名和目录名最长的长度不同。 操作系统文件名…

小程序主包超1.5MB分包处理流程优化方案

"subPackages": [// 分包1 {"root": "src, // 根目录"pages": [{"path": "views/business/index", // 页面路径"name": "business_index","aliasPath": "/business/index",&…

make/makefile的使用

make/makefile 文章目录 make/makefile初步认识makefile的工作流程依赖关系和依赖方法make的使用 总结 make是一个命令,是一个解释makefile中指令的命令工具,makefile是一个文件,当前目录下的文件,两者搭配使用,完成项…

快速上手dva

Dva 是一个基于 redux 和 redux-saga 的前端框架,它简化了 redux 和 redux-saga 的使用,并且内置了 react-router 和 fetch,所以也支持路由和异步操作。以下是一些基本的 Dva 使用方法: 快速上手 安装:首先&#xff…

异常参数处理:如何处理前端传递的非法参数,确保系统安全稳定

当前端将参数传递给后端时,考虑到各种异常情况,以下是对应的解决示例: 缺少必要的参数: 异常情况:前端未传递必要的参数,导致后端无法正常处理请求。 解决方案:在后端进行参数校验,如…

HarmonyOS学习路之方舟开发框架—学习ArkTS语言(基本语法 二)

自定义组件 创建自定义组件 在ArkUI中,UI显示的内容均为组件,由框架直接提供的称为系统组件,由开发者定义的称为自定义组件。在进行 UI 界面开发时,通常不是简单的将系统组件进行组合使用,而是需要考虑代码可复用性、…

从后验与模型推断视角深入剖析MATLAB中的变分贝叶斯蒙特卡罗(VBMC)算法:理论、代码示例与下载指南

在实践复杂的计算模型时,贝叶斯推断经常被用来进行参数估计和模型比较。其中,变分贝叶斯蒙特卡罗(VBMC)是一种高效的近似推理方法,能够在有限的预算下对具有潜在噪声似然评估的计算模型进行拟合和评估。这种方法并不只提供最优参数向量&#…

Python采集课堂视频教程, m3u8视频解密

前言 嗨喽,大家好呀~这里是爱看美女的茜茜呐 环境使用: Python 3.8 解释器 Pycharm 编辑器 模块使用: requests >>> pip install requests pycryptodome --> pip install pycryptodome re 第三方模块安装方法: win R 输…

7.14~7.15学习总结

Java的前置知识学习时间截至了,慌的一批~~。 看看自己学的,再看看要求学的,简直: 现在继续:IO流里面的Commons_IO的用法: public class Main {public static void main(String[]args) throws IOException…

【C++】多线程编程三(std::mutexstd::mutex、std::lock_guard、std::unique_lock详解)

目录 一、线程间共享数据 1.数据共享和条件竞争 2.避免恶性条件竞争 二、用互斥量来保护共享数据 1. 互斥量机制 2.mutex头文件介绍 三、C中使用互斥量mutex 1. 互斥量mutex使用 2.mutex类成员函数 ① 构造函数 ② lock() ③ unlock() ④ try_lock() 四、使用std::…

如何与ChatGPT愉快地聊天

原文链接:https://mp.weixin.qq.com/s/ui-O4CnT_W51_zqW4krtcQ 人工智能的发展已经走到了一个新的阶段,在这个阶段,人工智能可以像人一样与我们进行深度的文本交互。其中,OpenAI的ChatGPT是一个具有代表性的模型。然而&#xff0…

(02)Cartographer源码无死角解析-(80) 核心要点→local坐标系、子图坐标系、切片坐标系、地图坐标系等相转换与联系

讲解关于slam一系列文章汇总链接:史上最全slam从零开始,针对于本栏目讲解(02)Cartographer源码无死角解析-链接如下: (02)Cartographer源码无死角解析- (00)目录_最新无死角讲解:https://blog.csdn.net/weixin_43013761/article/details/127350885 文末正下方中心提供了本…

UE4/5C++多线程插件制作(二、简单的对Runnable进行封装)

目录 制作流程: FThreadRunnable void FThreadRunnable::SuspendThread(): void FThreadRunnable::AwakenThread(): uint32 FThreadRunnable::Run():

mac安装Golang开发环境及快速入门

目录 一、Mac brew 安装go环境 1.1 安装步骤 1.2 设置GOPATH 及环境变量 1.3 编写第一个go程序 二、快速入门 2.1 快速入门需求 2.2 go学习(自用) 2.2.1 go基础程序 2.2.2 变量声明 2.2.3 常量和枚举 2.2.4 函数与多种返回值 2.2.5 init函数…

18.Lucas-Kanade光流及OpenCV中的calcOpticalFlowPyrLK

文章目录 光流法介绍OpenCV中calcOpticalFlowPyrLK函数补充reference 欢迎访问个人网络日志🌹🌹知行空间🌹🌹 光流法介绍 光流描述了像素在图像中的运动,就像彗星☄划过天空中流动图像。同一个像素,随着时…

vue v-if v-show

1 使用 v-if 指令时,元素的插入和移除是动态的,当元素被移除时,与元素相关的对象和事件处理程序也会被销毁,包括 ACE 编辑器对象。因此,当再次插入元素时,相关的对象和事件处理程序需要重新初始化。 使用 …

使用EasyExcel读写Excel文件

笔者之前一直使用POI读写Excel文件,最近有个需求需要读取大概80万行数据的Excel,使用POI读取到10.2万行左右就卡死不动了,而且CPU占用直接拉满到100%,内存占用也很高。 查找资料后,发现POI提供了读取大量数据的方法&a…

手写对象浅比较(React中pureComponent和Component区别)

PureComponent和Component的区别 PureComponent会给类组件默认加一个shouldComponentUpdate这样的周期函数 //PureComponent类似自动加了这段shouldComponentUpdate(nextProps,nextState){let { props, state } this;// props/state:修改之前的属性状态// nextProps/nextState…

047、TiDB特性_TopSQL

TopSQL 之前 之前没有办法找单个TiKV Server的语句。只能查找整个集群的慢语句。 TopSQL之后 指定TiDB及TiKV实例正在执行的SQL语句CPU开销最多的Top 5 SQL每秒请求数、平均延迟等信息 TopSQL 使用 选择需要观察负载的具体TiDB Server或TiKV实例 观察Top 5 类SQL 查看某…

用IDEA写第一个Spring程序 HelloWorld

用IDEA写第一个Spring程序 HelloWorld 环境 Orcal JDK:1.8.0_341 maven:3.9.3 Spring:5.3.10 IDEA:2023.1.2 1. 安装JDK和IDEA 2. 安装maven并配置环境变量、换源 3. IDEA中maven属性配置,主要是版本和settings文件及…