当前位置: 首页 > news >正文

Spring Boot音乐服务器项目-登录模块

登录模块->项目结构图

一、项目准备与数据库设计

1. 创建Spring Boot项目

  • 先创建一个Maven项目:

  • 项目结构图如上

2. 数据库设计

-- 创建数据库
CREATE DATABASE IF NOT EXISTS musicserver CHARACTER SET utf8;USE musicserver;-- 用户表
CREATE TABLE user (id INT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(20) NOT NULL,password VARCHAR(255) NOT NULL
);-- 音乐表
CREATE TABLE music (id INT PRIMARY KEY AUTO_INCREMENT,title VARCHAR(50) NOT NULL,singer VARCHAR(30) NOT NULL,time VARCHAR(13) NOT NULL,url VARCHAR(1000) NOT NULL,userid INT(11) NOT NULL
);-- 收藏表
CREATE TABLE lovemusic (id INT PRIMARY KEY AUTO_INCREMENT,user_id INT(11) NOT NULL,music_id INT(11) NOT NULL
);

二、项目配置

整体项目的pom依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.6</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>musicplayer</artifactId>(自己项目名称)<version>0.0.1-SNAPSHOT</version><name>musicplayer</name>(自己项目名称)<description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- mybatis 依赖 --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.2</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- md5 依赖 --><dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.9</version></dependency><!-- security依赖包 (加密)--><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-web</artifactId></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-config</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>
application.properties配置(resources包下)
# 数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/musicserver?characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username=root(自己数据库)
spring.datasource.password=123456(自己数据库)
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver# MyBatis配置
mybatis.mapper-locations=classpath:mybatis/**Mapper.xml# 文件上传大小限制
spring.servlet.multipart.max-file-size=15MB
spring.servlet.multipart.max-request-size=100MB# 日志配置
logging.level.com.example.musicserver.mapper=debug

三、登录模块实现

1. 用户实体类(model->User)
@Data
public class User {private int id;private String username;private String password;
}
2. Mapper接口与XML
// UserMapper.java
@Mapper
public interface UserMapper {User selectByName(String username);
}
<!-- UserMapper.xml -->
<select id="selectByName" resultType="com.example.musicserver.model.User">SELECT * FROM user WHERE username=#{username}
</select>

3. 统一响应信息工具类(tools->ResponseBodyMessage)

@Data
public class ResponseBodyMessage<T> {private int status;private String message;private T data;public ResponseBodyMessage(int status, String message, T data) {this.status = status;this.message = message;this.data = data;}
}

4. 登录控制器(Controller层)

@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserMapper userMapper;@Autowiredprivate BCryptPasswordEncoder bCryptPasswordEncoder;@PostMapping("/login")public ResponseBodyMessage<User> login(@RequestParam String username,@RequestParam String password,HttpServletRequest request) {User userInfo = userMapper.selectByName(username);if (userInfo == null || !bCryptPasswordEncoder.matches(password, userInfo.getPassword())) {return new ResponseBodyMessage<>(-1, "用户名或密码错误", null);}request.getSession().setAttribute(Constant.USERINFO_SESSION_KEY, userInfo);return new ResponseBodyMessage<>(0, "登录成功", userInfo);}
}

注解介绍:

@RestController:@ResponseBody+ @Controller合在⼀起的作⽤。@Controller注解,表明了这 个类是⼀个控制器类 ,@ResponseBody表⽰⽅法的返回值直接以指定的格式写⼊Http response  body中 。 

@RequestMapping:使⽤ @RequestMapping来映射请求,也就是通过它来指定控制器可以处理哪 些URL请求 

@RequestParam:将请求参数绑定到你控制器的⽅法参数上 。

如果这个参数是⾮必传的可以写为: @RequestParam(required = false) ,默认是true.  

5. 常量类(tools->Constant)

public class Constant {public static final String USERINFO_SESSION_KEY = "USERINFO_SESSION_KEY";
}

6. BCrypt加密配置

  • BCrypt加密: 一种加盐的单向Hash,不可逆的加密算法,同一种明文(plaintext),每次加密后的密文都不一样,而且不可反向破解生成明文,破解难度很大。

  • MD5加密: 是不加盐的单向Hash,不可逆的加密算法,同一个密码经过hash的时候生成的是同一个hash值,在大多数的情况下,有些经过md5加密的方法将会被破解。

相关依赖我们在一开始的项目配置就已经加上了,主要就是这几个

<dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifactId>
</dependency>
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.9</version>
</dependency>
<dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-web</artifactId>
</dependency>
<dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-config</artifactId>
</dependency>

接下来就创建⼀个tools包,新建MD5Util类 

package com.example.musicplayer.tools;import org.apache.commons.codec.digest.DigestUtils;/**@Author hy@Description:*/
public class MD5Util {private static final String salt = "1b2i3t4e";public static String md5(String src){return DigestUtils.md5Hex(src);}/*** 第⼀次加密 :模拟前端⾃⼰加密,然后传到后端* @param inputPass* @return*/public static String inputPassToFormPass(String inputPass){String str = ""+salt.charAt(1) + salt.charAt(3) + inputPass + salt.charAt(5) + salt.charAt(6);return md5(str);}/*** 第2次MD5加密* @param formPass 前端加密过的密码,传给后端进⾏第2次加密* @param salt ⽤⼾数据库当中的盐值* @return*/public static String formPassToDBPass(String formPass,String salt){String str = ""+salt.charAt(0)+salt.charAt(2) + formPass+salt.charAt(5)+ salt.charAt(4);return md5(str);}/*** 上⾯两个函数合到⼀起进⾏调⽤* @param inputPass* @param saltDB* @return*/public static String inputPassToDbPass(String inputPass, String saltDB) {String formPass = inputPassToFormPass(inputPass);String dbPass = formPassToDBPass(formPass, saltDB);return dbPass;}public static void main(String[] args) {System.out.println("对⽤⼾输⼊密码进⾏第1次加密:"+inputPassToFormPass("123456"));System.out.println("对⽤⼾输⼊密码进⾏第2次加密:"+formPassToDBPass(inputPassToFormPass("123456"),"1b2i3t4e"));System.out.println("对⽤⼾输⼊密码进⾏第2次加密:"+inputPassToDbPass("123456", "1b2i3t4e"));}
}

创建⼀个tools包,新建BCryptTest类 

package com.example.musicplayer.tools;import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;/*** @Author 12629* @Date 2022/4/11 14:29* @Description:*/
public class BCryptTest {public static void main(String[] args) {//模拟从前端获得的密码String password = "123456";BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();String newPassword = bCryptPasswordEncoder.encode(password);System.out.println("加密的密码为: "+newPassword);//使用matches方法进行密码的校验boolean same_password_result = bCryptPasswordEncoder.matches(password,newPassword);//返回trueSystem.out.println("加密的密码和正确密码对比结果: "+same_password_result);boolean other_password_result = bCryptPasswordEncoder.matches("987654",newPassword);//返回falseSystem.out.println("加密的密码和错误的密码对比结果: " + other_password_result);}
}

基于此我们来实现加密登录!

UserMapper新增逻辑

@Mapperpublic interface UserMapper {User login(User loginUser);//username⽤⼾名是唯⼀的 User selectByName(String username);
}

 UserMapper.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.example.musicserver.mapper.UserMapper"><select id="login" resultType="com.example.musicserver.model.User">select * from user where username=#{username} and password=#{password}</select><select id="selectByName" resultType="com.example.musicserver.model.User">select * from user where username=#{username}</select>
</mapper>

修改UserController类

@RestController//@ResponseBody + @Controller合在⼀起的作⽤ @RequestMapping("/user")//使⽤ @RequestMapping 来映射请求,也就是通过它来指定控制器可
以处理哪些URL请求 public class UserController {@Autowiredprivate UserMapper userMapper;@Autowired//在⾃动装配之前,需要完成注⼊,我们再AppConfig中进⾏注⼊ private BCryptPasswordEncoder bCryptPasswordEncoder;@RequestMapping("/login")public ResponseBodyMessage<User> login(@RequestParam String username, @RequestParam String password, HttpServletRequest request) {User loginUser = new User();loginUser.setUsername(username);loginUser.setPassword(password);System.out.println(loginUser);User userInfo = userMapper.selectByName(username);if(userInfo == null) {return new ResponseBodyMessage<>(-1,"⽤⼾名或者密码错误",userInfo);}else {if(!bCryptPasswordEncoder.matches(password,userInfo.getPassword())) {return new ResponseBodyMessage<>(-1,"⽤⼾名或者密码错
误",userInfo);}request.getSession().setAttribute(Constant.USERINFO_SESSION_KEY,userInfo);return new ResponseBodyMessage<>(0,"登录成功",userInfo);}}
}

@Autowired:可以更准确地控制应该在何处以及如何进⾏⾃动装配。

此注解⽤于在setter⽅法,构造 函数,具有任意名称或多个参数的属性或⽅法上⾃动装配bean。默认情况下,它是类型驱动的注⼊ 

上面我们提到了在⾃动装配之前,需要完成注⼊,我们再AppConfig中进⾏注⼊

创建包config,新建AppConfig类

@Configuration
public class AppConfig {@Beanpublic BCryptPasswordEncoder getBCryptPasswordEncoder() {return new BCryptPasswordEncoder();}
}

7. 启动类配置

@SpringBootApplication(exclude = {SecurityAutoConfiguration.class})
public class MusicserverApplication {public static void main(String[] args) {SpringApplication.run(MusicserverApplication.class, args);}
}

四、密码加密原理

BCrypt vs MD5对比:

特性BCryptMD5
安全性高(每次加密结果不同)中(彩虹表可破解)
密文长度60位32位
盐值处理自动生成随机盐需手动加盐
破解难度极高中等
适用场景高安全需求(如金融)一般安全需求

五、功能测试

登录测试:

  1. 使用Postman发送POST请求

  2. URL:http://localhost:8080/user/login

  3. 参数:username=bit&password=123456

  4. 成功响应:

{"status": 0,"message": "登录成功","data": {"id": ,"username": "","password": ""}
}

这是我自己成功的数据

这是错误的数据,因为数据库就没有这组

所有内容在:Jared/音乐服务器 - 码云

http://www.lryc.cn/news/596533.html

相关文章:

  • 【论文阅读】Fast-BEV: A Fast and Strong Bird’s-Eye View Perception Baseline
  • 基于VU13P的百G光纤FMC高性能处理板
  • Rust实战:决策树与随机森林实现
  • 板凳-------Mysql cookbook学习 (十二--------5)
  • 【RAG优化】PDF复杂表格解析问题分析
  • 阶段1--Linux中的文件服务器(FTP、NAS、SSH)
  • 从差异到协同:OKR 与 KPI 的管理逻辑,Moka 让适配更简单
  • 苹果app应用ipa文件程序开发后如何运行到苹果iOS真机上测试?
  • C# 析构函数
  • 【论文阅读 | TIV 2024 | CDC-YOLOFusion:利用跨尺度动态卷积融合实现可见光-红外目标检测】
  • 2025年07月22日Github流行趋势
  • 坑机介绍学习研究
  • 激活函数Focal Loss 详解​
  • 数组——初识数据结构
  • DMZ网络安全基础知识
  • [3-02-02].第04节:开发应用 - RequestMapping注解的属性2
  • Fluent许可与网络安全策略
  • 【kubernetes】-2 K8S的资源管理
  • Java数据结构——ArrayList
  • 【黑马SpringCloud微服务开发与实战】(五)微服务保护
  • 嵌入式学习-土堆目标检测(3)-day27
  • 【自定义一个简单的CNN模型】——深度学习.卷积神经网络
  • 【Java】SVN 版本控制软件的快速安装(可视化)
  • 洛谷刷题7..22
  • (Arxiv-2025)HiDream-I1:一种高效图像生成基础模型,采用稀疏扩散Transformer
  • CMake实践:CMake3.30版本之前和之后链接boost的方式差异
  • Day20-二叉树基础知识
  • 智能Agent场景实战指南 Day 18:Agent决策树与规划能力
  • Java 动态导出 Word 登记表:多人员、分页、动态表格的最佳实践
  • IntelliJ IDEA (2024.3.1)优雅导入 Maven 项目的两种方式详解