我在Heroku上使用CORS遇到问题。
这是我在服务器上的代码
import express from 'express';
import bodyParser from 'body-parser';
import mongoose from 'mongoose';
require('dotenv').config()
import filmRoutes from './api/routes/films'
import userRoutes from './api/routes/users'
const app = express()
const DBNAME = process.env.DB_USER
const DBPASSWORD = process.env.DB_PASS
mongoose.connect(`mongodb://${DBNAME}:${DBPASSWORD}@ds157422.mlab.com:57422/filmbase`, {useNewUrlParser: true})
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", '*');
res.header("Access-Control-Allow-Credentials", true);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header("Access-Control-Allow-Headers", 'Origin,X-Requested-With,Content-Type,Accept,content-type,application/json');
next();
});
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.use('/films', filmRoutes)
app.use('/users', userRoutes)
export default app;
这是我的发帖请求
CheckLogin = () => {
const data = {
name: this.state.formInput.login.value,
password: this.state.formInput.password.value
}
axios.post('https://whispering-shore-72195.herokuapp.com/users/login', data)
.then(response=>{
console.log(response);
const expirationDate = new Date(new Date().getTime() + response.data.expiresIn * 1000)
localStorage.setItem('token', response.data.token)
localStorage.setItem('expirationDate', expirationDate)
this.context.loginHandler()
})
.catch(err=>{
console.log(err)
})
console.log(data);
}
这是错误
在以下位置访问XMLHttpRequest 原产地的“ https://whispering-shore-72195.herokuapp.com/users/login” “ https://mighty-citadel-71298.herokuapp.com”已被CORS屏蔽 策略:“访问控制允许来源”标头不存在 请求的资源。
我尝试了很多方法,什么也没做……有什么主意吗?
答案 0 :(得分:0)
您已经跨过https://whispering-shore-72195.herokuapp.com的https://mighty-citadel-71298.herokuapp.com上的原始域
您可以尝试npm cors package作为中间件而不是自定义中间件。 CORS
软件包允许您进行多个配置,并且非常易于使用。
简单用法(启用所有CORS请求)
import express from 'express';
import bodyParser from 'body-parser';
import mongoose from 'mongoose';
import cors from 'cors';
require('dotenv').config()
import filmRoutes from './api/routes/films'
import userRoutes from './api/routes/users'
const app = express()
const DBNAME = process.env.DB_USER
const DBPASSWORD = process.env.DB_PASS
mongoose.connect(`mongodb://${DBNAME}:${DBPASSWORD}@ds157422.mlab.com:57422/filmbase`, {useNewUrlParser: true})
/*app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", '*');
res.header("Access-Control-Allow-Credentials", true);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header("Access-Control-Allow-Headers", 'Origin,X-Requested-With,Content-Type,Accept,content-type,application/json');
next();
});*/
app.use(cors()); // <---- use cors middleware
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.use('/films', filmRoutes)
app.use('/users', userRoutes)
export default app;
我已经测试了从https
到服务器的客户端呼叫登录,并且该服务器可以正常工作而没有CORS问题。也许您已经成功修复了它。
我在StackBlitz上尝试了简单方法,它已经成功运行。
检查时,您可以尝试登录https://js-53876623.stackblitz.io/并查看“网络”选项卡,并查看OPTIONS (200 status)
和POST (404 not found)
(因为我在您的数据库中不认识任何用户)
我已经在本地尝试过您的代码,也许您没有测试并处理所有错误,不幸的是,这使您的应用程序崩溃了。
我已经运行了您的代码,发现问题可能是jsonwebtoken
错误:
错误:secretOrPrivateKey必须具有一个值
请尝试使用process.env.JWT_KEY || 'Require key here!!!',
,并在您的环境中设置JWT_KEY
或使用||
作为服务器上的默认密钥。
也许可以解决您的问题。
对于您的代码,我有一些建议:
User.findOne()
代替User.find()
app.use(cors());
jsonwebtoken
应该使用异步而不是同步。答案 1 :(得分:0)
这是我的源代码
userController.js
import mongoose from 'mongoose';
import User from '../models/user';
import bcrypt from 'bcrypt';
import jsw from 'jsonwebtoken'
export default {
async send(req, res ,next){
User.find({name: req.body.name})
.exec()
.then(user=>{
if(user.length >= 1){
return res.status(409).json({
message: 'User exist'
});
}
else{
bcrypt.hash(req.body.password, 10, (err,hash)=>{
if(err){
return res.status(500).json({
error: err
});
}else{
const user = new User({
_id: new mongoose.Types.ObjectId(),
name: req.body.name,
password: hash
});
user
.save()
.then(result=>{
console.log(result);
res.status(201).json({
message: 'user created'
});
})
.catch(err=>{
console.log(err)
res.status(500).json({
error: err
})
})
}
})
}
})
},
async login(req, res, next){
User.find({name: req.body.name})
.exec()
.then(user=>{
if(user.length < 1){
return res.status(404).json({
message: 'user exist'
})
}
bcrypt.compare(req.body.password, user[0].password, (err, result)=>{
if(err){
return res.status(404).json({
message: 'bcrypt failed'
})
}
if(result){
const time = '1'
const token = jsw.sign({
name: user[0].name,
iserId: user[0]._id
},process.env.JWT_KEY,
{
expiresIn: `${time}h`
}
);
return res.status(200).json({
message: 'auth success',
token: token,
expiresIn: time
})
}
return res.status(404).json({
message: 'Auth failed'
})
})
})
.catch(err=>{
res.status(500).json({
error: err
})
})
}
}
app.js
import express from 'express';
import bodyParser from 'body-parser';
import mongoose from 'mongoose';
require('dotenv').config()
import filmRoutes from './api/routes/films'
import userRoutes from './api/routes/users'
const app = express()
const DBNAME = process.env.DB_USER
const DBPASSWORD = process.env.DB_PASS
mongoose.connect(`mongodb://${DBNAME}:${DBPASSWORD}@ds157422.mlab.com:57422/filmbase`, {useNewUrlParser: true})
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", '*');
res.header("Access-Control-Allow-Credentials", true);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header("Access-Control-Allow-Headers", 'Origin,X-Requested-With,Content-Type,Accept,content-type,application/json');
next();
});
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.use('/films', filmRoutes)
app.use('/users', userRoutes)
export default app;
LoginPades.js
import React from 'react';
import './LoginPages.css';
import axios from 'axios'
import AuthContext from '../../../auth-context';
import Input from '../../Input/Input';
class Login extends React.Component {
static contextType = AuthContext;
state={
formInput:{
login:{
elementType: 'input',
elementConfig: {
type: 'text',
placeholder: 'Login'
},
Value:''
},
password:{
elementType: 'input',
elementConfig:{
type: 'text',
placeholder: 'Password'
},
Value:'',
}
}
}
inputChangeHandler = (event, id) => {
let value = event.target.value;
const updateState = {
...this.state.formInput
}
const updateElement = {
...updateState[id]
}
updateElement.value = value;
updateState[id] = updateElement
this.setState({
formInput: updateState
})
}
CheckLogin = () => {
const data = {
name: this.state.formInput.login.value,
password: this.state.formInput.password.value
}
axios.post('https://whispering-shore-72195.herokuapp.com/users/login', data)
.then(response=>{
console.log(response);
const expirationDate = new Date(new Date().getTime() + response.data.expiresIn * 1000)
localStorage.setItem('token', response.data.token)
localStorage.setItem('expirationDate', expirationDate)
this.context.loginHandler()
})
.catch(err=>{
console.log(err)
})
console.log(data);
}
render(){
const inputsArray = [];
for (let key in this.state.formInput){
inputsArray.push({
id: key,
config: this.state.formInput[key]
})
}
let inputs =(
<>
{inputsArray.map(inputElement=>(
<Input
className='input-lodig-password'
key={inputElement.id}
elementType={inputElement.config.elementType}
elementConfig={inputElement.config.elementConfig}
value={inputElement.value}
changed={(event)=>this.inputChangeHandler(event, inputElement.id)}
/>
))}
</>
)
return(
<div className='login'>
<div className='card'>
<div className='spider'>
{/* <img src='http://www.officialpsds.com/images/thumbs/Spiderman-Logo-psd59240.png' alt='pajak'/> */}
</div>
<p className='opis'>Zaloguj sie do groty rozpusty</p>
<form className='login-inputy'>
{inputs}
</form>
<button className='btn-login' onClick={this.CheckLogin}>Zaloguj sie</button>
</div>
</div>
)
}
}
export default Login
答案 2 :(得分:0)
router / user.js
import express from 'express';
import userController from '../controllers/usersController';
import {catchAsync} from '../moddlewares/errors';
const router = express.Router();
router.post('/signup',catchAsync(userController.send))
router.post('/login', catchAsync(userController.login))
export default router
模型/user.js
import mongoose from 'mongoose'
const userSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: {type: String, required: true},
password: {type: String, required: true}
})
const user = mongoose.model('User', userSchema);
export default user
catchAsync.js
export function catchAsync(cb){
return (req,res,next)=>{
cb(req,res,next).catch(err=>next(err))
}
}
答案 3 :(得分:0)
我也遇到过同样的问题,我认为您的问题不是CORS。您可以测试服务器日志吗?以我为例,我遇到了包装问题,这就是我得到503的原因,也没有“ Access-Control-Allow-Origin”标头,CORS错误。当我解决软件包和jwt问题时,我的CORS问题就解决了!。
答案 4 :(得分:0)
您需要确定是否确实是 CORS 问题或您的API代码已损坏。
如果是 CORS 问题,请按照上面的建议处理后端代码中的 CORS 或使用cors
软件包。
但是,问题经常是,您的代码正在中断,而您却并不知道,这是很多时候。例如,就我而言,我没有将nodemon
添加到依赖项中,而我的start
脚本依赖于Heroku找不到的nodemon
。因此,您的代码可能在dev中工作正常,但在prod中中断。
您可以通过以下方法在Heroku中查找代码的哪些部分:
答案 5 :(得分:0)
您的问题与 CORS Heroku 服务器的服务不可用有关。由于是免费服务,每小时调用次数限制为50次。请按照答案中的建议尝试使用您自己的CORS服务器作为中间件或自行托管CORS-Anywhere
答案 6 :(得分:0)
在 Heroku 中部署后,我遇到了同样的问题,在代码的不同点使用 console.log(),我可以看到这样的错误消息:'RangeError Maximum call stack size exceeded...'。 这是一个 NodeJs 错误,我通过在 package.json 底部添加此代码来修复它:
“决议”:{ “FS-电容器”:“3.0.0” }
告诉我它是否适合您。
答案 7 :(得分:-2)
我在使用 Heroku 和我的后端时遇到了类似的问题,它现在托管在 vercel 中。
如果您正在使用环境变量,请确保在您的 vercel 应用程序中设置这些变量,或者如果您在其他任何地方托管,请先检查一下。环境变量!