登录功能-token校验用户是否为登录态
1、Redis环境的准备:使用docker拉取Redis镜像
· 卸载掉已安装的docker,确保yum包更新到最新: [卸载旧版本(如果安装过旧版本的话)]
sudo yum remove docker docker-common docker-selinux dockesr-engine
·安装
yum install -y yum-utils device-mapper-persistent-data lvm2
· 安装阿里云镜像,提高镜像拉取速度:
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
· 安装
yum install -y docker-ce docker-ce-cli containerd.io
·创建文件夹
mkdir -p /opt/docker
·查看docker版本,查询得到表示docker安装成功:docker -v
![img](file:///C:\Users\洛\AppData\Local\Temp\ksohtml24328\wps11.jpg)
·查询docker的状态
systemctl status docker
dead:未启动
active:启动成功
2、Docker拉取Redis镜像,并启动
·查看docker下有哪些镜像【没有Redis则去拉取】:
docker images
·docker拉取镜像【docker pull redis:指定版本,没有指定则默认拉取最新版本】
docker pull redis
· 启动Redis容器前的准备工作:
配置redis.conf文件
新建路径:
mkdir -p /usr/local/redis-docker-image/conf
新建redis.conf文件:
touch /usr/local/redis-docker-image/conf/redis.conf
打开文件:
gedit /usr/local/redis-docker-image/conf/redis.conf
内容编写如下:
bind 0.0.0.0 #任何IP都可以接入
port 6379
appendonly yes #数据持久化
最后保存文件。
配置data存储路径:
新建路径:
mkdir -p /usr/local/redis-docker-image/data
· 创建并启动Redis容器
docker run -p 6379:6379 --name redis1 -v /usr/local/redis-docker-image/data:/data -v /usr/local/redis-docker-image/conf/redis.conf:/etc/redis/redis.conf -d redis redis-server /etc/redis/redis.conf --appendonly yes
命令解析:
-p:指明虚拟机端口到主机端口的映射,冒号前面表示主机的;表示将容器内暴露的6379端口映射到宿主机指定的6379端口
--name:指明容器的名字为redis1
-v:目录映射,容器目录挂载到宿主机目录,格式: <host目录>:<容器目录>
-v /usr/local/redis-docker-image/data:/data数据文件间的映射
-v /usr/local/redis-docker-image/conf/redis.conf:/etc/redis/redis.conf配置文件的映射
-d 表示容器启动时在后台运行
redis:表示要启动运行的镜像名称
--appendonly yes 表示数据持久化
· 执行
docker ps
查看容器是否成功启动,status为up表示成功启动
· 启动Redis客户端
docker exec -it redis1 redis-cli -h 192.168.xx.xx
redis1 :容器名称,上一步--name所指定
-h :在哪个IP下开启,可指定自己当前虚拟机的IP
3、项目连接Redis
依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.7.3</version>
</dependency>
配置文件application.yaml:
spring:
data:
redis:
host: 192.168.**.** #redis所在服务器的IP地址
port: 6379 #端口号
4、已登录状态token键值存入Redis
controller.java 控制器
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.example.service.Service;
@RestController
@RequestMapping("/login")
public class Controller {
@Autowired
private Service service;
@PostMapping("/toLogin")
public Resultful login(@RequestBody TwUserDTO twUserDTO){
TwUserVO twUserVO = service.login(twUserDTO);
return Resultful.build(twUserVO, ResultfulCodeEnum.SUCCESS);//Resultful:自定义统一返回,ResultfulCodeEnum:自定义枚举类
}
}
Service.java 接口
public interface Service {
public TwUserVO login(TwUserDTO twUserDTO);//TwUserDTO:自定义封装提交参数的类
}
ServiceImpl.java 实现类
import com.example.service.Service;
import com.example.mapper.Mapper;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.DigestUtils;
import java.util.UUID;
@Service
public class ServiceImpl implements Service {
@Resource
private Mapper userMapper;
@Resource
private RedisTemplate<String ,String> redisTemplate;
@Override
//登录
public TwUserVO login(TwUserDTO twUserDTO) {//TwUserVO:自定义的返回类
/** TwUserDTO: 手机号码 phoneNumber; 密码 password; **/
//1、获取提交的电话号码
String phoneNumber=twUserDTO.getPhoneNumber();
//2、根据电话号码查询数据表
TwUser twUser=Mapper.selectUserInfoByPhone(phoneNumber);//TwUser:自定义实体类
//3、若根据电话号码查询不到对应信息,即用户不存在,返回错误信息
if(twUser == null){
throw new RuntimeException("用户名不存在");//不雅观,可后面自行修改
}
//4、如果根据用户名查询到用户信息,表示用户存在
String database_password = twUser.getPassword();
//数据表中存储的密码为密文,而用户页面输入为明文
//需把输入的密码加密,再与数据库中的比对
String input_password = DigestUtils.md5DigestAsHex(twUserDTO.getPassword().getBytes());
//5、获取输入的密码,比较输入的密码和查询的密码是否一致
if(!database_password.equals(input_password)){
throw new RuntimeException("密码不正确");
}
//6、密码一致,登录成功,生成用户的唯一标识token(随机生成)
String token = UUID.randomUUID().toString().replaceAll("-","");
//7、把登录成功的用户信息放到redis里面 key:token value:用户信息
//参数分别是 键,值,过期时间,时间单位
redisTemplate.opsForValue().set("user:login"+token,
JSON.toJSONString(twUser),7,TimeUnit.DAYS);
//8、返回TwUserVO对象
TwUserVO twUserVO = new TwUserVO();
twUserVO.setToken(token);
return twUserVO;
Mapper.java
import com.example.pojo.twuser.TwUser;
import org.apache.ibatis.annotations.*;
import org.springframework.stereotype.Component;
@Component
@Mapper
public interface UserMapper {
@Select("select id,userName,password,phoneNumber,state,createTime,modifyTime from tw_user where phoneNumber = #{phoneNumber}")
TwUser selectUserInfoByPhone(@Param("phoneNumber") String phoneNumber);
}
下面是辅助类参考:
Resultful.java
import lombok.Data;
@Data
public class Resultful<T> {
private int code;
private String message;
private T data;
private Resultful(){
}
public Resultful(T data) {
this.code = 200;
this.message = "success";
this.data = data;
}
public Resultful(int code, String message) {
this.code = code;
this.message = message;
this.data = null;
}
//build方法,用于返回数据
public static<T> Resultful<T> build(T body,Integer code,String message){
Resultful<T> resultful = new Resultful<>();
resultful.setCode(code);
resultful.setData(body);
resultful.setMessage(message);
return resultful;
}
//通过枚举构造Resultful对象
public static<T> Resultful build(T body, ResultfulCodeEnum resultfulCodeEnum){
return build(body,resultfulCodeEnum.getCode(),resultfulCodeEnum.getMessage());
}
}
ResultfulCodeEnum.java
import lombok.Getter;
@Getter
public enum ResultfulCodeEnum {
SUCCESS(200,"操作成功"),
LOGIN_ERROR(201,"用户名或者密码错误"),
USER_NAME_IS_EXIST(209,"用户名已经存在"),
CODE_ERROR(505,"系统出错,请联系管理员!");
private Integer code;
private String message;
private ResultfulCodeEnum(Integer code, String message) {
this.code=code;
this.message=message;
}
public Integer getCode(){
return this.code;
}
public String getMessage(){
return this.message;
}
}
TwUserDTO.java
import lombok.Data;
//封装提交的数据
@Data
public class TwUserDTO {
//用户名
private String userName;
//账号(手机号码)
private String phoneNumber;
//密码
private String password;
}
TwUserVO.java
import lombok.Data;
//封装返回数据
@Data
public class TwUserVO {
//令牌
private String token;
}
TwUser.java
import lombok.Data;
import java.util.Date;
//Entity
@Data
public class TwUser {
private String id;
private String userName;
private String phoneNumber;
private String password;
private String state;
private Date createTime;
private Date modifyTime;
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append(" [");
sb.append("Hash = ").append(hashCode());
sb.append(", id=").append(id);
sb.append(", userName=").append(userName);
sb.append(", phoneNumber=").append(phoneNumber);
sb.append(", password=").append(password);
sb.append(", state=").append(state);
sb.append(", createTime=").append(createTime);
sb.append(", modifyTime=").append(modifyTime);
sb.append("]");
return sb.toString();
}
}
5、测试及redis中查询结果
在postman中执行测试,结果如下:
测试成功,回到Redis客户端,执行 keys * 命令即可查询到当前用户登录的token: