关于session的补充

前面虽然讲解了session和token的区别,大致了解了session的用法以及具体实现的流程

但是在敲瑞吉外卖的时候还是有个问题

先看代码:

@Slf4j
@RestController
@RequestMapping("/employee")
public class EmployeeController {

    @Autowired
    private EmployeeService employeeService;

    @PostMapping("/login")
    public R<Employee> login(HttpServletRequest request, @RequestBody Employee employee) {

        //1.将页面提交的密码password进行md5加密
        String password = employee.getPassword();
        password = DigestUtils.md5DigestAsHex(password.getBytes());

        //2.根据页面提交的用户名username查询数据库
        LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Employee::getUsername, employee.getUsername());
        Employee emp = employeeService.getOne(queryWrapper);

        //3.如果没有查询到则返回登录失败结果
        if (emp == null) {
            return R.error("登录失败");
        }

        //4.密码比对,如果不一致则返回登录失败结果
        if (!emp.getPassword().equals(password)) {
            return R.error("登录失败");
        }

        //5.查看员工状态,如果为已禁用,则返回员工已禁用结果
        if (emp.getStatus() == 0) {
            return R.error("账号已禁用");
        }

        //6.登录成功,将员工id存入Session并返回登录成功结果
        request.getSession().setAttribute("employee", emp.getId());
        return R.success(emp);
    }

    /*
    * 员工退出
    * */

    @PostMapping("/logout")
    public R<String> logout(HttpServletRequest request) {
        //清理session中保存的员工id
        request.getSession().removeAttribute("employee");
        return R.success("退出成功");
    }

}

和之前的代码是一样的,但是这里有个问题,如果有多个用户登录,可以都保存为key值是employee吗?是不是这个代码就不管用了,是不是要改成多个值

答案:

  • 正常来说不会冲突,因为Session 是和用户一一绑定的

  • 每个浏览器(或者说每个用户)在访问服务器时,都会有自己独立的一份 HttpSession

  • 同一个 Session 只对应一个用户的登录状态,所以在这个 Session 里面放一个 "employee" 是没问题的。

简单理解就是:

  • A用户访问时,有自己的 Session,里面有自己的 employee

  • B用户访问时,有另一个 Session,也有自己的 employee

  • 它们互不影响,不会覆盖或冲突。

🔵 Session是区分不同用户的,不是共享的!


什么时候会有问题?

  • 如果是同一个 Session 里,想同时登录多个账号(比如开同一个浏览器不同标签页登录不同账号),

  • 那你就需要考虑Session管理的问题了,比如用不同的 Key(比如 employeeAemployeeB)或者更复杂的机制。

但在绝大多数正常场景(每个用户自己登录自己账号)下, 👉 只用 "employee" 就够了,没问题。


那要不要改成保存多个值呢?

正常后台系统、商城系统:

  • 不需要

  • 登录以后,一个 Session 对应一个用户,只保存一个 "employee" 就好。

如果你要做那种支持"多账号切换"或者"同时保持多用户状态"的复杂应用,才需要保存多个。

所以总结:

情况处理方式
普通系统(后台管理、APP、官网)一个 "employee",没问题
特殊系统(支持多用户同时在线,一个浏览器开多个账号)需要复杂管理,比如 Map

但是服务器和浏览器之间不是一对多的关系吗,既然session是存在服务器里的,每次用户登录进来都需要判断session是否存在并比对id是否相等,那么有多个浏览器登录,服务器就只存储一个session不会有问题吗

服务器和浏览器之间是一对多没错!

✅ 一个服务器上可以有很多个浏览器(很多个客户端用户)访问。
✅ 但是每一个浏览器(或者说客户端)和服务器之间,其实是用Session ID来绑定自己的独立Session的!

重点来了

服务器上是存了很多个 Session 的,每个用户(浏览器)都有自己的 Session,不是所有人共用一个!


具体工作流程(非常重要)


也就是说:

服务器是根据 Session ID把每个用户隔离开来的!每个浏览器的 Session 是独立的、互不影响的。每个 Session 都可以保存自己的 "employee"

所以张三登录,服务器给张三一份 Session,张三的 Session 里有自己的 employee。

他们虽然都叫 "employee",但存储在不同 Session 里,所以不会冲突。


服务器上 Session 是什么样的?

你可以想象成服务器上有一个大的 Session 管理器,里面是这样的:

李四登录,服务器给李四另一份 Session,李四的 Session 里有李四的 employee。

  1. 浏览器第一次访问服务器的时候,服务器给它生成一个全新的 Session,比如:JSESSIONID=abc123

  2. 服务器把这个 JSESSIONID 通过 Set-Cookie 返回给浏览器。

    • 浏览器收到以后,把这个 Cookie 存起来。

  3. 以后这个浏览器再访问服务器时,就会自动带上这个 Cookie(JSESSIONID)

    • 服务器根据你带过来的 JSESSIONID=abc123,去找到属于你的 Session

  4. 每个浏览器都有自己独立的 Cookie(JSESSIONID),所以服务器知道:

    • A浏览器(Session1)

    • B浏览器(Session2)

    • C浏览器(Session3)

Session ID保存的数据
abc123(张三的浏览器)employee=张三
def456(李四的浏览器)employee=李四
ghi789(王五的浏览器)employee=王五

Session 是一份一份单独存在的,key是Session ID。

问题答案
多个浏览器登录,Session 会冲突吗?不会!每个浏览器有自己的 Session(通过 JSESSIONID 识别)
服务器上只有一个 Session 吗?不是!服务器维护了很多 Session,一个用户一个 Session
登录后要每次比对 id 吗?正常不需要!只要拿当前 Session 里的 employee 就可以了
employee key 会冲突吗?不会!每个 Session 各管各的

第一次登录时,浏览器发送登录请求。

服务器创建一个 Session 对象,把 employee=张三 保存进去。

后续每次请求,浏览器都会自动带上 JSESSIONID,服务器根据这个找到对应的 Session,从中拿到员工信息。

因为每个浏览器有独立的 Session,所以多个用户互不影响!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值