【问题标题】:My app is blocked using Google Strategy with PassportJs and MERN我的应用被 Google Strategy 和 PassportJs 和 MERN 阻止了
【发布时间】: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


    【解决方案1】:
    app.use(
      cors({
        origin: [
    "https://tagsite.netlify.app"
       ],
        credentials: true,
        methods: "GET,HEAD,PUT,PATCH,POST,DELETE",
      })
    );
    

    正如您的错误所说,CORS 不喜欢您的前端代码。它不知道。您必须将您的前端介绍给您的后端,并告诉您的后端让某些来源访问您的服务器。

    我对是否必须包含凭据没有足够的经验,但它对我有用!

    【讨论】:

    • DrakeColman,我试过你的代码,但仍然有同样的错误。
    • 终于找到了一个使用Twitter的教程。我更新它以在我的情况下使用谷歌。一切都在本地工作,但当我将它部署在后端的 heroku 和前端的 netlify 上时就不行了。
    • 经过多次搜索,我终于解决了我的问题,使用 react-google-login 和 react-facebook-login 包。谢谢!
    猜你喜欢
    • 2020-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-01
    • 2014-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多