我正在使用 Passport google OAuth 将用户登录到我的应用程序中。一切正常;每次登录时都会获取用户配置文件。然而,尽管每次登录都会在回调函数中返回正确的配置文件,但发送到前端的用户对象并没有改变。
我已经尝试删除后端和前端的cookie,但仍然没有任何变化。
我的护照策略文件(passport-google.js):
const User = require('./models/auth')
const passport = require('passport')
const GoogleStrategy = require('passport-google-oauth20').Strategy;
passport.use( new GoogleStrategy({
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: '/auth/google/callback',
passReqToCallback: true,
}, (req, accessToken, refreshToken, profile, done) => {
User.findOne({googleID: profile.id})
.then((currentUser) =>{
if(currentUser){
// if user is already saved
return done(null, currentUser)
}else{
// if user is not saved
new User({
username: profile.displayName,
googleID: profile.id,
email: profile.emails[0].value
})
.save()
.then((savedUser) => {
// console.log(savedUser)
return done(null, savedUser)
})
}
}).catch((err) => {
console.log('User not found!', err)
})
}))
passport.serializeUser((user, cb)=>{
console.log('users: ', user)
return cb(null, user.id)
})
passport.deserializeUser(async(id, cb) =>{
console.log('id: ' , id)
const user = User.findOne({where: {_id: id}})
.then((user)=>{
cb(null, user)
})
.catch((err)=>{
console.log(err)
cb(err, null)
})
})
路由器和控制器代码(authRouter.js):
const router = require('express').Router()
const passport = require('passport')
router.get('/logout', async(req, res) =>{
if(req.user){
req.logout()
res.clearCookie("session", {path:"/",httpOnly:true})
res.clearCookie("session.sig", {path:"/",httpOnly:true})
return res.redirect('http://localhost:3000/')
}else{
res.status(200).send('User already logged out!')
}
})
router.get('/login/success', async(req, res) => {
if(req.user){
res.status(200).json({
success: true,
message: 'Login success',
user: req.user,
})
}else{
res.status(401).json({
success: false,
message: 'You are not logged in',
})
}
})
router.get('/login/failed', (req, res) => {
res.status(404).json({
success: false,
message: 'Login failed',
user: false
})
})
router.get('/google', passport.authenticate('google', {session: false ,scope: ['profile', 'email']}))
router.get('/google/callback', passport.authenticate('google', {
failureRedirect: '/login/failed',
failureMessage: 'Login with Google failed! Try again.',
// session: false
}), (req, res) =>{
res.redirect('http://localhost:3000/', )
})
module.exports = router
app.js
require('dotenv').config()
const connectDB = require('./database/connect')
const express = require('express')
const cors = require('cors')
const cookieSession = require('cookie-session')
const passport = require('passport')
// const passportSetup = require('./passport')
const passportSetupStrategy = require('./passport-google')
const authRouter = require('./routers/authRouter')
const app = express()
app.use(cookieSession({name: 'session', keys: [process.env.SESSION_KEY] ,maxAge: 24 * 60 * 60 * 1000}))
app.use(cors({
origin: 'http://localhost:3000',
credentials: true,
methods: 'GET,PUT,POST,PATCH'
}))
// set encoding middleware
app.use(express.json())
app.use(express.static('public'))
app.use(express.urlencoded({extended: false}))
app.use(passport.initialize())
app.use(passport.session())
app.use('/auth', authRouter)
const mongoURI = process.env.MONGO_URI
const startServer = async() => {
try {
await connectDB(mongoURI)
app.listen('5000', async() => {
console.log('Server listening on port 5000')
})
} catch (error) {
console.log(error)
}
}
startServer()
前端代码: 应用程序.js:
import logo from './logo.svg';
import './App.css';
import { useEffect, useState } from 'react';
import Navbar from './components/Navbar/Navbar';
import { useDispatch } from 'react-redux';
import { getMovies } from './features/movie/movieSlice';
import {Routes, Route} from 'react-router-dom'
import { Home } from './pages/Home/Home';
import { MovieDetail } from './pages/MovieDetail/MovieDetail';
import Login from './pages/Login/Login';
import { setUser, clearUser } from './features/auth/authSlice';
import axios from 'axios';
function App() {
const [isLoading, setIsLoading] = useState()
const dispatch = useDispatch()
useEffect(() => {
dispatch(getMovies())
const getUser = async() =>{
fetch('http://localhost:5000/auth/login/success', {
credentials: 'include',
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Access-Control-Allow-Credential': true,
},
})
.then((res)=>{
return res.json()
})
.then((data) =>{
console.log('received: ', data)
dispatch(setUser(data.user))
})
.catch((error)=>{
console.log(error)
dispatch(clearUser())
})
}
getUser()
}, [])
return (
<div className='flex flex-col gap-5 relative bg-indigo-900'>
<Navbar />
<Routes>
<Route path='/' element={<Home />}/>
<Route path='/movie/:id' element={<MovieDetail />}/>
<Route path='/login' element={<Login />}/>
</Routes>
</div>
);
}
export default App;
Navbar.jsx:
import React from 'react'
import { FaHeart } from 'react-icons/fa'
import { useDispatch, useSelector } from 'react-redux'
import { Link } from 'react-router-dom'
import { clearUser } from '../../features/auth/authSlice'
import Favourites from '../Favourites/Favourites'
import './Navbar.css'
const Navbar = () => {
const {user} = useSelector(store => store.auth)
const dispatch = useDispatch()
const logout = () =>{
window.open('http://localhost:5000/auth/logout', '_self')
document.cookie = null
dispatch(clearUser())
}
return (
<header className='header text-white flex justify-between items-center p-2 bg-indigo-500 lg:px-20'>
<Link
className='text-center text-3xl font-bold'
to='/'
>
<span className='bg-white text-indigo-900 p-2 shadow-lg shadow-black rounded-md'>M</span>Moviex
</Link>
{
user? (
<div className='flex gap-1 items-center'>
<p>Hello, {user.username}</p>
<Link
className='bg-slate-400 p-2 rounded-md'
onClick={logout}>Logout</Link>
</div>
):(
<Link to='/login'>Login</Link>
)
}
<Favourites />
</header>
)
}
export default Navbar
添加此: 护照.use( 新的 GoogleStrategy({ ... 提示:'选择帐户', ...