v0.01 后端登录实现
parent
5b53d9502a
commit
fe3da4b1f8
29
pom.xml
29
pom.xml
|
|
@ -38,12 +38,12 @@
|
|||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis.spring.boot</groupId>
|
||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||
<version>3.0.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||
<version>3.5.10.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
|
|
@ -70,6 +70,25 @@
|
|||
<artifactId>spring-security-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- token &jwt 依赖 -->
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-api</artifactId>
|
||||
<version>0.11.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-impl</artifactId>
|
||||
<version>0.11.5</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-jackson</artifactId>
|
||||
<version>0.11.5</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,94 @@
|
|||
package com.bruce.sams.Constant;
|
||||
|
||||
/**
|
||||
* 返回状态码
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class HttpStatus
|
||||
{
|
||||
/**
|
||||
* 操作成功
|
||||
*/
|
||||
public static final int SUCCESS = 200;
|
||||
|
||||
/**
|
||||
* 对象创建成功
|
||||
*/
|
||||
public static final int CREATED = 201;
|
||||
|
||||
/**
|
||||
* 请求已经被接受
|
||||
*/
|
||||
public static final int ACCEPTED = 202;
|
||||
|
||||
/**
|
||||
* 操作已经执行成功,但是没有返回数据
|
||||
*/
|
||||
public static final int NO_CONTENT = 204;
|
||||
|
||||
/**
|
||||
* 资源已被移除
|
||||
*/
|
||||
public static final int MOVED_PERM = 301;
|
||||
|
||||
/**
|
||||
* 重定向
|
||||
*/
|
||||
public static final int SEE_OTHER = 303;
|
||||
|
||||
/**
|
||||
* 资源没有被修改
|
||||
*/
|
||||
public static final int NOT_MODIFIED = 304;
|
||||
|
||||
/**
|
||||
* 参数列表错误(缺少,格式不匹配)
|
||||
*/
|
||||
public static final int BAD_REQUEST = 400;
|
||||
|
||||
/**
|
||||
* 未授权
|
||||
*/
|
||||
public static final int UNAUTHORIZED = 401;
|
||||
|
||||
/**
|
||||
* 访问受限,授权过期
|
||||
*/
|
||||
public static final int FORBIDDEN = 403;
|
||||
|
||||
/**
|
||||
* 资源,服务未找到
|
||||
*/
|
||||
public static final int NOT_FOUND = 404;
|
||||
|
||||
/**
|
||||
* 不允许的http方法
|
||||
*/
|
||||
public static final int BAD_METHOD = 405;
|
||||
|
||||
/**
|
||||
* 资源冲突,或者资源被锁
|
||||
*/
|
||||
public static final int CONFLICT = 409;
|
||||
|
||||
/**
|
||||
* 不支持的数据,媒体类型
|
||||
*/
|
||||
public static final int UNSUPPORTED_TYPE = 415;
|
||||
|
||||
/**
|
||||
* 系统内部错误
|
||||
*/
|
||||
public static final int ERROR = 500;
|
||||
|
||||
/**
|
||||
* 接口未实现
|
||||
*/
|
||||
public static final int NOT_IMPLEMENTED = 501;
|
||||
|
||||
/**
|
||||
* 系统警告消息
|
||||
*/
|
||||
public static final int WARN = 601;
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package com.bruce.sams.Controller;
|
||||
|
||||
import com.bruce.sams.service.SysLoginService;
|
||||
import com.bruce.sams.Utils.AjaxResult;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/login")
|
||||
public class LoginController {
|
||||
|
||||
@Autowired
|
||||
private SysLoginService sysLoginService;
|
||||
|
||||
/**
|
||||
* 用户登录
|
||||
*
|
||||
* @param username 用户名
|
||||
* @param password 密码
|
||||
* @return AjaxResult 包含登录状态和token
|
||||
*/
|
||||
@PostMapping
|
||||
public AjaxResult login(@RequestParam String username, @RequestParam String password) {
|
||||
try {
|
||||
// 调用登录服务,生成Token
|
||||
String token = sysLoginService.login(username, password);
|
||||
|
||||
// 返回成功的响应,并包含生成的Token
|
||||
return AjaxResult.success("登录成功", token);
|
||||
} catch (Exception e) {
|
||||
// 如果捕获到异常,返回错误信息
|
||||
return AjaxResult.error("登录失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.bruce.sams.Controller;
|
||||
|
||||
import com.bruce.sams.service.SysUserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/user")
|
||||
public class UserController {
|
||||
@Autowired
|
||||
private SysUserService userService;
|
||||
|
||||
public Object addUesr(){
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
package com.bruce.sams.Entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 系统用户表
|
||||
* @TableName sys_user
|
||||
*/
|
||||
@TableName(value ="sys_user")
|
||||
@Data
|
||||
public class SysUser {
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 用户角色
|
||||
*/
|
||||
private Long roleId;
|
||||
|
||||
/**
|
||||
* 用户昵称
|
||||
*/
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 真实姓名
|
||||
*/
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
private String passwd;
|
||||
|
||||
/**
|
||||
* 学号/教职工号
|
||||
*/
|
||||
private String schoolId;
|
||||
|
||||
/**
|
||||
* 所属院系
|
||||
*/
|
||||
private Long collegeId;
|
||||
|
||||
/**
|
||||
* 用户邮箱
|
||||
*/
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 手机号码
|
||||
*/
|
||||
private String phonenumber;
|
||||
|
||||
/**
|
||||
* 用户性别(0男 1女 2未知)
|
||||
*/
|
||||
private String sex;
|
||||
|
||||
/**
|
||||
* 头像地址
|
||||
*/
|
||||
private String avatar;
|
||||
|
||||
/**
|
||||
* 帐号状态(0正常 1停用)
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object that) {
|
||||
if (this == that) {
|
||||
return true;
|
||||
}
|
||||
if (that == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != that.getClass()) {
|
||||
return false;
|
||||
}
|
||||
SysUser other = (SysUser) that;
|
||||
return (this.getUserId() == null ? other.getUserId() == null : this.getUserId().equals(other.getUserId()))
|
||||
&& (this.getRoleId() == null ? other.getRoleId() == null : this.getRoleId().equals(other.getRoleId()))
|
||||
&& (this.getNickName() == null ? other.getNickName() == null : this.getNickName().equals(other.getNickName()))
|
||||
&& (this.getUserName() == null ? other.getUserName() == null : this.getUserName().equals(other.getUserName()))
|
||||
&& (this.getPasswd() == null ? other.getPasswd() == null : this.getPasswd().equals(other.getPasswd()))
|
||||
&& (this.getSchoolId() == null ? other.getSchoolId() == null : this.getSchoolId().equals(other.getSchoolId()))
|
||||
&& (this.getCollegeId() == null ? other.getCollegeId() == null : this.getCollegeId().equals(other.getCollegeId()))
|
||||
&& (this.getEmail() == null ? other.getEmail() == null : this.getEmail().equals(other.getEmail()))
|
||||
&& (this.getPhonenumber() == null ? other.getPhonenumber() == null : this.getPhonenumber().equals(other.getPhonenumber()))
|
||||
&& (this.getSex() == null ? other.getSex() == null : this.getSex().equals(other.getSex()))
|
||||
&& (this.getAvatar() == null ? other.getAvatar() == null : this.getAvatar().equals(other.getAvatar()))
|
||||
&& (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus()))
|
||||
&& (this.getRemark() == null ? other.getRemark() == null : this.getRemark().equals(other.getRemark()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((getUserId() == null) ? 0 : getUserId().hashCode());
|
||||
result = prime * result + ((getRoleId() == null) ? 0 : getRoleId().hashCode());
|
||||
result = prime * result + ((getNickName() == null) ? 0 : getNickName().hashCode());
|
||||
result = prime * result + ((getUserName() == null) ? 0 : getUserName().hashCode());
|
||||
result = prime * result + ((getPasswd() == null) ? 0 : getPasswd().hashCode());
|
||||
result = prime * result + ((getSchoolId() == null) ? 0 : getSchoolId().hashCode());
|
||||
result = prime * result + ((getCollegeId() == null) ? 0 : getCollegeId().hashCode());
|
||||
result = prime * result + ((getEmail() == null) ? 0 : getEmail().hashCode());
|
||||
result = prime * result + ((getPhonenumber() == null) ? 0 : getPhonenumber().hashCode());
|
||||
result = prime * result + ((getSex() == null) ? 0 : getSex().hashCode());
|
||||
result = prime * result + ((getAvatar() == null) ? 0 : getAvatar().hashCode());
|
||||
result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode());
|
||||
result = prime * result + ((getRemark() == null) ? 0 : getRemark().hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(getClass().getSimpleName());
|
||||
sb.append(" [");
|
||||
sb.append("Hash = ").append(hashCode());
|
||||
sb.append(", userId=").append(userId);
|
||||
sb.append(", roleId=").append(roleId);
|
||||
sb.append(", nickName=").append(nickName);
|
||||
sb.append(", userName=").append(userName);
|
||||
sb.append(", passwd=").append(passwd);
|
||||
sb.append(", schoolId=").append(schoolId);
|
||||
sb.append(", collegeId=").append(collegeId);
|
||||
sb.append(", email=").append(email);
|
||||
sb.append(", phonenumber=").append(phonenumber);
|
||||
sb.append(", sex=").append(sex);
|
||||
sb.append(", avatar=").append(avatar);
|
||||
sb.append(", status=").append(status);
|
||||
sb.append(", remark=").append(remark);
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package com.bruce.sams.Exception;
|
||||
|
||||
public class CustomException extends RuntimeException {
|
||||
public CustomException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public CustomException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.bruce.sams.Exception.User;
|
||||
|
||||
import com.bruce.sams.Exception.CustomException;
|
||||
|
||||
/**
|
||||
* 密码错误异常
|
||||
*/
|
||||
public class IncorrectPasswordException extends CustomException {
|
||||
public IncorrectPasswordException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.bruce.sams.Exception.User;
|
||||
|
||||
import com.bruce.sams.Exception.CustomException;
|
||||
|
||||
/**
|
||||
* 权限不足异常
|
||||
*/
|
||||
public class InsufficientPermissionsException extends CustomException {
|
||||
public InsufficientPermissionsException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.bruce.sams.Exception.User;
|
||||
|
||||
import com.bruce.sams.Exception.CustomException;
|
||||
|
||||
/**
|
||||
* 无效输入异常
|
||||
*/
|
||||
public class InvalidInputException extends CustomException {
|
||||
public InvalidInputException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.bruce.sams.Exception.User;
|
||||
|
||||
import com.bruce.sams.Exception.CustomException;
|
||||
|
||||
/**
|
||||
* 用户不存在
|
||||
*/
|
||||
public class UserNotFoundException extends CustomException {
|
||||
public UserNotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,215 @@
|
|||
package com.bruce.sams.Utils;
|
||||
|
||||
import com.bruce.sams.Constant.HttpStatus;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 操作消息提醒
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class AjaxResult extends HashMap<String, Object>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 状态码 */
|
||||
public static final String CODE_TAG = "code";
|
||||
|
||||
/** 返回内容 */
|
||||
public static final String MSG_TAG = "msg";
|
||||
|
||||
/** 数据对象 */
|
||||
public static final String DATA_TAG = "data";
|
||||
|
||||
/**
|
||||
* 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。
|
||||
*/
|
||||
public AjaxResult()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化一个新创建的 AjaxResult 对象
|
||||
*
|
||||
* @param code 状态码
|
||||
* @param msg 返回内容
|
||||
*/
|
||||
public AjaxResult(int code, String msg)
|
||||
{
|
||||
super.put(CODE_TAG, code);
|
||||
super.put(MSG_TAG, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化一个新创建的 AjaxResult 对象
|
||||
*
|
||||
* @param code 状态码
|
||||
* @param msg 返回内容
|
||||
* @param data 数据对象
|
||||
*/
|
||||
public AjaxResult(int code, String msg, Object data)
|
||||
{
|
||||
super.put(CODE_TAG, code);
|
||||
super.put(MSG_TAG, msg);
|
||||
if(data!=null){
|
||||
super.put(DATA_TAG, data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回成功消息
|
||||
*
|
||||
* @return 成功消息
|
||||
*/
|
||||
public static AjaxResult success()
|
||||
{
|
||||
return AjaxResult.success("操作成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回成功数据
|
||||
*
|
||||
* @return 成功消息
|
||||
*/
|
||||
public static AjaxResult success(Object data)
|
||||
{
|
||||
return AjaxResult.success("操作成功", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回成功消息
|
||||
*
|
||||
* @param msg 返回内容
|
||||
* @return 成功消息
|
||||
*/
|
||||
public static AjaxResult success(String msg)
|
||||
{
|
||||
return AjaxResult.success(msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回成功消息
|
||||
*
|
||||
* @param msg 返回内容
|
||||
* @param data 数据对象
|
||||
* @return 成功消息
|
||||
*/
|
||||
public static AjaxResult success(String msg, Object data)
|
||||
{
|
||||
return new AjaxResult(HttpStatus.SUCCESS, msg, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回警告消息
|
||||
*
|
||||
* @param msg 返回内容
|
||||
* @return 警告消息
|
||||
*/
|
||||
public static AjaxResult warn(String msg)
|
||||
{
|
||||
return AjaxResult.warn(msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回警告消息
|
||||
*
|
||||
* @param msg 返回内容
|
||||
* @param data 数据对象
|
||||
* @return 警告消息
|
||||
*/
|
||||
public static AjaxResult warn(String msg, Object data)
|
||||
{
|
||||
return new AjaxResult(HttpStatus.WARN, msg, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回错误消息
|
||||
*
|
||||
* @return 错误消息
|
||||
*/
|
||||
public static AjaxResult error()
|
||||
{
|
||||
return AjaxResult.error("操作失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回错误消息
|
||||
*
|
||||
* @param msg 返回内容
|
||||
* @return 错误消息
|
||||
*/
|
||||
public static AjaxResult error(String msg)
|
||||
{
|
||||
return AjaxResult.error(msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回错误消息
|
||||
*
|
||||
* @param msg 返回内容
|
||||
* @param data 数据对象
|
||||
* @return 错误消息
|
||||
*/
|
||||
public static AjaxResult error(String msg, Object data)
|
||||
{
|
||||
return new AjaxResult(HttpStatus.ERROR, msg, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回错误消息
|
||||
*
|
||||
* @param code 状态码
|
||||
* @param msg 返回内容
|
||||
* @return 错误消息
|
||||
*/
|
||||
public static AjaxResult error(int code, String msg)
|
||||
{
|
||||
return new AjaxResult(code, msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为成功消息
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
public boolean isSuccess()
|
||||
{
|
||||
return Objects.equals(HttpStatus.SUCCESS, this.get(CODE_TAG));
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为警告消息
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
public boolean isWarn()
|
||||
{
|
||||
return Objects.equals(HttpStatus.WARN, this.get(CODE_TAG));
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为错误消息
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
public boolean isError()
|
||||
{
|
||||
return Objects.equals(HttpStatus.ERROR, this.get(CODE_TAG));
|
||||
}
|
||||
|
||||
/**
|
||||
* 方便链式调用
|
||||
*
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
* @return 数据对象
|
||||
*/
|
||||
@Override
|
||||
public AjaxResult put(String key, Object value)
|
||||
{
|
||||
super.put(key, value);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package com.bruce.sams.Utils;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.security.crypto.bcrypt.BCrypt;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class PasswordEncoder {
|
||||
|
||||
// 从配置文件中读取 bcrypt 的强度(默认强度为12),用于生成盐值。
|
||||
@Value("${bcrypt.strength:12}") // 如果没有设置,则默认为12
|
||||
private int bcryptStrength;
|
||||
|
||||
|
||||
/**
|
||||
* 密码加密
|
||||
* @param rawPassword 原始密码
|
||||
* @return 密文字符串
|
||||
*/
|
||||
public String encode(String rawPassword) {
|
||||
return BCrypt.hashpw(rawPassword, BCrypt.gensalt(bcryptStrength));
|
||||
}
|
||||
|
||||
/**
|
||||
* 密码验证
|
||||
* @param rawPassword 匹配
|
||||
* @param encodedPassword 存储密文
|
||||
* @return 匹配返回 True,否则返回 False
|
||||
*/
|
||||
public Boolean matches(String rawPassword, String encodedPassword) {
|
||||
return BCrypt.checkpw(rawPassword, encodedPassword);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
package com.bruce.sams.Utils;
|
||||
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.security.Key;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class TokenUtil {
|
||||
|
||||
// 密钥,用于签名和验证Token
|
||||
private static final Key SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);
|
||||
|
||||
// Token过期时间(单位:毫秒)
|
||||
private static final long EXPIRATION_TIME = 3600000; // 1小时
|
||||
|
||||
/**
|
||||
* 生成Token
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 生成的Token
|
||||
*/
|
||||
public static String generateToken(String userId) {
|
||||
Map<String, Object> claims = new HashMap<>();
|
||||
claims.put("userId", userId); // 将用户ID放入Token的负载部分
|
||||
|
||||
return Jwts.builder()
|
||||
.setClaims(claims) // 设置自定义信息
|
||||
.setIssuedAt(new Date(System.currentTimeMillis())) // 设置签发时间
|
||||
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) // 设置过期时间
|
||||
.signWith(SECRET_KEY) // 使用密钥进行签名
|
||||
.compact(); // 生成Token
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证Token是否有效
|
||||
*
|
||||
* @param token Token字符串
|
||||
* @return 是否有效
|
||||
*/
|
||||
public static boolean validateToken(String token) {
|
||||
try {
|
||||
Jwts.parserBuilder()
|
||||
.setSigningKey(SECRET_KEY) // 设置密钥
|
||||
.build()
|
||||
.parseClaimsJws(token); // 解析Token
|
||||
return true; // 如果没有异常,表示Token有效
|
||||
} catch (Exception e) {
|
||||
return false; // 如果解析失败,表示Token无效
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从Token中提取用户ID
|
||||
*
|
||||
* @param token Token字符串
|
||||
* @return 用户ID
|
||||
*/
|
||||
public static String getUserIdFromToken(String token) {
|
||||
Claims claims = Jwts.parserBuilder()
|
||||
.setSigningKey(SECRET_KEY) // 设置密钥
|
||||
.build()
|
||||
.parseClaimsJws(token) // 解析Token
|
||||
.getBody();
|
||||
return claims.get("userId", String.class); // 提取用户ID
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Token的过期时间
|
||||
*
|
||||
* @param token Token字符串
|
||||
* @return 过期时间
|
||||
*/
|
||||
public static Date getExpirationDateFromToken(String token) {
|
||||
Claims claims = Jwts.parserBuilder()
|
||||
.setSigningKey(SECRET_KEY) // 设置密钥
|
||||
.build()
|
||||
.parseClaimsJws(token) // 解析Token
|
||||
.getBody();
|
||||
return claims.getExpiration(); // 获取Token的过期时间
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package com.bruce.sams.mapper;
|
||||
|
||||
import com.bruce.sams.Entity.SysUser;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* @author bruce
|
||||
* @description 针对表【sys_user(系统用户表)】的数据库操作Mapper
|
||||
* @createDate 2025-02-08 00:19:50
|
||||
* @Entity com.bruce.sams.Entity.SysUser
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysUserMapper extends BaseMapper<SysUser> {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package com.bruce.sams.service;
|
||||
|
||||
public interface SysLoginService {
|
||||
/**
|
||||
* 用户登录方法
|
||||
* @param username 用户名
|
||||
* @param password 密码
|
||||
* @return token
|
||||
*/
|
||||
public String login(String username, String password);
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.bruce.sams.service;
|
||||
|
||||
import com.bruce.sams.Entity.SysUser;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* @author bruce
|
||||
* @description 针对表【sys_user(系统用户表)】的数据库操作Service
|
||||
* @createDate 2025-02-08 00:19:50
|
||||
*/
|
||||
public interface SysUserService extends IService<SysUser> {
|
||||
|
||||
/**
|
||||
* 修改密码
|
||||
* @param userId 用户ID
|
||||
* @param newPassword 新密码
|
||||
* @return 修改成功T 失败F
|
||||
*/
|
||||
public boolean changePassword(Long userId, String newPassword);
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package com.bruce.sams.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.bruce.sams.Entity.SysUser;
|
||||
import com.bruce.sams.Exception.User.IncorrectPasswordException;
|
||||
import com.bruce.sams.Exception.User.UserNotFoundException;
|
||||
import com.bruce.sams.Utils.PasswordEncoder;
|
||||
import com.bruce.sams.Utils.TokenUtil;
|
||||
import com.bruce.sams.mapper.SysUserMapper;
|
||||
import com.bruce.sams.service.SysLoginService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class SysLoginServiceImpl extends ServiceImpl<SysUserMapper, SysUser>
|
||||
implements SysLoginService {
|
||||
|
||||
@Resource
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
/**
|
||||
* 用户登录验证
|
||||
* @param schoolId 学号
|
||||
* @param password 原始密码
|
||||
* @return 如果登录成功返回用户信息和Token,否则返回null
|
||||
*/
|
||||
@Override
|
||||
public String login(String schoolId, String password) {
|
||||
// 查找用户
|
||||
SysUser user = this.getOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getSchoolId, schoolId));
|
||||
|
||||
//如果用户不存在,抛出用户未找到异常
|
||||
if (user == null) {
|
||||
throw new UserNotFoundException("用户不存在");
|
||||
}
|
||||
|
||||
// 检查密码是否正确
|
||||
if (!passwordEncoder.matches(password, user.getPasswd())) {
|
||||
throw new IncorrectPasswordException("密码错误");
|
||||
}
|
||||
|
||||
// 登录成功,生成Token
|
||||
|
||||
// 返回Token
|
||||
return TokenUtil.generateToken(user.getUserId().toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
package com.bruce.sams.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.bruce.sams.Entity.SysUser;
|
||||
import com.bruce.sams.Utils.PasswordEncoder;
|
||||
import com.bruce.sams.service.SysUserService;
|
||||
import com.bruce.sams.mapper.SysUserMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author bruce
|
||||
* @description 针对表【sys_user(系统用户表)】的数据库操作Service实现
|
||||
* @createDate 2025-02-08 00:19:50
|
||||
*/
|
||||
@Service
|
||||
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser>
|
||||
implements SysUserService {
|
||||
|
||||
@Resource
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
/**
|
||||
* 新增用户(更改加密)
|
||||
* @param entity 新增用户实体
|
||||
* @return 新增成功T 失败F
|
||||
*/
|
||||
@Override
|
||||
public boolean save(SysUser entity) {
|
||||
// 如果用户输入了密码,则加密后保存
|
||||
if (entity.getPasswd() != null) {
|
||||
entity.setPasswd(passwordEncoder.encode(entity.getPasswd())); // 加密密码
|
||||
}
|
||||
return super.save(entity); // 调用父类方法保存用户
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID更新(更改加密)
|
||||
* @param entity 修改用户实体
|
||||
* @return 新增成功T 失败F
|
||||
*/
|
||||
@Override
|
||||
public boolean updateById(SysUser entity) {
|
||||
// 更新时如果密码字段有变化,则加密新密码
|
||||
if (entity.getPasswd() != null) {
|
||||
entity.setPasswd(passwordEncoder.encode(entity.getPasswd())); // 加密新密码
|
||||
}
|
||||
return super.updateById(entity); // 调用父类方法更新用户信息
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改密码
|
||||
* @param userId 用户ID
|
||||
* @param newPassword 新密码
|
||||
* @return 修改成功T 失败F
|
||||
*/
|
||||
@Override
|
||||
public boolean changePassword(Long userId, String newPassword) {
|
||||
// 根据用户ID获取用户信息
|
||||
SysUser user = this.getById(userId);
|
||||
if (user == null) {
|
||||
throw new RuntimeException("用户不存在"); // 如果用户不存在,抛出异常
|
||||
}
|
||||
// 加密新密码
|
||||
String encodedPassword = passwordEncoder.encode(newPassword);
|
||||
user.setPasswd(encodedPassword); // 设置加密后的新密码
|
||||
return this.updateById(user); // 更新用户信息
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
spring.application.name=SAMS
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
spring:
|
||||
application:
|
||||
name: SAMS
|
||||
|
||||
datasource:
|
||||
url: jdbc:mysql://localhost:3306/SAMS
|
||||
username: root
|
||||
password: admin123
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?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.bruce.sams.mapper.SysUserMapper">
|
||||
|
||||
<resultMap id="BaseResultMap" type="com.bruce.sams.Entity.SysUser">
|
||||
<id property="userId" column="user_id" />
|
||||
<result property="roleId" column="role_id" />
|
||||
<result property="nickName" column="nick_name" />
|
||||
<result property="userName" column="user_name" />
|
||||
<result property="passwd" column="passwd" />
|
||||
<result property="schoolId" column="school_id" />
|
||||
<result property="collegeId" column="college_id" />
|
||||
<result property="email" column="email" />
|
||||
<result property="phonenumber" column="phonenumber" />
|
||||
<result property="sex" column="sex" />
|
||||
<result property="avatar" column="avatar" />
|
||||
<result property="status" column="status" />
|
||||
<result property="remark" column="remark" />
|
||||
</resultMap>
|
||||
|
||||
<sql id="Base_Column_List">
|
||||
user_id,role_id,nick_name,user_name,passwd,school_id,
|
||||
college_id,email,phonenumber,sex,avatar,
|
||||
status,remark
|
||||
</sql>
|
||||
|
||||
|
||||
</mapper>
|
||||
Loading…
Reference in New Issue