登录密码加密,反向解密
This commit is contained in:
88
src/main/java/com/rj/common/PasswordUtil.java
Normal file
88
src/main/java/com/rj/common/PasswordUtil.java
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
package com.rj.common;
|
||||||
|
|
||||||
|
import org.springframework.util.DigestUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码工具类
|
||||||
|
*
|
||||||
|
* @author 系统生成
|
||||||
|
* @since 2025-08-07
|
||||||
|
*/
|
||||||
|
public class PasswordUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认盐值
|
||||||
|
*/
|
||||||
|
private static final String DEFAULT_SALT = "rj_system_2025";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MD5加密密码
|
||||||
|
*
|
||||||
|
* @param password 原始密码
|
||||||
|
* @return 加密后的密码
|
||||||
|
*/
|
||||||
|
public static String encryptPassword(String password) {
|
||||||
|
return DigestUtils.md5DigestAsHex(password.getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MD5加密密码(带盐值)
|
||||||
|
*
|
||||||
|
* @param password 原始密码
|
||||||
|
* @param salt 盐值
|
||||||
|
* @return 加密后的密码
|
||||||
|
*/
|
||||||
|
public static String encryptPassword(String password, String salt) {
|
||||||
|
String saltedPassword = password + salt;
|
||||||
|
return DigestUtils.md5DigestAsHex(saltedPassword.getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用默认盐值加密密码
|
||||||
|
*
|
||||||
|
* @param password 原始密码
|
||||||
|
* @return 加密后的密码
|
||||||
|
*/
|
||||||
|
public static String encryptPasswordWithDefaultSalt(String password) {
|
||||||
|
return encryptPassword(password, DEFAULT_SALT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证密码
|
||||||
|
*
|
||||||
|
* @param inputPassword 输入的密码
|
||||||
|
* @param encryptedPassword 数据库中存储的加密密码
|
||||||
|
* @return 是否匹配
|
||||||
|
*/
|
||||||
|
public static boolean verifyPassword(String inputPassword, String encryptedPassword) {
|
||||||
|
String inputEncrypted = encryptPassword(inputPassword,DEFAULT_SALT);
|
||||||
|
return inputEncrypted.equals(encryptedPassword);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证密码(带盐值)
|
||||||
|
*
|
||||||
|
* @param inputPassword 输入的密码
|
||||||
|
* @param encryptedPassword 数据库中存储的加密密码
|
||||||
|
* @param salt 盐值
|
||||||
|
* @return 是否匹配
|
||||||
|
*/
|
||||||
|
public static boolean verifyPassword(String inputPassword, String encryptedPassword, String salt) {
|
||||||
|
String inputEncrypted = encryptPassword(inputPassword, DEFAULT_SALT);
|
||||||
|
return inputEncrypted.equals(encryptedPassword);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用默认盐值验证密码
|
||||||
|
*
|
||||||
|
* @param inputPassword 输入的密码
|
||||||
|
* @param encryptedPassword 数据库中存储的加密密码
|
||||||
|
* @return 是否匹配
|
||||||
|
*/
|
||||||
|
public static boolean verifyPasswordWithDefaultSalt(String inputPassword, String encryptedPassword) {
|
||||||
|
return verifyPassword(inputPassword, encryptedPassword, DEFAULT_SALT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
171
src/main/java/com/rj/controller/sys/AuthController.java
Normal file
171
src/main/java/com/rj/controller/sys/AuthController.java
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
package com.rj.controller.sys;
|
||||||
|
|
||||||
|
import com.rj.common.Result;
|
||||||
|
import com.rj.entity.sys.User;
|
||||||
|
import com.rj.pojo.sys.LoginRequest;
|
||||||
|
import com.rj.pojo.sys.LoginResponse;
|
||||||
|
import com.rj.service.sys.IUserService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 认证控制器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author 系统生成
|
||||||
|
* @since 2025-08-07
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/sys/auth")
|
||||||
|
@Tag(name = "认证管理", description = "用户认证相关接口")
|
||||||
|
@Slf4j
|
||||||
|
public class AuthController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IUserService userService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户登录
|
||||||
|
*/
|
||||||
|
@PostMapping("/login")
|
||||||
|
@Operation(summary = "用户登录", description = "根据用户名和密码进行登录验证")
|
||||||
|
public ResponseEntity<Map<String, Object>> login(
|
||||||
|
@Parameter(description = "登录信息", required = true)
|
||||||
|
@Valid @RequestBody LoginRequest loginRequest) {
|
||||||
|
log.info("用户登录:{}", loginRequest);
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
try {
|
||||||
|
LoginResponse loginResponse = userService.login(loginRequest);
|
||||||
|
result.put("success", true);
|
||||||
|
result.put("message", "登录成功");
|
||||||
|
result.put("data", loginResponse);
|
||||||
|
return ResponseEntity.ok(result);
|
||||||
|
} catch (Exception e) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "登录失败:" + e.getMessage());
|
||||||
|
return ResponseEntity.badRequest().body(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "通过token获取用户信息")
|
||||||
|
@GetMapping(value = "/getUserInfoByToken")
|
||||||
|
public ResponseEntity getUserInfoByToken(String token){
|
||||||
|
log.info("通过token获取用户信息:{}", token);
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
// 用户信息/角色信息
|
||||||
|
User user = userService.getUserInfoByToken(token);
|
||||||
|
user.setPassword(null);
|
||||||
|
user.setOriginalPassword(null);
|
||||||
|
result.put("success", true);
|
||||||
|
result.put("data", user);
|
||||||
|
result.put("message", "token验证成功");
|
||||||
|
return ResponseEntity.ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户登出
|
||||||
|
*/
|
||||||
|
@PostMapping("/logout")
|
||||||
|
@Operation(summary = "用户登出", description = "清除用户token,实现登出功能")
|
||||||
|
public ResponseEntity<Map<String, Object>> logout(
|
||||||
|
@Parameter(description = "用户ID", required = true)
|
||||||
|
@RequestParam Integer userId) {
|
||||||
|
log.info("用户登出:{}", userId);
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
try {
|
||||||
|
User user = userService.getById(userId);
|
||||||
|
if (user != null) {
|
||||||
|
// 清除token
|
||||||
|
user.setToken(null);
|
||||||
|
userService.updateById(user);
|
||||||
|
result.put("success", true);
|
||||||
|
result.put("message", "登出成功");
|
||||||
|
return ResponseEntity.ok(result);
|
||||||
|
} else {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "用户不存在");
|
||||||
|
return ResponseEntity.badRequest().body(result);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "登出失败:" + e.getMessage());
|
||||||
|
return ResponseEntity.internalServerError().body(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证token
|
||||||
|
*/
|
||||||
|
@GetMapping("/verify")
|
||||||
|
@Operation(summary = "验证token", description = "验证用户token是否有效")
|
||||||
|
public ResponseEntity<Map<String, Object>> verifyToken(
|
||||||
|
@Parameter(description = "token", required = true)
|
||||||
|
@RequestParam String token) {
|
||||||
|
log.info("验证token:{}", token);
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
try {
|
||||||
|
// 根据token查询用户
|
||||||
|
User user = userService.getUserByToken(token);
|
||||||
|
if (user != null) {
|
||||||
|
result.put("success", true);
|
||||||
|
result.put("message", "token有效");
|
||||||
|
result.put("data", user);
|
||||||
|
return ResponseEntity.ok(result);
|
||||||
|
} else {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "token无效或已过期");
|
||||||
|
return ResponseEntity.badRequest().body(result);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "验证失败:" + e.getMessage());
|
||||||
|
return ResponseEntity.internalServerError().body(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前用户信息
|
||||||
|
*/
|
||||||
|
@GetMapping("/current")
|
||||||
|
@Operation(summary = "获取当前用户信息", description = "根据token获取当前登录用户信息")
|
||||||
|
public ResponseEntity<Map<String, Object>> getCurrentUser(
|
||||||
|
@Parameter(description = "token", required = true)
|
||||||
|
@RequestParam String token) {
|
||||||
|
log.info("获取当前用户信息:{}", token);
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
try {
|
||||||
|
User user = userService.getUserByToken(token);
|
||||||
|
if (user != null) {
|
||||||
|
// 不返回密码等敏感信息
|
||||||
|
user.setPassword(null);
|
||||||
|
result.put("success", true);
|
||||||
|
result.put("message", "获取成功");
|
||||||
|
result.put("data", user);
|
||||||
|
return ResponseEntity.ok(result);
|
||||||
|
} else {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "用户未登录或token已过期");
|
||||||
|
return ResponseEntity.badRequest().body(result);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "获取用户信息失败:" + e.getMessage());
|
||||||
|
return ResponseEntity.internalServerError().body(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
26
src/main/java/com/rj/pojo/sys/LoginRequest.java
Normal file
26
src/main/java/com/rj/pojo/sys/LoginRequest.java
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package com.rj.pojo.sys;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录请求DTO
|
||||||
|
*
|
||||||
|
* @author 系统生成
|
||||||
|
* @since 2025-08-07
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "登录请求")
|
||||||
|
public class LoginRequest {
|
||||||
|
|
||||||
|
@Schema(description = "用户名", required = true, example = "admin")
|
||||||
|
@NotBlank(message = "用户名不能为空")
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
@Schema(description = "密码", required = true, example = "123456")
|
||||||
|
@NotBlank(message = "密码不能为空")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
}
|
||||||
37
src/main/java/com/rj/pojo/sys/LoginResponse.java
Normal file
37
src/main/java/com/rj/pojo/sys/LoginResponse.java
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package com.rj.pojo.sys;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录响应DTO
|
||||||
|
*
|
||||||
|
* @author 系统生成
|
||||||
|
* @since 2025-08-07
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "登录响应")
|
||||||
|
public class LoginResponse {
|
||||||
|
|
||||||
|
@Schema(description = "用户ID")
|
||||||
|
private Integer userId;
|
||||||
|
|
||||||
|
@Schema(description = "用户名")
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
@Schema(description = "邮箱")
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
@Schema(description = "头像")
|
||||||
|
private String avatar;
|
||||||
|
|
||||||
|
@Schema(description = "访问令牌")
|
||||||
|
private String token;
|
||||||
|
|
||||||
|
@Schema(description = "登录时间")
|
||||||
|
private String loginTime;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
25
src/main/resources/sql/test_user_data.sql
Normal file
25
src/main/resources/sql/test_user_data.sql
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
-- 测试用户数据
|
||||||
|
-- 密码都是 123456 的MD5加密值
|
||||||
|
|
||||||
|
-- 插入测试用户
|
||||||
|
INSERT INTO `user` (`user_name`, `email`, `password`, `avatar`) VALUES
|
||||||
|
('admin', 'admin@example.com', 'e10adc3949ba59abbe56e057f20f883e', '/avatar/admin.jpg'),
|
||||||
|
('user1', 'user1@example.com', 'e10adc3949ba59abbe56e057f20f883e', '/avatar/user1.jpg'),
|
||||||
|
('user2', 'user2@example.com', 'e10adc3949ba59abbe56e057f20f883e', '/avatar/user2.jpg'),
|
||||||
|
('test', 'test@example.com', 'e10adc3949ba59abbe56e057f20f883e', '/avatar/test.jpg');
|
||||||
|
|
||||||
|
-- 插入测试角色
|
||||||
|
INSERT INTO `role` (`role_name`) VALUES
|
||||||
|
('管理员'),
|
||||||
|
('普通用户'),
|
||||||
|
('访客');
|
||||||
|
|
||||||
|
-- 插入用户角色关联
|
||||||
|
INSERT INTO `user_role` (`user_id`, `role_id`) VALUES
|
||||||
|
(1, 1), -- admin -> 管理员
|
||||||
|
(2, 2), -- user1 -> 普通用户
|
||||||
|
(3, 2), -- user2 -> 普通用户
|
||||||
|
(4, 3); -- test -> 访客
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
15
src/main/resources/sql/update_user_table.sql
Normal file
15
src/main/resources/sql/update_user_table.sql
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
-- 更新用户表结构,添加原始密码字段
|
||||||
|
-- 执行时间:2025-08-07
|
||||||
|
|
||||||
|
-- 为user表添加original_password字段
|
||||||
|
ALTER TABLE `user`
|
||||||
|
ADD COLUMN `original_password` varchar(255) DEFAULT NULL COMMENT '原始密码'
|
||||||
|
AFTER `password`;
|
||||||
|
|
||||||
|
-- 更新现有用户的原始密码字段(如果密码是123456的MD5值,则设置原始密码为123456)
|
||||||
|
UPDATE `user`
|
||||||
|
SET `original_password` = '123456'
|
||||||
|
WHERE `password` = 'e10adc3949ba59abbe56e057f20f883e';
|
||||||
|
|
||||||
|
-- 为original_password字段添加索引(可选)
|
||||||
|
-- ALTER TABLE `user` ADD INDEX `idx_original_password` (`original_password`);
|
||||||
Reference in New Issue
Block a user