同域名下不同端口的 web 服务 session 冲突导致用户登录互顶的问题

好久没更新文章了,就先从整了个开发中遇到的小问题再开始吧!

日常开发中经常会在同域名或 IP 下在不同端口部署不同的 web 应用服务,但如果恰好每个服务都有用户登录功能,且采用 session 的安全认证方式,就会出现两个应用登录信息互顶的问题,具体表现为:已经登录了 A 应用,结果再去登录 B 应用,回头去 A 应用的页面发现登录信息失效了,本文就看一下这个问题。

说明

web 项目使用基于 python 的 web 框架 flask 实现。

探索

复现问题

我以自己的项目为例:

  • 应用 A:localhost:20702
  • 应用 B:localhost:20709

首先打开项目 A 的网页并登录,然后打开浏览器的网页检查器看一下,cookie 信息中 session id 叫 session:

session:"eyJ1c2VybmFtZSI6InRpYW55ZTEifQ.X5OddA.Tt8ayJhPp8KHcBdzRzU72I6U-SI"

同样,再打开项目 B 的网页并登录,然后同样打开浏览器网页检查器看一下 cookie 信息,也有一个 session id 为 session 的信息:

session:"eyJ1c2VybmFtZSI6InRpYW55ZSJ9.X5OaxQ.IltnUYo4-bO9JcrNxBJYPc1hxWs"

回过头去看项目 A 的网页发现,原来的 cookie 信息变了,还是有 session 的信息,但是值变了:

session:"eyJ1c2VybmFtZSI6InRpYW55ZSJ9.X5OexQ.OC7TtbfCLfuUtwsS0D9nbK6mh5w"

导致项目 A 的页面登录失效了。

排查原因

上面在检查器中可以明确看到 session 信息,cookie 中仅仅出现的是域名 localhost 下的一个 session 信息,id 为 session,怎么回事?两个项目共用了一个 session 信息。

经过了解知道:

对于浏览器来说,cookie 不区分端口,因此对于同一个域名,它的所有端口都是共享 cookie

解决

所以解决方法很简单,修改后端默认的 session id 名称为各自项目的,只要不相同就可以了。可以在 Flask 应用的配置中修改配置项 SESSION_COOKIE_NAME,其默认为 session,因为两个项目的均没有配置这个,都使用 session 作为了 session id,造成了冲突,我们添加这个配置项改为相关的应用名称即可,比如我的 Flask 项目中可以通过以下多种方式修改此配置:

# app 为 Flask 实例
app.config["SESSION_COOKIE_NAME"] = "session-demo1"

或者

# 单独定义配置对象
class ProductionConfig():
    SESSION_COOKIE_NAME = "session-demo1"

# 从对象读入配置内容,app 为 Flask 实例
app.config.from_object(ProductionConfig)

两个项目各自修改 SESSION_COOKIE_NAME 为不同值之后,即可解决 session 冲突问题了!Nice!

如果使用其它语言或 web 框架,一定可以找到这个 session cookie name 的配置项!

希望能帮到您!