第一部分:项目搭建

1. 初始化

npm init

2. 安装第三方拓展包

按需安装

##安装express框架
npm install express

3. 创建app.js

在这里插入图片描述

编写代码

const express = require('express');
const app = express();


// start server
const port = process.env.NODE_ENV === 'production' ? (process.env.PORT || 80) : 3030;
app.listen(port, function () {
    console.log('Server listening on port ' + port);
});


4. 启动

node app

在这里插入图片描述

5. 按Ctrl+c退出

6.网络 请求模块

6.1.跨域

## /*允许跨域*/
npm install cors

/*CORS stands for Cross Origin Resource Sharing and allows modern web browsers to be able to send AJAX requests and receive HTTP responses for resource from other domains other that the domain serving the client side application.*/
const cors = require('cors');
app.use(cors());

6.2 http请求体中间件:body-parser

##安装body-parser是一个http请求体中间件,处理json,raw,URL-encoded格式请求体等
npm install body-parser
//Parse incoming request bodies in a middleware before your handlers, available under the req.body property.
const bodyParser = require('body-parser');

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

7. 安全验证与错误处理

创建一个_helps的文件夹,
在下面创建两个文件,分布命名为jwt.jserror-handler.js
在这里插入图片描述

7.1 JWT

使用express-jwt,这是一个中间件,用于验证JsonWebTokens

在第8步之前不推荐使用

1. 安装

npm install express-jwt

2. 在项目根目录下创建config.json
config.json

{

    "secret": "a secret that no one should guess",
}

jwt.js

const expressJwt = require('express-jwt');
const config = require('../config.json');

module.exports = jwt;

//expressJwt(...) returns a function that takes three paramaters req, res and next. Thus, this will register as
// middleware.
function jwt() {
    const secret = config.secret;
    return new expressJwt({
        secret,
        algorithms:['HS256'],
        allowCredentials:false,//设置为false表示游客也可以访问
    }).unless({
        path: [
            // public routes that don't require authentication
            '/',
        ]
    });
}

app.js

const jwt = require('./_helpers/jwt');
app.use(jwt());

7.2 error Handler

在_helper下的error-handler.js代码

module.exports = errorHandler;

function errorHandler(err, req, res, next) {
    if (typeof (err) === 'string') {
        // custom application error
        return res.status(400).json({ message: err });
    }

    if (err.name === 'ValidationError') {
        // mongoose validation error
        return res.status(400).json({ message: err.message });
    }

    if (err.name === 'UnauthorizedError') {

        // jwt authentication error
        return res.status(401).json({ message: 'Invalid Token'});
    }

    // default to 500 server error
    console.log("Error:", err);
    return res.status(500).json({ message: err.message });
}

app.js

// Our error handler
const errorHandler = require('./_helpers/error-handler');
app.use(errorHandler);

8. 路由配置

在根目录下创建一个文件夹routes用于存放路由的配置文件,在routes文件夹下创建user.router.js用与配置user相关的路由。

user.router.js

//user router
var express = require('express');
var router = express.Router();

router.get('/hello', function (req,res,next){
    res.json('hello');
});

module.exports = router;

app.js

app.use('/user', require('./routes/user.router'));

路由地址为:

浏览器访问

启动node app
在这里插入图片描述

这时候你在浏览器打开http://localhost:3030/user/hello发现出现401这是因为我们配置的jwt生效了,这时候你把app.js中的app.use(jwt());删除掉之后就能争取成功访问
在这里插入图片描述

第一部分全部代码

在这里插入图片描述

app.js

const express = require('express');
const app = express();

/*CORS stands for Cross Origin Resource Sharing and allows modern web browsers to be able to send AJAX requests and receive HTTP responses for resource from other domains other that the domain serving the client side application.*/
const cors = require('cors');


//Parse incoming request bodies in a middleware before your handlers, available under the req.body property.
const bodyParser = require('body-parser');

// Our JWT logic. Uses express-jwt which is a middleware that validates JsonWebTokens and sets req.user.
const jwt = require('./_helpers/jwt');

// Our error handler
const errorHandler = require('./_helpers/error-handler');


app.use(cors());

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

//暂时不用
//app.use(jwt());

app.use(errorHandler);

app.use('/user', require('./routes/user.router'));

// start server
const port = process.env.NODE_ENV === 'production' ? (process.env.PORT || 80) : 3030;
app.listen(port, function () {
    console.log('Server listening on port ' + port);
});

config.json

{

    "secret": "a secret that no one should guess",
  
}

_helper/jwt.js

const expressJwt = require('express-jwt');
const config = require('../config.json');

module.exports = jwt;

//expressJwt(...) returns a function that takes three paramaters req, res and next. Thus, this will register as
// middleware.
function jwt() {
    const secret = config.secret;
    return new expressJwt({
        secret,
        algorithms:['HS256'],
    }).unless({
        path: [
            // public routes that don't require authentication
            '/',
        ]
    });
}

_helper/error-handler.js

module.exports = errorHandler;

function errorHandler(err, req, res, next) {
    if (typeof (err) === 'string') {
        // custom application error
        return res.status(400).json({ message: err });
    }

    if (err.name === 'ValidationError') {
        // mongoose validation error
        return res.status(400).json({ message: err.message });
    }

    if (err.name === 'UnauthorizedError') {

        // jwt authentication error
        return res.status(401).json({ message: 'Invalid Token'});
    }

    // default to 500 server error
    console.log("Error:", err);
    return res.status(500).json({ message: err.message });
}

routes/user.router.js

//user router
var express = require('express');
var router = express.Router();

router.get('/hello', function (req,res,next){
    res.json('hello');
});

module.exports = router;

到这里整体框架就搭建好了。

第二部分:用户登录注册实现

1. 数据库

Mongodb

你的计算机需要安装Mongodb,安装教程这里不介绍。
1.1 安装nodejs的mongodb扩展库

##安装mongodb数据库
npm install mongoose

1.2 配置config.json
config.json修改为:

{

    "secret": "a secret that no one should guess",
    "connectionString": "mongodb://localhost/travel"
}

数据库名为:travel

1.3 user.model
在根目录下创建models文件夹,在该文件夹下创建user.model.js,集合名为:User
在这里插入图片描述

const mongoose = require('mongoose');
const Schema = mongoose.Schema;


const schema = new Schema({
        username: { type: String, unique: true, required: true },//登录的用户名,唯一
        email: { type: String, unique: true, required: true },//邮箱,唯一
        hash: { type: String, required: true },//加密之后的密码
        nickname: { type: String, required: true },
        age: { type: Number, required: true },
    }
);

schema.set('toJSON', { virtuals: true });

module.exports = mongoose.model('User', schema);

database工具

_helps 下创建database.js

database.js

const config = require('../config.json');
const mongoose = require('mongoose');
mongoose.connect(process.env.MONGODB_URI || config.connectionString, {  useNewUrlParser: true });
//mongoose.Promise = global.Promise;

module.exports = {
    User: require('../models/user.model'),
};


3.Service层

3.1 注册:添加用户

在根目录下创建services 文件夹,在该文件夹下创建user.service.js,用于对User集合的增删改查。
在这里插入图片描述

密码不加密

user.service.js

const db = require('../_helpers/database');
const User = db.User;


async function addUser(userParam) {

    // validate
    if (await User.findOne({ username: userParam.username })) {
        throw 'Username "' + userParam.username + '" is already taken';
    }
    else  if (await User.findOne({ email: userParam.email })) {
        throw 'Email "' + userParam.email + '" is already taken';
    }

    const user = new User(userParam);

    // hash password
    if (userParam.password) {
        //不加密
        user.password=userParam.password;
        //密码加密,未实现
        // user.hash = bcrypt.hashSync(userParam.password, 10);
    }

    // save user
    await user.save();
}


module.exports = {
    addUser,
}

4.controller层

在根目录下创建controllers 文件夹,在该文件夹下创建user.controller.js,用于对User集合的增删改查。

user.controller.js

const userService = require('../services/user.service')

function register(req, res, next) {
    userService.addUser(req.body)
        .then(() => res.json('Register success!'))
        .catch(err => next(err));
}

module.exports = {
    register,
}

5.路由配置

routes/user.routers.js修改为

//user router
var express = require('express');
var router = express.Router();
const userController = require('../controllers/user.controller');

router.post('/register', userController.register);

module.exports = router;

注册接口为POST: http://localhost:3030/user/register

注册密码加密

npm install bcryptjs

user.service.js

const db = require('../_helpers/database');
const User = db.User;
const bcrypt = require('bcryptjs');

async function addUser(userParam) {

    // validate
    if (await User.findOne({ username: userParam.username })) {
        throw 'Username "' + userParam.username + '" is already taken';
    }
    else  if (await User.findOne({ email: userParam.email })) {
        throw 'Email "' + userParam.email + '" is already taken';
    }

    const user = new User(userParam);

    // hash password
    if (userParam.password) {
        user.hash = bcrypt.hashSync(userParam.password, 10);
    }

    // save user
    await user.save();
}


module.exports = {
    addUser,
}

登录

 npm install jsonwebtoken

user.server.js

const db = require('../_helpers/database');
const User = db.User;
const bcrypt = require('bcryptjs');
const config = require('../config.json');
const jwt = require('jsonwebtoken');

async function addUser(userParam) {

    // validate
    if (await User.findOne({ username: userParam.username })) {
        throw 'Username "' + userParam.username + '" is already taken';
    }
    else  if (await User.findOne({ email: userParam.email })) {
        throw 'Email "' + userParam.email + '" is already taken';
    }

    const user = new User(userParam);

    // hash password
    if (userParam.password) {
        user.hash = bcrypt.hashSync(userParam.password, 10);
    }

    // save user
    await user.save();
}

//login
async function authenticate({ username, password }) {

    const user = await User.findOne({ username });
    if (user && bcrypt.compareSync(password, user.hash)) {
        const { hash, ...userWithoutHash } = user.toObject();
        const token = jwt.sign({ sub: user.id, role: user.role }, config.secret);
        return {
            ...userWithoutHash,
            token
        };
    }
}

module.exports = {
    addUser,
    authenticate,
}

user.controller.js

const userService = require('../services/user.service')

function register(req, res, next) {
    userService.addUser(req.body)
        .then(() => res.json('Register success!'))
        .catch(err => next(err));
}


function authenticate(req, res, next) {
    console.log("Authenticate():", req.body);
    userService.authenticate(req.body)
        .then(user => user ? res.json(user) : res.status(400).json({ message: 'Username or password is incorrect' }))
        .catch(err => next(err));
}
module.exports = {
    register,
    authenticate
}

user.router.js添加

router.post('/authenticate', userController.authenticate);

启动

注意:一定要先启动mongodb,然后再用node app启动nodejs项目

用到的第三方扩展

##安装express框架
npm install express
##安装mongodb数据库
npm install mongoose
##安装body-parser是一个http请求体中间件,处理json,raw,URL-encoded格式请求体等
npm install body-parser

## 加密
npm install bcryptjs

npm install express-jwt

npm install jsonwebtoken


Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐