【发布时间】:2022-02-28 00:43:58
【问题描述】:
我使用 MERN 堆栈和 PassportJs 开发了一个应用程序进行身份验证。我使用 Google 策略来允许用户身份验证,但我遇到了问题。
以下是控制台中出现的错误:
CORS 政策已阻止从源“https://tagsite.netlify.app”访问“https://tagsite.herokuapp.com/users/google”获取:对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。如果不透明的响应满足您的需求,请将请求的模式设置为“no-cors”以获取禁用 CORS 的资源。
GET https://tagsite.herokuapp.com/users/googlenet::ERR_FAILED
我该如何解决?请帮忙。
我已经在后端使用了 cors 包,但仍然有同样的错误。
这是我的代码。
后端
app.js
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const passport = require('passport');
const serverless = require('serverless-http');
if (process.env.NODE_END !== 'production') {
// Load environment variables from .env file for non production environment
require('dotenv').config()
}
// Connect database
require('./utils/connectdb')
// Strategies
require('./strategies/GoogleStrategy')
require('./utils/authenticate')
// Routes import
const userRoutes = require('./routes/user')
const app = express();
app.use(bodyParser.json())
app.use(cookieParser(process.env.COOKIE_SECRET))
app.use(cors())
app.use(passport.initialize())
// Use routes
app.use('/users', userRoutes)
app.get('/', (req, res) => {
res.send({ status: 'success' })
})
// Server set up
let port;
if (process.env.PORT) {
port = process.env.PORT
} else {
port = 8000
}
app.listen(port, () => {
console.log('Listen on port: ' + port)
})
module.exports.handler = serverless(app)
GoogleStrategy.js
const passport = require('passport')
const googleStrategy = require('passport-google-oauth20').Strategy
const User = require('../models/user')
const slug = require('slug')
require('dotenv').config()
// serialize & deserialize user
passport.serializeUser((user, done) => {
done(null, user.id)
// done(null, user)
})
passport.deserializeUser((id, done) => {
User.findById(id)
.then((user) => {
done(null, user)
})
// done(null, user)
})
passport.use(
new googleStrategy(
{
clientID: process.env.GOOGLE_APP_ID,
clientSecret: process.env.GOOGLE_APP_SECRET,
callbackURL: process.env.GOOGLE_APP_CALLBACK_URL
},
(accessToken, refreshToken, profile, done) => {
User.findOne({ providerId: profile.id })
.then((user) => {
if (user) {
const userData = {
username: profile.displayName,
provider: profile.provider,
providerId: profile.id,
email: profile.emails[0].value,
avatar: profile._json.picture
&& profile._json.picture,
token: accessToken,
slug: slug(profile.displayName)
}
user.refreshToken.push({ refreshToken: accessToken })
user.save()
done(null, userData)
} else {
new User({
username: profile.displayName,
provider: profile.provider,
providerId: profile.id,
email: profile.emails[0].value,
avatar: profile._json.picture
&& profile._json.picture,
$addToSet: { refreshToken: accessToken },
slug: slug(profile.displayName)
})
.save()
.then((user) => {
const userData = {
username: profile.displayName,
provider: profile.provider,
providerId: profile.id,
email: profile.emails[0].value,
avatar: profile._json.picture
&& profile._json.picture,
token: accessToken,
slug: slug(profile.displayName)
}
user.refreshToken.push({ refreshToken: accessToken })
user.save()
done(null, userData)
})
.catch((error) => {
console.log(`create new user failed: ${error}`)
})
}
})
}
)
)
user.js(控制器)
const passport = require('passport');
module.exports = {
googleLogin: [
passport.authenticate('google', { scope: ['profile', 'email'] })
],
googleLoginCallback : [
passport.authenticate('google', {
failureRedirect: process.env.AUTH_FAILURE_REDIRECT_URL,
session: false
}),
(req, res, next) => {
const token = req.user.token
// res.status(200).json({userData: req.user})
res.cookie('refreshToken', req.user.token, COOKIE_OPTIONS)
res.send({ success: true, token })
}
],
user.js(路由)
const router = require('express').Router()
// Controllers
const {
googleLogin, googleLoginCallback
} = require('../controllers/user')
router.get('/google', googleLogin)
router.get('/google/callback', googleLoginCallback)
module.exports = router
前端
google.js(组件)
import { Button, Callout } from '@blueprintjs/core'
import React, { useContext, useState } from 'react'
import { UserContext } from '../../utils/context/UserContext'
const GoogleLogin = () => {
const [error, setError] = useState(null)
const [userContext, setUserContext] = useContext(UserContext)
const loginGoogle = () => {
setError(null)
const genericErrorMessage = 'Something error'
fetch(`${process.env.REACT_APP_API_URL}/users/google`, {
method: 'GET',
// credentials: 'include',
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
})
.then(async (res) => {
if (!res.ok) {
if (res.status === 400) {
setError('Please try again')
} else if (res.status === 401) {
setError('Unauthorized')
} else {
setError(genericErrorMessage)
}
} else {
const data = await res.json()
setUserContext((oldValues) => {
return { ...oldValues, token: data.token }
})
}
})
.catch((err) => {
setError(genericErrorMessage)
})
}
return (
<>
{error && <Callout intent="danger">{error}</Callout>}
<Button text="login with google" onClick={loginGoogle} />
</>
)
}
export default GoogleLogin
【问题讨论】:
标签: node.js reactjs express cors passport.js