我有一个简单的应用程序,可以将用户登录并注册到SQLite数据库,该应用程序在localhost
上可以很好地工作,但是不能使其在部署中正常工作。它返回错误405 (Not Allowed)
和Error: Request failed with status code 405
。我的服务器是运行Nginx的Ubuntu。
我用于处理登录/注册行为的操作(使用Vuex):
actions: {
// Login user action.
login({ commit }, user) {
// Use Promise object to return desired objects.
return new Promise((resolve, reject) => {
commit("auth_request"); // Vuex helper to trigger mutations.
// Make a call to the server's login and return necessary data.
axios({
url: "http://localhost:3000/login", // Uncomment for localhost.
// url: "http://XX.XX.XX.XX/login", // Uncomment for deployment.
data: user,
method: "POST"
})
// Fetch necessary data from response.
.then(resp => {
// Necessary data.
const token = resp.data.token;
const user = resp.data.user;
localStorage.setItem("token", token); // Store token on localStorage.
axios.defaults.headers.common["Authorization"] = token; // Set Axio's header.
commit("auth_success", token, user); // Vuex helper to trigger mutations, which passes JWT token and user data.
resolve(resp); // Return Promise object that is resolved with a given value.
})
// Catch errors.
.catch(err => {
commit("auth_error"); // Vuex helper to trigger mutations.
localStorage.removeItem("token"); // Remove JWT token from the localStorage.
reject(err); // Return Promise object that is rejected with a given reason.
});
});
},
// Register user action.
register({ commit }, user) {
// Use Promise to return desired objects.
return new Promise((resolve, reject) => {
commit("auth_request"); // Vuex helper to trigger mutations.
// Make a call to the server's register and return necessary data.
axios({
url: "http://localhost:3000/register", // Uncomment for localhost.
// url: "http://XX.XX.XX.XX/register", // Uncomment for deployment.
data: user,
method: "POST"
})
// Fetch necessary data from response.
.then(resp => {
// Necessary data.
const token = resp.data.token;
const user = resp.data.user;
localStorage.setItem("token", token); // Store token on localStorage.
axios.defaults.headers.common["Authorization"] = token; // Set Axio's header.
commit("auth_success", token, user); // Vuex helper to trigger mutations, which passes JWT token and user data.
resolve(resp); // Return Promise that is resolved with a given value.
})
// Catch errors.
.catch(err => {
commit("auth_error", err); // Vuex helper to trigger mutations.
localStorage.removeItem("token"); // Remove JWT token from the localStorage.
reject(err); // Return Promise object that is rejected with a given reason.
});
});
},
对于后端,我使用以下方式通过路由注册启用所有必需的HTTP标头:
#!/usr/bin/env node
"use strict";
const express = require("express");
const DB = require("./db");
const config = require("./config");
const bcrypt = require("bcrypt");
const jwt = require("jsonwebtoken");
const bodyParser = require("body-parser");
// Create required database, Express server and routing.
const db = new DB("sqlitedb");
const app = express();
const router = express.Router();
router.use(bodyParser.urlencoded({ extended: false }));
router.use(bodyParser.json());
// CORS middleware configuration to avoid cross origin resource errors.
const allowCrossDomain = function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "*");
res.header("Access-Control-Allow-Headers", "*");
next();
};
app.use(allowCrossDomain);
// Route for new users registration.
router.post("/register", function(req, res) {
// Pass request body to database method and callback function to handle the response.
db.insert([req.body.email, bcrypt.hashSync(req.body.password, 8)], function(
err
) {
if (err)
return res.status(500).send("There was a problem registering the user.");
db.selectByEmail(req.body.email, (err, user) => {
if (err) return res.status(500).send("There was a problem getting user");
// User successfully registered, create an authentication token (JWT).
let token = jwt.sign({ id: user.id }, config.secret, {
expiresIn: 86400 // 24 hours expiration time.
});
res.status(200).send({ auth: true, token: token, user: user }); // Send 200 HTTP "OK" response, user successfully registered.
});
});
});
// Route for users login.
router.post("/login", (req, res) => {
db.selectByEmail(req.body.email, (err, user) => {
if (err) return res.status(500).send("Error on the server."); // Some kind of server error.
if (!user) return res.status(404).send("No user found."); // User not found.
// Check if given password mathces password in a database.
let passwordIsValid = bcrypt.compareSync(req.body.password, user.user_pass);
if (!passwordIsValid)
return res.status(401).send({ auth: false, token: null }); // Password doesn't match, don't sign in user.
// Password matches, sign in user.
let token = jwt.sign({ id: user.id }, config.secret, {
expiresIn: 86400 // 24 hours expiration time.
});
res.status(200).send({ auth: true, token: token, user: user }); // Send 200 (OK) HTTP response, user successfully logged in.
});
});
app.use(router); // Make the application accessible.
let port = process.env.PORT || 3000; // Dynamically generated port by hosting system or on localhost it's 3000.
app.listen(port, function() {
console.log("Express server listening on port " + port);
});
我用于处理此应用程序的nginx.conf
文件如下(它是HTTP,而不是HTTPS):
server {
listen 80;
listen [::]:80;
root /var/www/html;
index index.html;
server_name XX.XX.XX.XX;
location / {
try_files $uri $uri/ /index.html;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods *;
add_header Access-Control-Allow-Headers *;
}
}
有或没有这些标头(在nginx.conf
中)都不会更改行为。我猜这是某种服务器端配置错误,因为正如localhost
所说,一切工作都很好。有什么我想念的吗?对于部署,我将取消对url: "http://XX.XX.XX.XX/...
的注释,并注释掉url: "http://localhost:8080/...
的逻辑。
Edit1:
在error_page 405 = 200 $uri;
上添加骇客nginx.conf
可以消除此错误,但随后却给了我undefined
。
答案 0 :(得分:0)
您的CORS中间件不完整-您还需要为preflight requests实现OPTIONS
HTTP方法。基本上,405错误是不言自明的-您实施POST
而不是OPTIONS
。
查看如何在Express的现有CORS中间件中is implemented-https://github.com/expressjs/cors