小序
榜首篇是后端整体登录出发,完成了一个企业级的用户中心项目:/post/722079…
第二篇文章是前后端的交互出发,讲述了服务间的通信:
/post/722172…
而本篇文章将会告诉您:
- session到底是个啥?
- session 与 jwt的差异?
正文
Session
以登录功能为例(具体能够看榜首篇文章,文章中有git地址,是一个最简单的企业级项目——用户管理体系)
当然,并不会影响您阅览本篇文章的体验!
controller层
@PostMapping("/login")
public BaseResponse<User> userLogin(@RequestBody UserLoginRequest userLoginRequest, HttpServletRequest request) {
if (userLoginRequest == null) {
return ResultUtils.error(ErrorCode.PARAMS_ERROR);
}
String userAccount = userLoginRequest.getUserAccount();
String userPassword = userLoginRequest.getUserPassword();
if (StringUtils.isAnyBlank(userAccount, userPassword)) {
return ResultUtils.error(ErrorCode.PARAMS_ERROR);
}
User user = userService.userLogin(userAccount, userPassword, request);
return ResultUtils.success(user);
}
service接口
/**
* 用户登录
*
* @param userAccount 用户账户
* @param userPassword 用户密码
* @param request
* @return 脱敏后的用户信息
*/
User userLogin(String userAccount, String userPassword, HttpServletRequest request);
service完成层
@Override
public User userLogin(String userAccount, String userPassword, HttpServletRequest request) {
// 1. 校验
if (StringUtils.isAnyBlank(userAccount, userPassword)) {
return null;
}
if (userAccount.length() < 4) {
return null;
}
if (userPassword.length() < 8) {
return null;
}
// 账户不能包含特别字符
String validPattern = "[`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、?]";
Matcher matcher = Pattern.compile(validPattern).matcher(userAccount);
if (matcher.find()) {
return null;
}
// 2. 加密
String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());
// 查询用户是否存在
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("userAccount", userAccount);
queryWrapper.eq("userPassword", encryptPassword);
User user = userMapper.selectOne(queryWrapper);
// 用户不存在
if (user == null) {
log.info("user login failed, userAccount cannot match userPassword");
return null;
}
// 3. 用户脱敏
User safetyUser = getSafetyUser(user);
// 4. 记录用户的登录态
request.getSession().setAttribute(USER_LOGIN_STATE, safetyUser);
return safetyUser;
}
最重要的也便是这句话:
request.getSession().setAttribute(USER_LOGIN_STATE, safetyUser);
它的意思便是将其保存在,session服务器中
而后续前端所携带的cookie中就有这个 经过session的key咱们就能获取到用户信息!

以上 便是 刚刚的login功能,经过 Cookie 中 JSESSIONID 获取到的用户信息
而所谓的注销则是移除session中的数据
/**
* 用户注销
* @param request
*/
@Override
public int userLogout(HttpServletRequest request) {
// 移除登录态
request.getSession().removeAttribute(USER_LOGIN_STATE);
return 1;
}
Session的问题
细心的小伙伴应该就会发现,session应该也有问题吧,没错 咱们看到session便是保存在服务器中的,而session代表的是一次会话,无论是在分布式的使用场景中又或许服务器重启后都会面临session丢失的问题!
分布式场景如下:

保存在不同的服务中无法共享session!
也便是说A服务器存储一个用户的服务,当咱们网购的时分翻开订单时(此刻在B服务器) 可是B服务器 并不认识 A服务器中记载的session
不知道读者能不能了解!!!
Redis+Session

没错经过引进的redis,咱们改变了session的存储形式
由以前的存储在服务器上的形式,更改为存储在数据库中
那么你看哈,引进redis 咱们必定需求下载redis 对吧
下载也很简单,咱们假如没有服务器的话能够下载redis Windows 版本 地址如下:
github.com/MicrosoftAr…
当然,假如您电脑中有reids 那么能够疏忽这一步!
下面咱们已经下载好了,接下来该怎么办呢? 别急、假如咱们想要在spring项目中运用redis 只需求引进一下依靠就好了!
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.6.4</version>
</dependency>
不知道咱们还记不记的starter的命名格局呢?
- spring-boot-starter-xx 表明这是一个spring官方的starter
- xx-spring-boot-starter 这是指非spring官方的starter
也便是说明,上一个依靠是spring官方封装的starter
除此之外还有一些第三方的封装的redis 比方 redssion(适合分布式)jedis (速度快)
等等……
咱们引进了redis 的依靠,外表咱们已经能够将数据写入session了对吧。
这儿,假如咱们学过redis的话,知道读写指令 可能会将session 自己手动写入redis ~
可是,这么简单的工作,必定会有他人帮咱们考虑到!
所以咱们还需求引进一个依靠:
<!-- https://mvnrepository.com/artifact/org.springframework.session/spring-session-data-redis -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>2.6.3</version>
</dependency>
这个依靠的效果便是,咱们不需求履行任何操作,当咱们保存在session中的数据,会经过上面的这个依靠,它会自动帮咱们写入redis中,咱们只需求做的便是在yaml中装备redis:
spring:
redis:
port: 6379
host: localhost
database: 1
jwt与session的差异
其实jwt与session最大的差异便是jwt的无状况性
那么什么是无状况性呢?便是说咱们运用它来进行存储愈加的轻量化,几乎不占用内存只是存储在前端的东西多点!,你能够将jwt了解成一个session整体(key+用户信息)
没错 前后端的交互都会携带着jwt 咱们能够经过jwt 直接获取到用户数据
当然只有key+用户信息是不安全的,所以完好的jwt还会包含着加密的数据~
感兴趣能够看下jwt由哪三部分组成~ 我就不解说了、因为这些都能够在网上搜到、解说的意义不大!
想到这儿你应该就能理解jwt的运用场景了
- 轻量化、不占用内存
- 无序、结构简单
- 还有一点 jwt 更多的是跨域的效果!
可是在实际的使用场景中还是session+redis愈加适用!
因为虽然session比较jwt失去了简单性、可是session 的方式愈加的灵敏(jwt的生成无法修改)即便这样会占用部分内存。
但这点内存比较起灵敏性,显得微不足道!
结尾
本篇完好就到此结束了~
我是荔枝程序员、一名大三的在校生~
作者继续找实习中求内推!