问题
According to the Passport Documentation on Sessions
...only the user ID is serialized to the session, keeping the amount of data stored within the session small. When subsequent requests are received, this ID is used to find the user, which will be restored to req.user.
However my test SPA which is based on Passport form-based authentication sample with debug messages added indicates req.user
has already been restored before the app.get
route handler is triggered.
Here is the output from an HTTP POST where the username and passport fields are empty -
[nodemon] starting `node app.js`
agenda-spa app listening at http://localhost:3000
handling request for: / POST
handling request for: / GET
xxx get root
xxx req.user undefined
handling request for: /style.css GET
req.user
is undefined as expected
Here is the output from an HTTP POST with an authenticated username and password
handling request for: / POST
xxx passport.use sss
xxx findByUsername sss
xxx password match
xxx serializeUser { id: 1, username: 'sss', password: 'sss' }
xxx auth success
xxx deserializeUser 1
xxx findById 1
handling request for: / GET
xxx get root
xxx req.user { id: 1, username: 'sss', password: 'sss' }
xxx deserializeUser 1
xxx findById 1
handling request for: /style.css GET
I would expect it to be -
...
xxx deserializeUser 1
xxx findById 1
xxx req.user { id: 1, username: 'sss', password: 'sss' }
...
Why is passport.deserializeUser
called after req.user
has been restored?
回答1:
First, in my case I get:
xxx passport.use sss
xxx findByUsername sss
xxx password match
xxx serializeUser { id: 1, username: 'sss', password: 'sss' }
xxx auth success
xxx deserializeUser 1
xxx findById 1
handling request for: / GET
xxx get root
xxx req.user { id: 1, username: 'sss', password: 'sss' }
To reproduce the issue I run the following script:
#!/usr/bin/env bash
set -eu
rm cookies.txt || true
args=(
-sSv -b cookies.txt -c cookies.txt
)
curl "${args[@]}" -d 'username=sss&password=sss' localhost:3000
curl "${args[@]}" localhost:3000
Let's add some debugging information to understand where requests start:
$ DEBUG=* node app.js
...
express:router dispatching POST / +10s
express:router session : / +1ms
express-session no SID sent, generating session +1ms
express:router initialize : / +3ms
express:router authenticate : / +1ms
express:router <anonymous> : / +0ms
handling request for: / POST
xxx passport.use sss
xxx findByUsername sss
xxx password match
xxx serializeUser { id: 1, username: 'sss', password: 'sss' }
xxx auth success
express-session saving y4TUFn7tzccSARC7kHiDbuKY8qXj1sCU +13ms
express-session split response +1ms
express-session set-cookie connect.sid=s%3Ay4TUFn7tzccSARC7kHiDbuKY8qXj1sCU.yxt3TbHx4HSzm03JMrtPcTPrm3K40FbHiuS6NGT%2Fd7E; Path=/; HttpOnly +3ms
...
express:router dispatching GET / +14ms
body-parser:urlencoded skip empty body +0ms
express:router session : / +0ms
express-session fetching y4TUFn7tzccSARC7kHiDbuKY8qXj1sCU +1ms
express-session session found +1ms
express:router initialize : / +1ms
express:router authenticate : / +0ms
xxx deserializeUser 1
xxx findById 1
express:router <anonymous> : / +1ms
handling request for: / GET
xxx get root
xxx req.user { id: 1, username: 'sss', password: 'sss' }
...
As such what is output for the second request in your case is:
xxx deserializeUser 1
xxx findById 1
handling request for: / GET
xxx get root
xxx req.user { id: 1, username: 'sss', password: 'sss' }
xxx deserializeUser 1
xxx findById 1
So it's as you expected, but for some reason the session strategy is triggered twice. That I can't reproduce.
来源:https://stackoverflow.com/questions/65374696/why-is-passport-deserializeuser-called-after-req-user-has-been-restored