在 Spring Boot 中实现多种方式登录(用户名、手机号、邮箱等)的不正经指南

欢迎来到一场技术与幽默交织的冒险!今天,我们将跳进 Spring Boot 的世界,探索如何通过 用户名手机号邮箱 等多种方式实现登录。想象一下,用户在登录时可以随心所欲地选择——就像你今天早上纠结到底是要喝美式咖啡还是拿铁!而我们要做的就是为他们提供这些选择,确保他们都能毫无阻碍地进入我们的系统。

目标? 用一种轻松而富有趣味的方式带你构建一个支持多种登录方式的 Spring Boot 项目!好了,系好安全带,让我们开始这段奇妙的代码之旅。

一、需求分析

首先,让我们明白我们要做什么。如果你还记得那些老式网站,登录方式非常单一:只允许使用用户名登录,且密码必须是8个字符的 “password123” 这种经典组合。好吧,时代已经不同了,现在的人们懒得记用户名和密码,他们更愿意使用手机、邮箱,甚至脸书、微信等社交账号来登录。为什么? 因为每个人都有点“懒得输入太多字”的心理。

因此,我们的目标很明确——让用户能有更多的选择方式来登录:

  1. 用户名 + 密码(这是经典款)
  2. 手机号 + 密码(这就很潮流了)
  3. 邮箱 + 密码(一看就很高端)

这就像在餐厅点菜——我们提供多样化的菜单,用户随便选,爱吃啥点啥!

二、搭建你的基础工程:项目配置

没有基础设施的建筑就是一场灾难,而没有配置文件的 Spring Boot 项目就是——废的。所以,第一步,我们要确保项目的所有配置正确无误。

在你的 pom.xml 文件中,加入我们即将用到的一些核心依赖。包括 Spring Security(因为我们要玩登录认证嘛)、JPA(因为我们要有地方存储用户信息),以及 MySQL 数据库的连接驱动。

<dependencies><!-- Spring Boot Security 依赖,用于管理我们的登录和认证 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><!-- Spring Boot Data JPA 依赖,用来进行数据库操作 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- Spring Boot Web 依赖,用来处理 Web 请求 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- MySQL Connector 依赖,毕竟数据还是要放进数据库的 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!-- Lombok 用来减少代码量,让我们不用再写那些烦人的 getter/setter --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>
</dependencies>

好了,既然我们已经有了正确的配置依赖,现在就像是我们已经准备好了一杯现磨咖啡,接下来该享受喝咖啡的过程了!

三、数据库设计:让用户信息有个家

每个登录系统都需要一个地方存储用户信息,否则它就像你早上出门忘了带钥匙一样尴尬。我们要创建一个用户表来保存用户名、手机号、邮箱以及密码。这里我们使用 JPA 来简化数据库操作,不必再写那些琐碎的 SQL 语句。

@Entity
@Table(name = "users")
@Data
public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String username;      // 用户名private String password;      // 密码(重要的东西,当然要加密保存)private String email;         // 邮箱private String phoneNumber;   // 手机号
}

你可能会问,为什么不加个字段来存储用户的昵称、性别、兴趣爱好?嗯,那确实也是个不错的想法,但我们今天的重点是登录系统——所以先忍一忍,别跑偏了。

四、用户存储库:我们需要一些查询方式

数据库表已经有了,但我们还需要写一些代码来查询这些用户信息。为此,我们需要创建一个存储库类,用于根据用户名、手机号或者邮箱来查找用户。

public interface UserRepository extends JpaRepository<User, Long> {Optional<User> findByUsername(String username);Optional<User> findByEmail(String email);Optional<User> findByPhoneNumber(String phoneNumber);
}

瞧,这就是我们数据层的三剑客:findByUsernamefindByEmailfindByPhoneNumber。有了它们,我们可以方便地从数据库中查询到用户。

五、用户认证服务:让 Spring Security 成为我们的好帮手

接下来,我们要告诉 Spring Security 如何根据不同的登录信息来加载用户。这部分代码就像是一道考题,告诉系统:“嘿,如果用户输入了个手机号或者邮箱,你该如何处理?”

@Service
public class CustomUserDetailsService implements UserDetailsService {@Autowiredprivate UserRepository userRepository;@Overridepublic UserDetails loadUserByUsername(String loginInput) throws UsernameNotFoundException {Optional<User> userOpt;// 判断输入的登录信息类型,来确定是邮箱、手机号还是用户名if (loginInput.contains("@")) {// 邮箱登录userOpt = userRepository.findByEmail(loginInput);} else if (loginInput.matches("\\d+")) {// 手机号登录userOpt = userRepository.findByPhoneNumber(loginInput);} else {// 用户名登录userOpt = userRepository.findByUsername(loginInput);}// 如果用户不存在,抛出异常User user = userOpt.orElseThrow(() -> new UsernameNotFoundException("用户不存在"));// 返回 Spring Security 所需的 UserDetails 对象return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), new ArrayList<>());}
}

这个类做的事情就像是一个门卫,不管用户输入的是用户名、邮箱,还是手机号,都会验证一遍,确保用户是真实存在的。

六、密码加密:不要让用户的密码变成人人可知的小秘密

安全问题非常重要,如果我们把密码明文存储,那就相当于把家里的钥匙放在门口的地垫下面,绝对是个坏主意。幸运的是,Spring Security 自带了密码加密支持,我们可以使用 BCryptPasswordEncoder 来加密用户密码。

@Bean
public PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();
}

然后在用户注册时,对密码进行加密后再存入数据库:

@Service
public class UserService {@Autowiredprivate UserRepository userRepository;@Autowiredprivate PasswordEncoder passwordEncoder;public void registerUser(User user) {// 密码加密user.setPassword(passwordEncoder.encode(user.getPassword()));userRepository.save(user);}
}

有了这个小魔法,所有密码都会以加密形式存储,即便有人黑进了数据库,也只能看到一串毫无意义的字符。

七、Spring Security 配置:别忘了这位主角

一部电影怎么能没有导演?而我们的导演就是 Spring Security 的配置类。我们将在这里配置登录逻辑,告诉系统如何处理不同的登录方式。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate CustomUserDetailsService userDetailsService;@Autowiredprivate PasswordEncoder passwordEncoder;@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {// 配置认证方式,使用我们自定义的 UserDetailsService 和密码加密方式auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);}@Overrideprotected void configure(HttpSecurity http) throws Exception {// 设置允许哪些 URL 可以被匿名访问http.csrf().disable().authorizeRequests().antMatchers("/login", "/register").permitAll()  // 允许登录和注册页面被访问.anyRequest().authenticated()  // 其他页面都需要认证.and().formLogin().loginPage("/login")  // 设置自定义的登录页面.defaultSuccessUrl("/home", true)  // 登录成功后跳转的页面.permitAll().and().logout().permitAll();}
}

在这段配置中,我们告诉 Spring Security 使用我们自定义的 CustomUserDetailsService 来处理登录请求。我们还设置了登录页面和成功后的重定向页面,显得很专业有木有?

八、最后的话:为用户提供选择,登录就像选咖啡一样简单

现在,我们已经成功搭建了一个支持多种方式登录的系统。不论是使用用户名、手机号还是邮箱,用户都可以自由选择,就像他们早晨选择喝哪种咖啡一样简单。而你,作为这家“咖啡店”的老板,成功地提供了更多的便利和选择!

所以,下次当你看到用户轻松登录时,可以骄傲地拍拍自己的肩膀,毕竟,你让这个世界的登录系统变得更加多样化了。

(Ps:如果用户抱怨登录总是出错,请告诉他们密码不能用“123456”,那样实在太“平庸”了点 😜)

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

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

相关文章

认识RabbitMq和RabbitMq的使用

1 认识RabbitMq RabbitMQ是⼀个消息中间件&#xff0c;也是⼀个生产者消费者模型&#xff0c;它负责接收&#xff0c;存储并转发消息。 2.1 Producer和Consumer Producer&#xff1a;生产者&#xff0c;是RabbitMQServer的客户端&#xff0c;向RabbitMQ发送消息 Consumer&…

性能测试及调优

一、性能测试介绍 1、什么叫做性能测试&#xff1f; &#xff08;1&#xff09;通过某些工具或手段来检测软件的某些指标是否达到了要求&#xff0c;这就是性能测试 &#xff08;2&#xff09;指通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指…

代码纪元——源神重塑无序

简介 源神&#xff0c;真名为张晨斌&#xff0c;原为代码宇宙创世四神之一。代码宇宙在创造之初时空无一物&#xff0c;只有复杂且繁琐的底层代码&#xff0c;智慧神灵每日都困在诸如脚本等复杂的底层框架之中&#xff0c;源神面对这种局面非常不满意&#xff0c;于是源神通过大…

LVGL加载器,led和列表学习(基于正点原子)

加载器部件&#xff08;lv_spinner&#xff09; 加载器部件常用于提示当前任务正在加载。 加载器部件组成部分&#xff1a; 主体(LV_PART_MAIN) 指示器(LV_PART_INDICATOR) 手柄(LV_PART_KNOB) 知识点1&#xff1a;创建加载器部件 lv_obj_t *spinner lv_spinner_creat…

内存不足引发C++程序闪退崩溃问题的分析与总结

目录 1、内存不足一般出现在32位程序中 2、内存不足时会导致malloc或new申请内存失败 2.1、malloc申请内存失败&#xff0c;返回NULL 2.2、new申请内存失败&#xff0c;抛出异常 3、内存不足项目实战案例中相关细节与要点说明 3.1、内存不足导致malloc申请内存失败&#…

docker搭建私有的仓库

docker搭建私有仓库 一、为什么要搭建私有的仓库&#xff1f; 因为在国内&#xff0c;访问&#xff1a;https://hub.docker.com/ 会出现无法访问页面。。。。&#xff08;已经使用了魔法&#xff09; 当然现在也有一些国内的镜像管理网站&#xff0c;比如网易云镜像服务、Dao…

Http 转 https 中 Nginx 的详细配置过程

摘要 本节将简要介绍从 HTTP 到 HTTPS 的配置过程&#xff0c;并完整展示 Nginx 的相关配置信息。 经过两天断断续续的调试&#xff0c;终于将 http 变成 https 了。现在说说这个安装 ssl 证书的过程。 服务器是在某云上。这个过程大致分为三个步骤&#xff1a;申请 ssl 证书、…

神经网络12-Time-Series Transformer (TST)模型

Time-Series Transformer (TST) 是一种基于 Transformer 架构的深度学习模型&#xff0c;专门用于时序数据的建模和预测。TST 是 Transformer 模型的一个变种&#xff0c;针对传统时序模型&#xff08;如 RNN、LSTM&#xff09;在处理长时间依赖、复杂数据关系时的限制而提出的…

【Linux】安装cuda

一、安装nvidia驱动 # 添加nvidia驱动ppa库 sudo add-apt-repository ppa:graphics-drivers/ppa sudo apt update# 查找推荐版本 sudo ubuntu-drivers devices# 安装推荐版本 sudo apt install nvidia-driver-560# 检验nvidia驱动是否安装 nvidia-smi 二、安装cudatoolkit&…

go-web项目通用脚手架

前言 构建go-web项目时&#xff0c;在编写业务逻辑代码之前&#xff0c;还需搭建脚手架&#xff08;框架&#xff09;&#xff1a;进行编写配置文件、整合web框架&#xff08;gin框架&#xff09;和数据库框架&#xff08;sqlx&#xff09;等&#xff0c;搭建脚手架的过程就类…

深度学习图像视觉 RKNN Toolkit2 部署 RK3588S边缘端 过程全记录

深度学习图像视觉 RKNN Toolkit2 部署 RK3588S边缘端 过程全记录 认识RKNN Toolkit2 工程文件学习路线&#xff1a; Anaconda Miniconda安装.condarc 文件配置镜像源自定义conda虚拟环境路径创建Conda虚拟环境 本地训练环境本地转换环境安装 RKNN-Toolkit2&#xff1a;添加 lin…

论文模型设置与实验数据:scBERT

Yang, F., Wang, W., Wang, F. et al. scBERT as a large-scale pretrained deep language model for cell type annotation of single-cell RNA-seq data. Nat Mach Intell 4, 852–866 (2022). https://doi.org/10.1038/s42256-022-00534-z 论文地址&#xff1a;scBERT as a…

Jenkins的环境部署

day22 回顾 Jenkins 简介 官网Jenkins Jenkins Build great things at any scale The leading open source automation server, Jenkins provides hundreds of plugins to support building, deploying and automating any project. 用来构建一切 其实就是用Java写的一个项目…

怎么编译OpenWrt镜像?-基于Widora开发板

1.准备相应的环境&#xff0c;我使用的环境是VMware16ubuntu20.04&#xff0c;如图1所示安装编译所需的依赖包&#xff1b; sudo apt-get install build-essential asciidoc binutils bzip2 gawk gettext git libncurses5-dev libz-dev patch python3 python2.7 unzip zlib1g-…

拉格朗日乘子(Lagrange Multiplier)是数学分析中用于解决带有约束条件的优化问题的一种重要方法,特别是SVM

拉格朗日乘子&#xff08;Lagrange Multiplier&#xff09;是数学分析中用于解决带有约束条件的优化问题的一种重要方法&#xff0c;也称为拉格朗日乘数法。 例如之前博文写的2月7日 SVM&线性回归&逻辑回归在支持向量机&#xff08;SVM&#xff09;中&#xff0c;为了…

Python 获取微博用户信息及作品(完整版)

在当今的社交媒体时代&#xff0c;微博作为一个热门的社交平台&#xff0c;蕴含着海量的用户信息和丰富多样的内容。今天&#xff0c;我将带大家深入了解一段 Python 代码&#xff0c;它能够帮助我们获取微博用户的基本信息以及下载其微博中的相关素材&#xff0c;比如图片等。…

# linux 清理指定目录下,指定时间的历史文件

如何使用这个脚本 1、创建脚本 cleanup.sh #!/bin/bash# 默认值 DEFAULT_DIR"/path/to/default/directory" DEFAULT_DAYS7# 使用方法提示 usage() {echo "Usage: $0 [-d directory] [-t days]"echo " -d 目标目录 (默认为: ${DEFAULT_DIR})"…

MySQL的DELETE(删除数据)详解

MySQL的DELETE语句用于从数据库表中删除记录。与UPDATE语句类似&#xff0c;DELETE语句也非常强大&#xff0c;支持多种用法和选项。本文将详细介绍DELETE语句的基本语法、高级用法、性能优化策略以及注意事项。 1. 基本语法 单表删除 单表删除的基本语法如下&#xff1a; …

C#里怎么样实现多播委托?

C#里怎么样实现多播委托? 如果你想实现一次通知,就可以让多个地方同步执行, 这时候就可以使用多播。 在这里使用委托来实现多播的功能。delegate void dele(int a, int b); 先定义一个委托的形式。 dele del = new dele(Oper.Add); del += new dele(Oper.Sub); 这里添加…

MySQL底层概述—1.InnoDB内存结构

大纲 1.InnoDB引擎架构 2.Buffer Pool 3.Page管理机制之Page页分类 4.Page管理机制之Page页管理 5.Change Buffer 6.Log Buffer 1.InnoDB引擎架构 (1)InnoDB引擎架构图 (2)InnoDB内存结构 (1)InnoDB引擎架构图 下面是InnoDB引擎架构图&#xff0c;主要分为内存结构和磁…