若依 Spring Security 短信,扫码登录
1. 修改 LoginBody,添加登录类型字段
@Data
public class LoginBody {/*** 用户名*/private String username;/*** 用户密码*/private String password;/*** 验证码*/private String code;/*** 唯一标识*/private String uuid;/*** 登录类型*/private String loginType;
}
2.定义一个常量
package com.ruoyi.common.core.domain.constant;/*** @author Ls* @date 2024/6/4*/
public class LoginTypeConstant {public static final String PASSWORD_LOGIN = "password";public static final String MOBILE_LOGIN = "mobile";public static final String QR_CODE_LOGIN = "qrCode";
}
3.修改登录接口
@PostMapping("/login")public AjaxResult login(@RequestBody LoginBody loginBody) {AjaxResult ajax = AjaxResult.success();loginBody.setLoginType(LoginTypeConstant.MOBILE_LOGIN);// 生成令牌String token = loginService.login(loginBody);ajax.put(Constants.TOKEN, token);return ajax;}
4.重载登录实现类,基本不用改,loginbody 作为 credentials传入UsernamePasswordAuthenticationToken
public String login(LoginBody loginBody) {String username = loginBody.getUsername();
// // 验证码校验
// validateCaptcha(username, code, uuid);
// // 登录前置校验
// loginPreCheck(username, password);// 用户验证Authentication authentication = null;try {UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, loginBody);AuthenticationContextHolder.setContext(authenticationToken);// 该方法会去调用UserDetailsServiceImpl.loadUserByUsernameauthentication = authenticationManager.authenticate(authenticationToken);} catch (Exception e) {if (e instanceof BadCredentialsException) {AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));throw new UserPasswordNotMatchException();} else {AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));throw new ServiceException(e.getMessage());}} finally {AuthenticationContextHolder.clearContext();}AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));LoginUser loginUser = (LoginUser) authentication.getPrincipal();recordLoginInfo(loginUser.getUserId());// 生成tokenreturn tokenService.createToken(loginUser);}
5.自定义MyAuthenticationProvider类
package com.ruoyi.framework.security.mobile;import com.ruoyi.common.core.domain.constant.LoginTypeConstant;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
import com.ruoyi.framework.web.service.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;/*** @author Ls* @date 2024/6/4*/
@Component
public class MyAuthenticationProvider implements AuthenticationProvider {@Autowiredprivate UserDetailsServiceImpl userDetailsService;@Autowiredprivate BCryptPasswordEncoder bCryptPasswordEncoder;@Overridepublic Authentication authenticate(Authentication authentication) throws AuthenticationException, UserPasswordNotMatchException {String name = authentication.getName();LoginBody loginBody = (LoginBody) authentication.getCredentials();String loginType = loginBody.getLoginType();UserDetails user;switch (loginType) {case LoginTypeConstant.PASSWORD_LOGIN:user = userDetailsService.loadUserByUsername(name);String password = loginBody.getPassword();String encoderPassword = bCryptPasswordEncoder.encode(password);// 数据库账号密码的校验能通过就通过if (bCryptPasswordEncoder.matches(password, user.getPassword())) {return new UsernamePasswordAuthenticationToken(user, encoderPassword);}case LoginTypeConstant.MOBILE_LOGIN:user = userDetailsService.loadUserByPhone(loginBody);return new UsernamePasswordAuthenticationToken(user, loginBody.getCode());case LoginTypeConstant.QR_CODE_LOGIN:break;default:break;}// 如果都登录不了,就返回异常输出throw new UserPasswordNotMatchException();}@Overridepublic boolean supports(Class<?> aClass) {return true;}
}
6.用户验证类新增手机号登录 UserDetailsServiceImpl
public UserDetails loadUserByPhone(LoginBody loginBody) throws UsernameNotFoundException {// TODO: 2024/6/4 各种业务效验,这里图省事验证码放在passwordif (!Objects.equals(loginBody.getPassword(), "123456")) {throw new ServiceException("验证码错误");}//这里应该是根据手机号查询,我这里图省事直接拿账号登录String username = loginBody.getUsername();SysUser user = userService.selectUserByUserName(username);return createLoginUser(user);}
7.SecurityConfig调整,配置一下MyAuthenticationProvider
/*** 自定义用户认证逻辑*/@Autowiredprivate MyAuthenticationProvider myAuthenticationProvider;/*** 身份认证接口*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.authenticationProvider(myAuthenticationProvider);}
相关文章:
若依 Spring Security 短信,扫码登录
1. 修改 LoginBody,添加登录类型字段 Data public class LoginBody {/*** 用户名*/private String username;/*** 用户密码*/private String password;/*** 验证码*/private String code;/*** 唯一标识*/private String uuid;/*** 登录类型*/private String logi…...

Web 网页性能优化
Web 网页性能及性能优化 一、Web 性能 Web 性能是 Web 开发的一个重要方面,侧重于网页加载速度以及对用户输入的响应速度 通过优化网站来改善性能,可以在为用户提供更好的体验 网页性能既广泛又非常深入 1. 为什么性能这么重要? 1. 性能…...

JDBC-MySQL
JDBC-MySQL 1.JDBC 操作步骤1.1 DriverManager1.2.Connection对象1.3 Statement1.4 PreparedStatement 1.JDBC 操作步骤 public void quickStart() throws ClassNotFoundException, SQLException {//1、注册驱动 (确认要使用哪个数据库)Class.forName(&…...

MySQL经典练习50题(上)(解析版)
所有笔记、生活分享首发于个人博客 想要获得最佳的阅读体验(无广告且清爽),请访问本篇笔记 MySQL经典练习50题(上) 创建数据库和表 -- 建 表 -- 学 生 表 CREATE TABLE Student( s_id VARCHAR(20), s_name VARCHAR(2…...

每日一题33:数据统计之广告效果
一、每日一题 返回结果示例如下: 示例 1: 输入: Ads 表: ------------------------- | ad_id | user_id | action | ------------------------- | 1 | 1 | Clicked | | 2 | 2 | Clicked | | 3 | 3 | Viewed…...
52、有边数限制的最短路
有边数限制的最短路 题目描述 给定一个n个点m条边的有向图,图中可能存在重边和自环, 边权可能为负数。 请你求出从1号点到n号点的最多经过k条边的最短距离,如果无法从1号点走到n号点,输出impossible。 注意:图中可…...

Spring boot实现基于注解的aop面向切面编程
Spring boot实现基于注解的aop面向切面编程 背景 从最开始使用Spring,AOP和IOC的理念就深入我心。正好,我需要写一个基于注解的AOP,被这个注解修饰的参数和属性,就会被拿到参数并校验参数。 一,引入依赖 当前sprin…...

MySQL之查询性能优化(四)
查询性能优化 MySQL客户端/服务器通信协议 一般来说,不需要去理解MySQL通信协议的内部实现细节,只需要大致理解通信协议是如何工作的。MySQL客户端和服务器之间的通信协议是"半双工"的,这意味着,在任何一个时刻&#…...
定时任务详解
文章目录 定时任务详解JDK自带第三方任务调度框架java有哪些定时任务的框架为什么需要定时任务定时任务扫表的方案有什么缺点Quartzxxl-jobxxl-job详解 elastic-job 定时任务详解 在定时任务中,操作系统或应用程序会利用计时器或定时器来定期检查当前时间是否达到了…...
OnlyOffice DocumentServer 8.0.1编译破解版本(¥100)
OnlyOffice DocumentServer 8.0.1编译破解版本(¥100) 破解20人数限制 更换中文字体 修改源码,根据业务自定义服务 根据源码在本机启动项目,便于开发 将编译好的服务打包docker镜像运行 提供各种docker镜像包&…...

Android 应用权限
文章目录 权限声明uses-permissionpermissionpermission-grouppermission-tree其他uses-feature 权限配置 权限声明 Android权限在AndroidManifest.xml中声明,<permission>、 <permission-group> 、<permission-tree> 和<uses-permission>…...
MATLAB 匿名函数
定义匿名函数定义匿名函数的基本语法如下:示例示例 1:简单数学运算示例 2:字符串操作示例 3:作为参数传递 匿名函数的高级用法使用函数句柄定义多输出函数使用局部变量使用嵌套匿名函数 注意事项 匿名函数( Anonymous…...

Java 新手入门:基础知识点一览
Java 新手入门:基础知识点一览 想要踏入 Java 的编程世界?别担心,这篇文章将用简单易懂的表格形式,带你快速了解 Java 的基础知识点。 一、Java 是什么? 概念解释Java一种面向对象的编程语言,拥有跨平台、…...

三维模型轻量化工具:手工模型、BIM、倾斜摄影等皆可用!
老子云是全球领先的数字孪生引擎技术及服务提供商,它专注于让一切3D模型在全网多端轻量化处理与展示,为行业数字化转型升级与数字孪生应用提供成套的3D可视化技术、产品与服务。 老子云是全球领先的数字孪生引擎技术及服务提供商,它专注于让…...

小程序CI/CD之自动化打包预览并钉钉通知发布进程
小程序打包方式分为两种:手动打包、自动打包 那如何实现 自动打包 呐?我们今天就来聊一聊! 首先,很重要,看 官方文档 这里提到今天我们要聊的“主角” miniprogram-ci miniprogram-ci 是从微信开发者工具中抽离的关于…...
C++使用QtHttpServer开发服务端Server的Http POST接口和客户端Client示例
Client HTTP POST 假设http://127.0.0.1:8888/post/是一个能够接受POST请求的路径,我们想要向它提交一段json数据,用Qt可以这样实现: Suppose we want to make an HTTP POST with json body to http://127.0.0.1:8888/post/. QCoreApplica…...

计算机基础(8)——音频数字化(模电与数电)
💗计算机基础系列文章💗 👉🍀计算机基础(1)——计算机的发展史🍀👉🍀计算机基础(2)——冯诺依曼体系结构🍀👉ἴ…...

手搓单链表(无哨兵位)(C语言)
目录 SLT.h SLT.c SLTtest.c 测试示例 单链表优劣分析 SLT.h #pragma once#include <stdio.h> #include <assert.h> #include <stdlib.h>typedef int SLTDataType;typedef struct SListNode {SLTDataType data;struct SListNode* next; }SLTNode;//打印…...
代码随想录算法训练营第18天|二叉树
513. 找树左下角的值 最左边的结点的特性 1.只能是叶子结点, 2.必须考虑是最底层,所以要考虑树的深度 3.同样的深度考虑左子树 考虑迭代法,层序遍历 递归优点难搞的 /*** Definition for a binary tree node.* function TreeNode(val, left, righ…...

使用tftpd更新开发板内核
我们升级内核可以通过原厂提供的升级软件来进行,比如瑞芯微的RKDevTool.exe,只不过这种方式必须通过指定的OTG升级口,还得借助按键进入loader模式后才可以。 其实还可以利用一些通用的工具来进行升级,比如tftpd工具。 下载地址p…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...

【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...

《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...

《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...