• session存储到MongoDB


    1. 基于session的注册、登录、登出

    session存储到数据库

    新建user.js,添加usersmongoose model

    var mongoose = require('mongoose')
    var Schema = mongoose.Schema
    
    var User = new Schema({
        username: {
            type: String,
            required: true,
            unique: true
        },
        password: {
            type: String,
            required: true
        },
        admin: {
            type: Boolean,
            default: false
        }
    })
    
    module.exports = mongoose.model('User', User)
    

    实现注册、登录、登出功能

    新建users.js文件

    var express = require('express')
    const bodyParser = require('body-parser')
    var User = require('user.js')
    
    var router = express.Router()
    router.use(bodyParser.json())
    
    router.get('/', function(req, res, next) {
      res.send('respond with a resource');
    });
    
    router.post('/signup', (req, res, next) => {
        User.findOne({username: req.body.username})
        .then((user) => {
            if (user != null) {	// 注册用户已存在
                var err = new Error('User ' + req.body.username + ' already exists!')
                err.status = 403
                next(err)
            } else {	// 没有该用户
                return User.create({
                    username: req.body.username,
                    password: req.body.password
                })
            }
        })
        .then((user) => {
            res.statusCode = 200
            res.setHeader('Content-Type', 'application/json')
            res.json({status: 'Registration Successful!', user: user})
        }, (err) => next(err))
        .catch((err) => next(err))
    })
    
    router.post('/login', (req, res, next) => {
        
        if(!req.session.user) {
            var authHeader = req.headers.authorization
            
            if (!authHeader) {
                var err = new Error('You are not authenticated!')
                res.setHeader('WWW-Authenticate', 'Basic')
                err.status = 401
                return next(err)
            }
            
            var auth = new Buffer.from(authHeader.split(' ')[1], 'base64').toString().split(':')
            var username = auth[0]
            var password = auth[1]
            
            User.findOne({username: username})
            .then((user) => {
                if (user === null) {
                    var err = new Error('User ' + username + ' does not exist!')
                    err.status = 403
                    return next(err)
                } else if (user.password !== password) {
                    var err = new Error('Your password is incorrect!')
                    err.status = 403
                    return next(err)
                } else if(user.username === username && user.password === password) {
                    req.session.user = 'authenticated'
                    req.statusCode = 200
                    res.setHeader('Content-Type', 'text/plain')
                    res.end('You are authenticated!')
                }
            })
            .catch((err) => next(err))
        } else {
            res.statusCode = 200
            res.setHeader('Content-Type', 'text/plain')
            res.end('You are authenticated!')
        }
    })
    
    router.get('/logout', (req, res) => {
        if (req.session) {
            req.session.destroy()	// 删除session
            res.clearCookie('session-id')	// 清除客户端的cookie
            res.redirect('/')	// 重定向到应用主页
        } else {
            var err = new Error('You are not logged in!')
            err.status = 403
            next(err)
        }
    })
    

    更改app.js

    ...
    app.use('/', indexRouter)
    app.use('/users', usersRouter)
    
    function basicAuth(req, res, next) {
        if (!req.session.user) {
            var err = new Error('You are not authenticated!')
            err.status = 403
            return next(err)
        } else {
            if (req.session.user === 'authenticated') {
                next()
            } else {
                var err = new Error('You are not authenticated!')
                err.status = 403
                return next(err)
            }
        }
    }
    ...
    

    2. Passport优化冗余代码

    正如上面的代码中有有许多重复的错误检查代码和重复的认证操作,可以使用Passport中间价进行简化。Passport支持不同的认证策略,如OpenID、OAuth、OAuth2.0等。在这里,使用Local Strategy来简化用户名密码注册的认证方式。

    更新user.js,使用passport-local-mongoose模块简化usernamepassword存储

    var passportLocalMongoose = require('passport-local-mongoose')
    
    var User = new Schema({
        admin: {
        	type: Boolean,
        	default: false    
        }
    })
    
    User.plugin(passportLocalMongoose)
    

    passport-local-mongoose plugin adds in the username and a encrypted way of storing the password within our user model. 将注册用户的密码进行哈希加密。使用salt为password加密,salt是一个用来执行密码hash操作的随机字符串。经hash加密后的密码存储在数据库中,原始的真实密码并没有被存储。当用户使用用户名密码进行认证时,密码经hash后,与数据库中存储的密码进行比对。

    所以,Passport-Local-Mongooseuser model上添加了认证方法,自动进行认证;基于用户名和密码的Local Strategy认证方法可以通过user.authenticate直接使用。

    以用户名test,密码password为例,存储到mongoDB中的内容如下:

    {
            "_id" : ObjectId("5e69d49249cd2322286205b6"),
            "admin" : false,
            "username" : "test",
            "salt" : "706639aa4b1d0627629ca0372e3e945189c6d2c6f534dcead55518d13200127c",
            "hash" : "e9141ec79f2a0bcab0af3b4bc337c76b635e36f5cc3727f3d71e24224e559dda87e3e3e5f309d4220c50e1bc0fc10d2d78d007004e0076e81e43a9b05c3393bce5ca7f4de65bef0c40c4e9383aade96263a5a56ca81c9992e859e7e9f5daab2811df49fa897b731d313769c2f3bb2a73f7dd8bbb3c14b3bcf5088c57cb1439db03238f1d542dc56008b067f0061c5f0d91f0ce89c053180630c2e086ebb6fb7f5a26a67a4e5cabe63887beec82af6e757ebf945d727564ee09494d05f3b5fb05e33e718c01e44e7cef10344dd6b2ee02da9717ac410c8259ae752acf8d97e931cc6be2d32981af6c0a24c51fcdbde44dc44bb220abe09407dfadd5c6d3d7a5699ea35db46a3acb0e6881cca77ba2802a75e97f9be8c719792dfc9847e3f0af1b97a0152f1d772eea4c30a0a18e9dc5621bdab77255e958f509402aeb9a2b8238d78e72c46f3b08cb76425aa5ebcdbe80ec7541c3b6b394529be98eed96be5622366710db7388c599d3412dea143b233da9e429ded07bbd1159e41b8ab96a73f79ab15e5734a961c13e276445a8c2f28d315b0e48784918422709763871c1074ccbfc1d9841f88719d529ba0ab90d2d71b4db039213ffb4e072da7787f022564b1ad285b0512e2679edc461286b5c51deb0c0ec9cfbc4a70cecb8e531471a4adeff27b69d0cb0aec4b4f155d3a14d9f03af7f62428b3a895620aa26b3f4a67f09",
            "__v" : 0
    }
    // 这里可没有存密码
    

    新建authenticate.js文件

    var passport = require('passport')
    // passport-local支持用户名密码的local strategy认证
    var LocalStrategy = require('passport-local').Strategy
    var User = require('user')
    
    exports.local = passport.use(new LocalStrategy(User.authenticate()))
    passport.serializeUser(User.serializeUser())
    passport.deserializeUser(User.deserializeUser())
    

    Passport中间件也支持sessions,但有用户信息要序列化后与session信息存储在服务端,收到请求后,用户信息需要反序列化从session信息中提取出。Passport-Local-Mongoose插件通过serializeUserdeserializeUser支持序列化和反序列化操作。

    更改users.js文件

    ...
    var passport = require('passport')
    ...
    
    router.post('/signup', (req, res, next) => {
        User.register(new User({username: req.body.username}), req.body.password, (err, user) => {
            if (err) {
                res.statusCode = 500
                res.setHeader('Content-Type', 'application/json')
                res.json({err: err})
            } else {
                passport.authenticate('local')(req, res, () => {
                    res.statusCode = 200
                    res.setHeader('Content-Type', 'application/json')
                    res.json({success: true, status: 'Registration Successful!'})
                })
            }
        })
    })
    
    router.post('/login', passport.authenticate('local'), (req, res) => {
        res.statusCode = 200
        res.setHeader('Content-Type', 'application/json')
        res.json({success: true, status: 'You are successfully logged in!'})
    })
    

    更改app.js

    ...
    var passport = require('passport')
    var authenticate = require('./authenticate')
    
    ...
    app.use(passport.initialize())
    app.use(passport.session())
    ...
    function basicAuth(req, res, next) {
        console.log(req.user)
        
        if(!req.user) {
            var err = new Error('You are not authenticated!')
            err.status = 403
            next(err)
        } else {
            next()
        }
    }
    ...
    
  • 相关阅读:
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    微信小程序TodoList
    C语言88案例-找出数列中的最大值和最小值
    C语言88案例-使用指针的指针输出字符串
  • 原文地址:https://www.cnblogs.com/wydumn/p/12590664.html
Copyright © 2020-2023  润新知