小序

榜首篇是后端整体登录出发,完成了一个企业级的用户中心项目:/post/722079…

第二篇文章是前后端的交互出发,讲述了服务间的通信:

/post/722172…

而本篇文章将会告诉您:

  1. session到底是个啥?
  2. 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咱们就能获取到用户信息!

搞懂Session就是现在!

以上 便是 刚刚的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就是现在!

保存在不同的服务中无法共享session!

也便是说A服务器存储一个用户的服务,当咱们网购的时分翻开订单时(此刻在B服务器) 可是B服务器 并不认识 A服务器中记载的session

不知道读者能不能了解!!!

Redis+Session

搞懂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的命名格局呢?

  1. spring-boot-starter-xx 表明这是一个spring官方的starter
  2. 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的运用场景了

  1. 轻量化、不占用内存
  2. 无序、结构简单
  3. 还有一点 jwt 更多的是跨域的效果!

可是在实际的使用场景中还是session+redis愈加适用!

因为虽然session比较jwt失去了简单性、可是session 的方式愈加的灵敏(jwt的生成无法修改)即便这样会占用部分内存。

但这点内存比较起灵敏性,显得微不足道!

结尾

本篇完好就到此结束了~

我是荔枝程序员、一名大三的在校生~

作者继续找实习中求内推!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。