如何在 node.js 中实现登录认证

我让这个节点服务器运行:

var server=http.createServer(function(request, responsehttp) {
if (request.method == 'POST') {
var body = '';
request.on('data', function (data) {
body += data;
});
request.on('end', function () {
var POST = qs.parse(body);
processquery(POST, request, responsehttp);
});
} else {
var url_parts = url.parse(request.url, true);
var query = url_parts.query;
console.log(query);
processquery(query, request, responsehttp);
}
});

我想添加这个服务器的登录表单。所以当用户验证,然后它会显示。

   function processquery(query, request, responsehttp){
var returnResult = function (data){
responsehttp.end(JSON.stringify(data));
};


if (!query.command) {
fileprocess(request, responsehttp);
}
responsehttp.writeHead(200, {"Content-Type": "application/json"});
switch(query.command) {
case 'logout':
logout(query, returnResult);
break;
case 'login':
login(query, returnResult);
break;
}
}

在进程查询函数返回文件给客户端,如果没有给出任何命令, 所以我可以发送登录命令从客户端到服务器,但服务器应该做什么,当它收到用户名密码登录命令,它应该如何递交登录请求,并返回登录成功或失败,写这一部分我需要帮助。

我尽力了。

function login(request, callback) {
if(request.username==users[request.username] && request.password==users[request.username].password) {
users[request.username].auth=true;
var data = {result:'success','message':'login successful'};
callback(data);
} else {
var data = {result:'error','message':'login incorrect'};
callback(data);
}
}

请建议我如何添加会话在这我尝试添加,请求变量在登录函数和尝试设置 request.session 变量它说 request.session 是未定义的。

请建议我如何编写这个登录模块,可以维护每个用户正确的登录认证。

131239 次浏览

实际上这并不是问题的答案,但这是一个更好的方法。

我建议您使用 连接/快递作为 http 服务器,因为它们为您节省了很多时间。你显然不想重新发明轮子。在您的情况下,使用 connect/Express 进行会话管理要容易得多。

Beside that for authentication I suggest you to use 每个人. Which supports a lot of authentication strategies. Awesome for rapid development.

所有这些都可以很容易地从他们的文档复制粘贴下来!

下面是我对 快递的处理方法:

1) 检查用户是否经过身份验证: 我有一个名为 CheckAuth 的中间件函数,我在每个需要用户验证身份的路由上使用它:

function checkAuth(req, res, next) {
if (!req.session.user_id) {
res.send('You are not authorized to view this page');
} else {
next();
}
}

我在路线中使用这个函数如下:

app.get('/my_secret_page', checkAuth, function (req, res) {
res.send('if you are viewing this page it means you are logged in');
});

2) 登入路线:

app.post('/login', function (req, res) {
var post = req.body;
if (post.user === 'john' && post.password === 'johnspassword') {
req.session.user_id = johns_user_id_here;
res.redirect('/my_secret_page');
} else {
res.send('Bad user/pass');
}
});

3) 注销路线:

app.get('/logout', function (req, res) {
delete req.session.user_id;
res.redirect('/login');
});

如果你想了解 Express.js 的更多信息,请点击这里查看他们的网站: < a href = “ http://Expressjs.com/en/guide/outing.html”> expressjs.com/en/guide/routing.html 如果需要更复杂的东西,检查 每个人(它有很多可用的认证方法,Facebook,twitter 等; 很好的教程关于它的 给你)。

再加上法里德的伪答案,

考虑在 每个人上使用 护照

这个问题的答案提供了一些关于差异的见解。


There are plenty of benefits to offloading your user authentication to Google, Facebook or another website. If your application's requirements are such that you could use Passport as your sole authentication provider or alongside traditional login, it can make the experience easier for your users.

@ alessioalex 是新节点用户的完美演示。但无论如何,很难将 checkAuth 中间件写入除 login 之外的所有路由,所以最好使用 app.use 将 checkAuth 从每个路由移动到一个条目。例如:

function checkAuth(req, res, next) {
// if logined or it's login request, then go next route
if (isLogin || (req.path === '/login' && req.method === 'POST')) {
next()
} else {
res.send('Not logged in yet.')
}
}


app.use('/', checkAuth)

我试过这个答案,但是没有用。我也是一个新手在网络开发和采取类,我使用 mlab,但我更喜欢解析,这就是为什么我必须寻找最合适的解决方案。下面是我自己的当前解决方案,它在 ExpressJS 上使用 parse。

1)检查用户是否通过身份验证: 我有一个名为 isLogginIn 的中间件函数,我在每个需要用户通过身份验证的路由上使用它:

 function isLoggedIn(req, res, next) {
var currentUser = Parse.User.current();
if (currentUser) {
next()
} else {
res.send("you are not authorised");
}
}

我在路线中使用这个函数如下:

  app.get('/my_secret_page', isLoggedIn, function (req, res)
{
res.send('if you are viewing this page it means you are logged in');
});

2)登入路线:

  // handling login logic
app.post('/login', function(req, res) {
Parse.User.enableUnsafeCurrentUser();
Parse.User.logIn(req.body.username, req.body.password).then(function(user) {
res.redirect('/books');
}, function(error) {
res.render('login', { flash: error.message });
});
});

3)注销路线:

 // logic route
app.get("/logout", function(req, res){
Parse.User.logOut().then(() => {
var currentUser = Parse.User.current();  // this will now be null
});
res.redirect('/login');
});

这对我来说非常有效,我完全参考了这里的 https://docs.parseplatform.org/js/guide/#users文档

感谢@alessioalex 的回答,我只是更新了最新的练习。

======authorization====== MIDDLEWARE


const jwt = require('../helpers/jwt')
const User = require('../models/user')


module.exports = {
authentication: function(req, res, next) {
try {
const user = jwt.verifyToken(req.headers.token, process.env.JWT_KEY)
User.findOne({ email: user.email }).then(result => {
if (result) {
req.body.user = result
req.params.user = result
next()
} else {
throw new Error('User not found')
}
})
} catch (error) {
console.log('langsung dia masuk sini')


next(error)
}
},


adminOnly: function(req, res, next) {
let loginUser = req.body.user
if (loginUser && loginUser.role === 'admin') {
next()
} else {
next(new Error('Not Authorized'))
}
}
}


====error handler==== MIDDLEWARE
const errorHelper = require('../helpers/errorHandling')


module.exports = function(err, req, res, next) {
//   console.log(err)
let errorToSend = errorHelper(err)
// console.log(errorToSend)
res.status(errorToSend.statusCode).json(errorToSend)
}




====error handling==== HELPER
var nodeError = ["Error","EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"]
var mongooseError = ["MongooseError","DisconnectedError","DivergentArrayError","MissingSchemaError","DocumentNotFoundError","MissingSchemaError","ObjectExpectedError","ObjectParameterError","OverwriteModelError","ParallelSaveError","StrictModeError","VersionError"]
var mongooseErrorFromClient = ["CastError","ValidatorError","ValidationError"];
var jwtError = ["TokenExpiredError","JsonWebTokenError","NotBeforeError"]


function nodeErrorMessage(message){
switch(message){
case "Token is undefined":{
return 403;
}
case "User not found":{
return 403;
}
case "Not Authorized":{
return 401;
}
case "Email is Invalid!":{
return 400;
}
case "Password is Invalid!":{
return 400;
}
case "Incorrect password for register as admin":{
return 400;
}
case "Item id not found":{
return 400;
}
case "Email or Password is invalid": {
return 400
}
default :{
return 500;
}
}
}


module.exports = function(errorObject){
// console.log("===ERROR OBJECT===")
// console.log(errorObject)
// console.log("===ERROR STACK===")
// console.log(errorObject.stack);


let statusCode = 500;
let returnObj = {
error : errorObject
}
if(jwtError.includes(errorObject.name)){
statusCode = 403;
returnObj.message = "Token is Invalid"
returnObj.source = "jwt"
}
else if(nodeError.includes(errorObject.name)){
returnObj.error = JSON.parse(JSON.stringify(errorObject, ["message", "arguments", "type", "name"]))
returnObj.source = "node";
statusCode = nodeErrorMessage(errorObject.message);
returnObj.message = errorObject.message;
}else if(mongooseError.includes(errorObject.name)){
returnObj.source = "database"
returnObj.message = "Error from server"
}else if(mongooseErrorFromClient.includes(errorObject.name)){
returnObj.source = "database";
errorObject.message ? returnObj.message = errorObject.message : returnObj.message = "Bad Request"
statusCode = 400;
}else{
returnObj.source = "unknown error";
returnObj.message = "Something error";
}
returnObj.statusCode = statusCode;
    

return returnObj;




}




===jwt====
const jwt = require('jsonwebtoken')


function generateToken(payload) {
let token = jwt.sign(payload, process.env.JWT_KEY)
return token
}


function verifyToken(token) {
let payload = jwt.verify(token, process.env.JWT_KEY)
return payload
}


module.exports = {
generateToken, verifyToken
}


===router index===
const express = require('express')
const router = express.Router()


// router.get('/', )
router.use('/users', require('./users'))
router.use('/products', require('./product'))
router.use('/transactions', require('./transaction'))


module.exports = router


====router user ====
const express = require('express')
const router = express.Router()
const User = require('../controllers/userController')
const auth = require('../middlewares/auth')


/* GET users listing. */
router.post('/register', User.register)
router.post('/login', User.login)
router.get('/', auth.authentication, User.getUser)
router.post('/logout', auth.authentication, User.logout)
module.exports = router




====app====
require('dotenv').config()
const express = require('express')
const cookieParser = require('cookie-parser')
const logger = require('morgan')
const cors = require('cors')
const indexRouter = require('./routes/index')
const errorHandler = require('./middlewares/errorHandler')
const mongoose = require('mongoose')
const app = express()


mongoose.connect(process.env.DB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
useFindAndModify: false
})


app.use(cors())
app.use(logger('dev'))
app.use(express.json())
app.use(express.urlencoded({ extended: false }))
app.use(cookieParser())


app.use('/', indexRouter)
app.use(errorHandler)


module.exports = app

为什么不剖分一个最小认证模块?

SweetAuth

一个不依赖于数据库的轻量级、零配置的用户身份验证模块。

Https://www.npmjs.com/package/sweet-auth

It's simple as:

app.get('/private-page', (req, res) => {


if (req.user.isAuthorized) {
// user is logged in! send the requested page
// you can access req.user.email
}
else {
// user not logged in. redirect to login page
}
})