- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 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 。或者您的选择查询在数据库中没有找到任何内容,因此 authToken
是 undefined =>
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/
我的 Angular 应用程序中有以下代码。 app.config(function($routeProvider, $locationProvider) { $locationProvider
这就是我在 Backbone 中进行路由的方式,在决定调用哪个外部模板之前,首先获取路由及其参数。我觉得这很灵活。 var Router = Backbone.Router.extend({
我是 MEAN 堆栈领域的新手,我对 Angular 路线有一些疑问。为什么我应该在客户端重新创建后端已经用express.js创建的路由,有什么好处?这是 Angular.js 工作的唯一方式吗?我
我可以设置一条从根级 URL 进行映射的路由吗? http://localhost:49658/ 我使用的是 VS2010 内置 Web 服务器。 尝试使用空白或单斜杠 URL 字符串设置路由不起作用
我有一个现有的应用程序 Rails 3.2.17和 Angular js。我想在现有应用程序中包含 Activeadmin。 我遵循了 active-admin post from ryan bate
我正在关注 this Angular 中的路由教程,它就是行不通。当我使用“comp”选择器放置它的 HTML 代码时,它可以工作,但是当我尝试使用路由器 socket 对其进行路由时,它只显示来自
多个路由通过路由器进行管理。 前端路由的概念和原理 (编程中的) 路由 (router)就是一组 key-value 对应关系,分为:后端路由和前端路由 后端路由
服务器需要根据不同的URL或请求来执行不一样的操作,我们可以通过路由来实现这个步骤。 第一步我们需要先解析出请求URL的路径,我们引入url模块。 我们来给onRequest()函数加上一些逻辑
我正在为 Angular 6 应用程序设置路由,我想要一条可以匹配可变数量的段的路由。目前我有一个看起来像这样的路由配置: const routes: Routes = [ { path: '',
用户将点击电子邮件中的链接,如下所示: do-something/doSomething?thing=XXXXXXXXXXX 如何在路由器中定义路由并订阅获取参数? 目前在我的路由器中: {
我有一个具有以下结构的 Angular (4) 应用程序: app.module bi.module auth.module 路由应该是: / -> redirect to /home /
我正在使用 WCF 4 路由服务,并且需要以编程方式配置服务(而不是通过配置)。我见过的这样做的例子很少见,创建一个 MessageFilterTable 如下: var fi
我需要创建一个“路由”服务。我正在尝试使用 .Net 的 System.ServiceModel.Routing.IRequestReplyRouter我可以让它只在 HTTP 模式下工作,而不是在
例如,链接: /shop/phones/brend/apple/display/retina/color/red 在哪里: phones - category alias brend -
非常基本的问题,我很惊讶我找不到答案。我刚刚开始研究 django 并进行了开箱即用的安装。创建了一个项目并创建了一个应用程序。 urls.py 的默认内容很简单: urlpatterns = [
我已经实现了 WCF 路由服务;我还希望该服务(或类似的 WCF 服务)以规定的和统一的(与内容无关的)方式转换有效负载。例如,有效负载将始终采用 Foo 的形式。我想把它作为Bar在所有情况下。我很
我想使用 $locationProvider.html5Mode(true); 在 angularJs 中删除 # 哈希;但这导致所有 URL 都通过 angularJs 进行路由。我如何设置它以便只
我要听导航开始事件并判断其是否url属性是 /logout . 如果是这样,路由器应该停止触发连续事件,例如 路线已识别 , GuardsCheckStart , ChildActivationSta
有人可以解释我如何使用参数路由到 URL 吗? 例如id 喜欢点击产品并通过Id打开产品的更多信息。 我的路由到目前为止... angular.module('shop', ["cus
我目前正在 Angular: 7.2.14 上构建,想看看是否有人可以解释如何使用路由保护、共享服务或其他方式等重定向查询参数。 我试图解决的问题要求查询参数从根 Uri 路径传入,然后将路由重定向到
我是一名优秀的程序员,十分优秀!