【问题标题】:can't store the cookie clientside when using cookie-parser使用 cookie-parser 时无法存储 cookie 客户端
【发布时间】:2018-07-20 18:16:16
【问题描述】:

我很难让我的 react 应用程序与 cookie-session 一起工作。 当我查看我的网络并注册时,我确实发送了一个 Set-Cookie。这些是我的响应标头:

 Connection:keep-alive
Content-Type:application/json
Date:Fri, 09 Feb 2018 22:32:02 GMT
Set-Cookie:session=eyJ1c2VySWQiOjEwOX0=; path=/; expires=Mon, 19 Feb 2018 22:32:02 GMT; httponly
Set-Cookie:session.sig=o975QwcyzldDFzSPzbp2S4Qe_M4; path=/; expires=Mon, 19 Feb 2018 22:32:02 GMT; httponly
Transfer-Encoding:chunked
X-Powered-By:Express

请求头:

Accept:application/json
Accept-Encoding:gzip, deflate, br
Accept-Language:en-US,en;q=0.9
Connection:keep-alive
Content-Length:59
Content-Type:application/json
Host:localhost:5000
Origin:http://localhost:5000
Referer:http://localhost:5000/signup
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36

但是,我注意到我的 cookie 没有存储在浏览器中。我相信cookies应该由浏览器自动存储?这是我的代码:

const express = require('express')
const bodyParser = require('body-parser')
const cookieParser = require('cookie-parser')
const cookieSession = require('cookie-session')
const bcrypt = require('bcrypt')
const port = process.env.PORT || 5000
const app = express()
const pg = require('pg')
const conString = "postgres://postgres:postgres@localhost:5432/test"
const db = new pg.Client(conString)
let User


app.use(bodyParser.urlencoded({ extended: true }))
app.use(cookieParser())
app.use(cookieSession({
    name: 'session',
    secret: "booboo",
    httpOnly: true,
    // Cookie Options
    maxAge: 24 * 60 * 60 * 1000 * 10 // 24 hours * 10 days
  }))

app.use(express.json())
app.use(express.static(__dirname + '/client/build'))

app.use(function(req,res ,next){
console.log(req.session)
if(req.method !== 'POST')
    res.sendFile(__dirname + '/client/build/index.html')

if(req.headers.accept === 'application/json')
    next() 
})


app.route('/signup')
    .post((req, res) => {
        const sendError = (msg) => {
            res.status(400).send({error: msg})
        }

        if(!User.validateBeforeCreate({email: req.body.user.email, password: req.body.user.password}, sendError))
            return

        const salt = bcrypt.genSaltSync();
        const password = bcrypt.hashSync(req.body.user.password, salt);
        User.create({email: req.body.user.email, password: password}, (err, user) => {
            if(err !== null){
                if(err.code === '23505')
                    sendError('Account with that email already exists.')
            }
            else{
                req.session.userId = user.user_id
                res.writeHead(201, {"Content-Type": "application/json"})
                res.end()
                console.log(req.session)
                console.log(req.session.userId)
            }
        })
    })

我在注册时的 console.log 打印了这个: 会话 {userId: 103} 103

同时,在我注册并访问页面以接收我的 react 应用程序后,我的 console.log 会打印出来(可能是因为浏览器没有 cookie): Session {} ,我尝试将 httpOnly 设置为 true 和 false。结果相同。

我做错了什么?

【问题讨论】:

    标签: javascript reactjs cookie-session


    【解决方案1】:

    您似乎没有在 cookie 对象中设置域,因此浏览器正在丢弃 cookie。我还建议在浏览器中打开开发者工具并检查服务器发送的标头以查看传输的 cookie 的样子。

    试试:

    app.use(cookieSession({
      name: 'session',
      secret: "booboo",
      httpOnly: true,
      domain: "example.com",
      // Cookie Options
      maxAge: 24 * 60 * 60 * 1000 * 10 // 24 hours * 10 days
    }))
    

    【讨论】:

    • 我输入了路径:“/”,并为域属性尝试了 4 个不同的值,“localhost”、“localhost:5000”、“127.0.0.1”和“127.0.0.1”: 5000" 还是不行。
    • 不幸的是,这可能取决于实现。历史上,cookie 中的域需要一个前导点,例如“.example.com”,但现在看起来该域至少需要一个点。但是,这不适用于 localhost。尝试将其设置为空字符串或使用其他浏览器。每个浏览器处理它的方式不同。您的服务器正在发送哪些标头?
    • 连接:keep-alive 内容类型:application/json 日期:格林威治标准时间 2018 年 2 月 9 日星期五 23:03:30 Set-Cookie:session=eyJ1c2VySWQiOjEyMX0=;路径=/;过期=格林威治标准时间 2018 年 2 月 19 日星期一 23:03:30;域=127.0.0.1; httponly Set-Cookie:session.sig=7ZAaj8_BTYKHRBWuX3XJt0hm2fo;路径=/;过期=格林威治标准时间 2018 年 2 月 19 日星期一 23:03:30;域=127.0.0.1; httponly Transfer-Encoding:chunked X-Powered-By:Express
    • 空字符串不起作用,我将下载firefox并尝试一下。
    • 我在所有浏览器上都试过了。不行。但是,我有一个 Rails 应用程序在 localhost 上进行身份验证和授权。我检查了 rails 设置的 cookie,它的域属性设置为“localhost”并且正在工作。它的服务器响应与我的不同:
    【解决方案2】:

    在我的头撞在键盘上几个小时后,我想通了。出于某种原因,它不会设置 cookie。得到的工作,但我花了一段时间才到达那里。我花了一段时间弄清楚它是否有反应。但是不,如果我将它设置在 get 操作上它会起作用。所以后来我认为这是一个安全问题。而且我发现我需要在客户的提取中添加一个具有“同源”的凭据属性。我在错误的位置放置了一个 next() 。现在一切正常。所以总而言之,我所做的所有更改,4 行。感谢 Taylor Swanson 和这篇文章: Why is the browser not setting cookies after an AJAX request returns?

    name: 'session',
    secret: "booboo",
    httpOnly: true,
    path: "/",
    domain: "localhost"
    

    处理提交是一个客户端回调:

    handleSubmit = (event) => {
            event.preventDefault()
            fetch('/signup',{
                headers:{
                  'Accept': 'application/json',
                  'Content-Type': 'application/json'
                },
                credentials: 'same-origin',
                method: 'post',
                body: JSON.stringify({user: {...this.state}})
              })
        }
    

    我的新服务器代码如下所示:

    app.use(bodyParser.urlencoded({ extended: true }))
    app.use(cookieParser())
    app.use(cookieSession({
        name: 'session',
        secret: "booboo",
        httpOnly: true,
        path: "/",
        domain: "localhost"
        // Cookie Options
      }))
    
    app.use(express.json())
    app.use(function(req, res, next){
        if(req.method === 'GET' && req.cookies.session === undefined)
            req.session.userId = null
        else
            console.log(req.session.userId)
    
        next()
    })
    app.use(express.static(__dirname + '/client/build/'))
    app.use(function(req,res ,next){
        if(req.method === 'GET')
            res.sendFile(__dirname + '/client/build/index.html')
    
        if(req.headers.accept === 'application/json')
            next()
    })
    
    app.route('/signup')
        .post((req, res, next) => {
            const sendError = (msg) => {
                res.status(400).send({error: msg})
            }
    
            if(!User.validateBeforeCreate({email: req.body.user.email, password: req.body.user.password}, sendError))
                return
    
            const salt = bcrypt.genSaltSync();
            const password = bcrypt.hashSync(req.body.user.password, salt);
            User.create({email: req.body.user.email, password: password}, (err, user) => {
                if(err !== null){
                    if(err.code === '23505')
                        sendError('Account with that email already exists.')
                }
                else{
                    req.session.userId = user.user_id
                    res.writeHead(201, {"Content-Type": "application/json"})
                    res.end()
                    console.log(req.session)
                    console.log(req.session.userId)
                }
                next()
            })
        })
    

    【讨论】:

      猜你喜欢
      • 2018-03-05
      • 1970-01-01
      • 1970-01-01
      • 2013-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多