简体   繁体   English

Node JS,快速会话,从客户端浏览器中删除 cookie

[英]Node JS, express-session, remove cookie from client browser

I work with app, that already has its own infrastructure.我使用的应用程序已经拥有自己的基础架构。 The task is to prevent user login in several browser.任务是防止用户在多个浏览器中登录。 Our application has single app architecture, so ideally user should work only in one browser tab.我们的应用程序具有单一应用程序架构,因此理想情况下用户应该只在一个浏览器选项卡中工作。 And I have a problem.我有一个问题。 I can't remove cookie from client.我无法从客户端删除 cookie。

I. Briefly.一、简述。

App settings:应用设置:

Server: NodeJS Port: 8083服务器:NodeJS 端口:8083

Client: VueJS Port: 8088客户端:VueJS 端口:8088

I use module express-session to initialize session mechanism on server side and send cookies to client.我使用模块express-session在服务器端初始化 session 机制并将 cookies 发送给客户端。 Client hasn't set cookies.客户端尚未设置 cookies。

II.二、 Details:细节:

Server's root file is index.js服务器的根文件是index.js

I do the following in it:我在其中执行以下操作:

  1. Plug in express module:插入express模块:
const express = require('express')
  1. Plug in cors module:插入cors模块:
const cors = require('cors')
  1. Add cors settings:添加cors设置:
app.use(cors({
    origin: 'http://localhost:8088',
    credentials: true
}))

Then I initialize session in user.js file and receive client's connects:然后我在user.js文件中初始化 session 并接收客户端的连接:

  1. Plug in express-session module:插入express-session模块:
const session = require('express-session')
  1. Plug in routing by express.Router() :通过express.Router()插入路由:
const router = express.Router()
  1. Add session settings:添加 session 设置:
const EIGHT_HOURS  = 1000 * 60 * 60 * 8
const {
    SESS_NAME = 'sid',
    SESS_LIFETIME = EIGHT_HOURS,
    SESS_SECRET = 'test',
    NODE_ENV = 'development'
} = process.env
const IN_PROD = NODE_ENV === 'production'
  1. Initialize session:初始化 session:
router.use(session({
    name: SESS_NAME,
    resave: false,
    saveUninitialized: false,
    secret: SESS_SECRET,
    cookie: {
        maxAge: SESS_LIFETIME,
        sameSite: false,
        // Must have HTTPS to work 'secret:true'
        secure: IN_PROD
    }
}))
  1. Receive client queries by router.post()通过router.post()接收客户端查询

So what I did:所以我做了什么:

  1. I use req.session.destroy to remove session data and expect the browser logout user from certain browser and cookies clear.我使用req.session.destroy删除 session 数据并期望浏览器注销用户从某些浏览器和 cookies 清除。
req.session.destroy(err => {
            if (err) {
                return res.send({ error: 'Logout error' })
            }
            res.clearCookie(SESS_NAME, {path: '/'})
            return res.send({ 'clearSession': 'success' })
        })

Unfortunately nothing magic happens不幸的是,没有魔法发生

  1. I read different topics.我阅读了不同的主题。 For example, here ( GitHub ) offer the conclusion: use explicit cookie's path indication in res.clearCookie method as shown above.例如,这里 ( GitHub ) 提供结论:在res.clearCookie方法中使用显式 cookie 的路径指示,如上所示。 That didn't work.那没有用。

  2. Wrote this setting {path: '/'} in cookies settings.在 cookies 设置中写入此设置{path: '/'} Didn't work too.也没有用。

router.use(session({
    name: SESS_NAME,
    resave: false,
    saveUninitialized: false,
    secret: SESS_SECRET,
    cookie: {
    path: '/',
        maxAge: SESS_LIFETIME,
        sameSite: false,
        // Must have HTTPS to work 'secret:true'
        secure: IN_PROD
    }
}))

And as wrote in express-session documentation ( NPM:express-session ) this path is the default path for cookie storage.正如 express-session 文档 ( NPM:express-session ) 中所写,此路径是 cookie 存储的默认路径。

  1. Add req.session = null in req.session.destroy:在 req.session.destroy 中添加req.session = null
req.session.destroy(err => {
            if (err) {
                return res.send({ error: 'Logout error' })
            }
            req.session = null
            res.clearCookie(SESS_NAME, {path: '/'})
            return res.send({ 'clearSession': 'success' })
        })

That didn't work那没有用

  1. delete req.session doesn't work too. delete req.session也不起作用。

So, how can I resolve this problem?那么,我该如何解决这个问题呢? What should I do?我应该怎么办?

adding .send('cleared cookie') made my browser clear its cache of the named cookie.添加.send('cleared cookie')使我的浏览器清除命名cookie的缓存。

const logOutRequest = (req, res) => {
      req.session.destroy((err) => {
         res.clearCookie("notcookie").send('cleared cookie');
      });
    };

Have you tried removing the exact cookie by setting it to null that is lets say that you are dealing with a cookie named Views you could remove the cookie using req.session.Views = null您是否尝试通过将其设置为 null 来删除确切的 cookie,也就是说您正在处理一个名为 Views 的 cookie,您可以使用req.session.Views = null删除 cookie

Instead of doing this而不是这样做

req.session.destroy(err => {
            if (err) {
                return res.send({ error: 'Logout error' })
            }
            req.session = null
            res.clearCookie(SESS_NAME, {path: '/'})
            return res.send({ 'clearSession': 'success' })
        })

you could do the name of your session cookie and set that to null that is您可以命名您的 session cookie 并将其设置为 null 即

req.session.sid= null

This removes the cookie from client browser这会从客户端浏览器中删除 cookie

req.session.destroy(err => {
    res.clearCookie("session-cookie-name", { path: "/" });
  });

The most important key is setting 'domain' in the clearCookie method to solve your issue.最重要的关键是在 clearCookie 方法中设置“域”来解决您的问题。 Expressjs will return the following in the http response header. Expressjs 将在 http 响应 header 中返回以下内容。 However, it seems that on the browser or some browsers that I tested, it doesn't know which cookie belonging to which domain to clear, hence, the cookie remains there.但是,似乎在我测试的浏览器或某些浏览器上,它不知道要清除哪个 cookie 属于哪个域,因此 cookie 仍然存在。 You do not need to include the path when calling clearCookie调用 clearCookie 时不需要包含路径

Set-Cookie: mycookie=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT

You have to set domain like below:您必须如下设置域:

 req.session.destroy(err => {
        res.clearCookie("session-cookie-name", { domain: 'your-domain' });
    });

Then response header will become然后响应 header 将变为

Set-Cookie: mycookie=; Domain=your-domain; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT

The browser will clear the cookie nicely!浏览器会很好地清除 cookie!

this works for me这对我有用

  @Post('signout')
  async signout(@Req() req: Request, @Res({ passthrough: true }) res: Response) {
    const user = req.user

    if (!user) return {}

    await new Promise<void>((resolve, reject) => {
      req.session.destroy((err) => {
        if (err) {
          reject(err)
        } else {
          res.clearCookie('ACCESS_TOKEN', {
            domain: '.xxx.com'
          })
          res.clearCookie('REFRESH_TOKEN', {
            domain: '.xxx.com'
          })
          res.clearCookie('connect.sid', {
            domain: '.xxx.com'
          })

          resolve()
        }
      })
    })

    return {}
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM