登录优化redis
解决在更改密码后 原先的旧令牌也能使用
优化后要让令牌主动失效
令牌主动失效机制
- 登录成功后,给浏览器响应令牌的同时,把该令牌存储到redis中
- LoginInterceptor拦截器中,需要验证浏览器携带的令牌,并同时需要获取到redis中存储的与之相同的令牌
- 当用户修改密码成功后,删除redis中存储的旧令牌
SpringBoot集成redis
-
导入spring-boot-starter-data-redis起步依赖
- 起步依赖中会自动往lc容器里面注入StringRedisTemlate对象
<!--redis坐标-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
-
在yml配置文件中, 配置redis连接信息
- port:6379是默认端口号
-
调用API(StringRedisTemplate)完成字符串的存取操作
创建一个RedisTest类
package com.itheima;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import java.util.concurrent.TimeUnit;
@SpringBootTest//如果在测试类上添加了这个注解,那么将来单元测试方法执行之前,会先初始化Spring容器
public class RedisTest {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
public void testSet() {
//往redis中存储一个键值对 StringRedisTemplate
ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
operations.set("name", "zhangsan");
//带上过期时间
operations.set("id","1",15, TimeUnit.SECONDS);
}
@Test
public void testGet(){
//从redis中获取一个键值对 StringRedisTemplate
ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
String name = operations.get("name");
System.out.println(name);
}
}
令牌主动失效机制
- 登录成功后,给浏览器响应令牌的同时,把该令牌存储到redis中
- LoginInterceptor拦截器中,需要验证浏览器携带的令牌,并同时需要获取到redis中存储的与之相同的令牌
- 当用户修改密码成功后,删除redis中存储的旧令牌
1、在controller的登录里面
@PostMapping("/login")
public Result login(@Pattern(regexp = "^\\S{5,16}$") String username, @Pattern(regexp = "^\\S{5,16}$") String password){
//根据y用户名查询用户信息
User loginUser = userService.findByUsername(username);
//判断用户是否存在
if(loginUser == null){
//不存在
return Result.error("用户名错误");
}
//判断密码是否正确,LoginUser对象中的password是密文
if(Md5Util.getMD5String(password).equals(loginUser.getPassword())){
Map<String,Object> claims = new HashMap<>();
claims.put("id",loginUser.getId());
claims.put("username",loginUser.getUsername());
String token = JwtUtil.genToken(claims);
//把token存储到redis中
ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
operations.set(token,token,6, TimeUnit.HOURS);
return Result.success(token);
}
return Result.error("密码错误");
}
2.在LoginInterceptor
//从redis中获得相同的token
ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
String redisToken = operations.get(token);
if(redisToken == null){
throw new RuntimeException();
}
3.在controller的更改密码里面
//删除redis中对应的token
ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
operations.getOperations().delete(token);
Springboot项目部署
开发好的项目如何部署:
- springboot项目打包的时候需要借助一个打包插件
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.2.3</version>
</plugin>
</plugins>
</build>
- 再把这个jar包发送或拷贝到服务器上
- 在服务器上就可以执行java-jar运行命令
如何 运行:
注意:jar包部署,要求服务器必须有jre环境
属性配置:
1.项目配置文件方式:
弊端:把项目打包成运维或者用户的时候,他们无法直接去修改属性
2.命令行参数方式
3.环境变量方式:
外部配置文件方式
配置优先级
- 项目中resources目录下的application.yml
- Jar包所在目录下的application.yml
- 操作系统环境变量
- 命令行参数
这个中方法的优先级是
命令行参数 >操作系统环境变量>Jar包所在目录下的application.yml>项目中resources目录下的application.yml
多环境开发-Profiles
开发、测试、生产三种环境下配置信息是不同的
SpringBoot提供的Profiles可以用来隔离应用程序配置的各个部分,并在特定环境下指定部分配置生效
#通用配置信息 ,指定生效的环境
spring:
profiles:
active: test
---
# 开发环境
spring:
config:
activate:
on-profile: dev
server:
port: 8081
---
# 测试环境
spring:
config:
activate:
on-profile: test
server:
port: 8082
---
# 生产环境
spring:
config:
activate:
on-profile: pro
server:
port: 8083
#通用配置信息 ,指定生效的环境
#多环境下的共性属性
#如果特点环境中的配置和通用配置有冲突,以特点环境的配置为准
spring:
profiles:
active: test
server:
servlet:
context-path: /aaa
三种环境配置文件写到同一个yml文件中会不好维护
解决:多文件配置
把不同环境的配置信息写到不同文件
SpringBoot多环境开发 分组
在一个环境的yml文件中配置多个配置信息也会不好维护
解决:
把不同的配置信息再分成多个yml文件
application.yml
spring:
profiles:
group:
"dev": devDB,devServer,devSelf
# "test":testDB,testServer,testSelf
# "pro":proDB,proServer,proSelf
active: dev
dev-Server
# 服务器相关性息
server:
port: 8081