gpt4 book ai didi

javascript - 登录路由返回未通过身份验证的消息

转载 作者:行者123 更新时间:2023-12-03 22:33:03 25 4
gpt4 key购买 nike

我正在使用 Postman 测试我的路线,包括我遇到问题的注销路线。它不断发送我在 Controller 文件中创建的错误消息,说“未通过身份验证”,而不是向我发送消息“注销”。我不知道问题出在我的服务器文件、我的路由还是我使用 Sequelize 创建的模型中。关于如何纠正这个问题的任何想法?这是我的文件:
用户 Controller .js

const express = require('express');
const bcrypt = require('bcryptjs');

const router = express.Router();

// grab the User model from the models folder, the sequelize
// index.js file takes care of the exporting for us and the
// syntax below is called destructuring, its an es6 feature
const { User } = require('../models');

/* Register Route
========================================================= */
router.post('/register', async (req, res) => {

// hash the password provided by the user with bcrypt so that
// we are never storing plain text passwords. This is crucial
// for keeping your db clean of sensitive data
const hash = bcrypt.hashSync(req.body.password, 10);

try {
// create a new user with the password hash from bcrypt
let user = await User.create(
Object.assign(req.body, { password: hash })
);

// data will be an object with the user and it's authToken
let data = await user.authorize();

// send back the new user and auth token to the
// client { user, authToken }
return res.json(data);

} catch(err) {
return res.status(400).send(err);
}

});

/* Login Route
========================================================= */
router.post('/login', async (req, res) => {
const { username, password } = req.body;

// if the username / password is missing, we use status code 400
// indicating a bad request was made and send back a message
if (!username || !password) {
return res.status(400).send(
'Request missing username or password param'
);
}

try {
let user = await User.authenticate(username, password)

user = await User.authorize(user);

return res.json(user);

} catch (err) {
return res.status(400).send('invalid username or password' + err);
}

});

/* Logout Route
========================================================= */
router.delete('/logout', async (req, res) => {

// because the logout request needs to be send with
// authorization we should have access to the user
// on the req object, so we will try to find it and
// call the model method logout
const { user, cookies: { auth_token: authToken } } = req

// we only want to attempt a logout if the user is
// present in the req object, meaning it already
// passed the authentication middleware. There is no reason
// the authToken should be missing at this point, check anyway
if (user && authToken) {
await req.user.logout(authToken);
return res.status(204).send("Logged out")
}

// if the user missing, the user is not logged in, hence we
// use status code 400 indicating a bad request was made
// and send back a message
return res.status(400).send(
{ errors: [{ message: 'not authenticated' }] }
);
});

/* Me Route - get the currently logged in user
========================================================= */
router.get('/me', (req, res) => {
if (req.user) {
return res.send(req.user);
}
res.status(404).send(
{ errors: [{ message: 'missing auth token' }] }
);
});

// export the router so we can pass the routes to our server
module.exports = {"AccountRoutes" : router};
custom-auth-middleware.js
const { User, AuthToken } = require('../models');

module.exports = async function(req, res, next) {

// look for an authorization header or auth_token in the cookies
const token =
req.cookies.auth_token || req.headers.authorization;

// if a token is found we will try to find it's associated user
// If there is one, we attach it to the req object so any
// following middleware or routing logic will have access to
// the authenticated user.
if (token) {

// look for an auth token that matches the cookie or header
const authToken = await AuthToken.find(
{ where: { token }, include: User }
);

// if there is an auth token found, we attach it's associated
// user to the req object so we can use it in our routes
if (authToken) {
req.user = authToken.User;
}
}
next();
}
authtoken.js 模型
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class AuthToken extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
AuthToken.belongsTo(models.User)
}
};
AuthToken.init({
token: {
type: DataTypes.STRING,
allowNull: false,
},
}, {
sequelize,
modelName: 'AuthToken',
});

// generates a random 15 character token and
// associates it with a user
AuthToken.generate = async function(UserId) {
if (!UserId) {
throw new Error('AuthToken requires a user ID')
}

let token = '';

const possibleCharacters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
'abcdefghijklmnopqrstuvwxyz0123456789';

for (var i = 0; i < 15; i++) {
token += possibleCharacters.charAt(
Math.floor(Math.random() * possibleCharacters.length)
);
}

return AuthToken.create({ token, UserId })
}

return AuthToken;
};
index.js 模型
// require the node packages
var fs = require('fs');
var path = require('path');
var Sequelize = require('sequelize');
// set a reference to this file's name so we can exclude it later
var basename = path.basename(__filename);
// create a variable called env which will pull from the process.env
// or default to 'development' if nothing is specified
var env = process.env.NODE_ENV || 'development';
// require the config file that was generated by sequelize and use the
// env variable we just created to pull in the correct db creds
var config = require(__dirname + '/../config/config.json')[env];
// initalize a db object
var db = {};
// we can set an optional property on our config objects call
// 'use_env_variable' if wanted to set our db credentials on our
// process.env. This is primarily used when deploying to a remote
// server (in production)
if (config.use_env_variable) {
var sequelize = new Sequelize(
process.env[config.use_env_variable], config
);
} else {

// otherwise we use the config object to initialize our sequelize
// instance
var sequelize = new Sequelize(
config.database, config.username, config.password, config
);
}
// This gathers up all the model files we have yet to create, and
// puts them onto our db object, so we can use them in the rest
// of our application
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0)
&& (file !== basename)
&& (file.slice(-3) === '.js');
})
.forEach(file => {
var model = sequelize['import'](path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
// export the main sequelize package with an uppercase 'S' and
// our own sequelize instance with a lowercase 's'
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
user.js 模型
var bcrypt = require("bcryptjs");

const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class User extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
User.hasMany(models.AuthToken);
}
};

// This is a class method, it is not called on an individual
// user object, but rather the class as a whole.
// e.g. User.authenticate('user1', 'password1234')
User.authenticate = async function(username, password) {

const user = await User.findOne({ where: { username } });

// bcrypt is a one-way hashing algorithm that allows us to
// store strings on the database rather than the raw
// passwords. Check out the docs for more detail
if (bcrypt.compareSync(password, user.password)) {
return user.id;
}

throw new Error('invalid password');
}

// in order to define an instance method, we have to access
// the User model prototype. This can be found in the
// sequelize documentation
User.authorize = async function (userId) {
const { AuthToken } = sequelize.models;
const user = this

// create a new auth token associated to 'this' user
// by calling the AuthToken class method we created earlier
// and passing it the user id
const authToken = await AuthToken.generate(userId);

// addAuthToken is a generated method provided by
// sequelize which is made for any 'hasMany' relationships

return { user, authToken }
};


User.logout = async function (token) {

// destroy the auth token record that matches the passed token
sequelize.models.AuthToken.destroy({ where: { token } });
};

User.init({
email: {
type: DataTypes.STRING,
unique: true,
allowNull: false
},
username: {
type: DataTypes.STRING,
unique: true,
allowNull: false
},
password: {
type: DataTypes.STRING,
allowNull: false
},
}, {
sequelize,
modelName: 'User',
});
return User;
};
index.js “服务器文件”
require('dotenv').config()
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const cookieParser = require('cookie-parser');
const customAuthMiddleware = require('./middleware/custom-auth-middleware');
const session = require('express-session');

// Imports the account route created in user-controller
var AccountRoutes = require('./controllers/user-controller');

// Requiring our models for syncing
const db = require('./models/index');

// directory references
const clientDir = path.join(__dirname, '../client');

// set up the Express App
const app = express();
const PORT = process.env.PORT || 8080;

// Express middleware that allows POSTing data
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

// configure express
app.set('view engine','js');

// use the cookie-parser to help with auth token,
// it must come before the customAuthMiddleware
app.use(cookieParser());
app.use(customAuthMiddleware);

// serve up the public folder so we can request static
// assets from the client
app.use(express.static(`${clientDir}/public`));

// initialize express-session to allow us track the logged-in user across sessions.
app.use(session({
key: 'user_sid',
secret: 'somerandonstuffs',
resave: false,
saveUninitialized: false,
cookie: {
expires: 600000
}
}));

// This middleware will check if user's cookie is still saved in browser and user is not set, then automatically log the user out.
// This usually happens when you stop your express server after login, your cookie still remains saved in the browser.
app.use((req, res, next) => {
if (req.cookies.user_sid && !req.session.user) {
res.clearCookie('user_sid');
}
next();
});

// Include our routes created in user-controller.js
app.use('/',AccountRoutes.AccountRoutes);

// sync our sequelize models and then start server
// force: true will wipe our database on each server restart
// this is ideal while we change the models around
db.sequelize.sync({ force: false }).then(() => {


// inside our db sync callback, we start the server
// this is our way of making sure the server is not listening
// to requests if we have not made a db connection
app.listen(PORT, () => {
console.log(`App listening on PORT ${PORT}`);
});
});

最佳答案

当您请求注销 Postman 时,您是否将 token 与请求一起发送?您获得 400: 'not authenticated' 的原因是您的用户,而 authToken 未定义。这两个未定义的原因在于您的中间件 custom-auth-middleware.js 。当您提出请求时,它没有 token 。或者您的选择查询在数据库中没有找到任何内容,因此 authTokenundefined => req.user` 也未定义。
我认为您不需要将 customAuthMiddleware 作为全局中间件。该中间件仅用于登录用户 => 所以你应该把它放在需要检查用户是否登录的路由之前。在您的示例中,仅注销需要中间件,登录和注册可以是公共(public)路由。您应该删除 index.js 中的这一行代码 app.use(customAuthMiddleware); 并将其添加到您的注销路由中:

router.delete('/logout',customAuthMiddleware, async (req, res) => {
我会像这样重新制作您的 customAuthMiddleware 中间件:
module.exports = async function(req, res, next) {

// look for an authorization header or auth_token in the cookies
const token =
req.cookies.auth_token || req.headers.authorization;

// if a token is found we will try to find it's associated user
// If there is one, we attach it to the req object so any
// following middleware or routing logic will have access to
// the authenticated user.
if (!token)
return res.status(400).send(
{ errors: [{ message: 'No token. Not authenticated!!' }] }

// look for an auth token that matches the cookie or header
const authToken = await AuthToken.find(
{ where: { token }, include: User }
);

// if there is an auth token found, we attach it's associated
// user to the req object so we can use it in our routes
if (authToken) {
req.user = authToken.User;
}

next();
}
由于您只将这个中间件放在需要登录的路由中,因此公共(public)路由不会受到影响。

关于javascript - 登录路由返回未通过身份验证的消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64960654/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com