基于node的登入例子(node-koa-mongoose)

前言

这是一个基于node实现的一个简单登入例子,对于刚上手node想进一步了解,前端页面如何请求到服务层 -> 路由处理 -> 数据库操作 -> 返回结果到页面这整个过程的同学比较有用。这个例子基于github上两个项目(文末有链接),自己整理改写,希望有需要的同学可以看到。

项目源码地址https://github.com/linwalker/node-login/tree/v1.0

技术栈

  • node 使用 Koa框架,node版本7.6以上可以直接使用async/await;
  • 使用mongoose来与Mongodb数据库连接交互;
  • 前端使用react与antd-design组件;
  • webpack 打包构建

环境准备与运行

  • node.js >= 7.6
  • mongodb 安装
  • robomongo 安装 (mongodb的可视化工具)
  • mongodb 新建名为node-login的数据库,并开启;
  • npm install 安装依赖
  • npm run build 代码构建
  • node app 开启服务,可以访问localhost:3003/home

项目目录

node-login
    |-- components              //页面组件
        |-- LoginTab.js
        |-- RegisterTab.js
    |-- controller          //路由回调处理
        |-- user-info.js
    |-- models              //用户模型
        |-- user.js
    |-- pages                   //页面js
        |-- home
            |-- home.js
            |-- index.js
        |-- main
    |-- routes                  //路由
    |-- static                  //静态文件
    |-- tools                   //webpack构建文件
    |-- views                   //页面模版
    |-- .babelrc
    |-- app.js                  //入口文件
    |-- config.js               //配置文件
    |-- package.json

具体介绍

入口文件 - app.js

const Koa = require('koa');
const...
const app = new Koa();

// 配置控制台日志中间件
app.use(convert(koaLogger()));

// 使用ctx.body解析中间件
app.use(bodyParser());

// 配置服务端模板渲染引擎中间件
app.use(views(path.join(__dirname, './view'), {
    extension: 'ejs'
}));

// 配置静态资源加载中间件
app.use(convert(koaStatic(
    path.join(__dirname , './static')
)))

mongoose.Promise = global.Promise;
mongoose.connect(config.database);

// 初始化路由中间件
app.use(routers.routes()).use(routers.allowedMethods())

app.listen(3003);
console.log('The server is on prot 3003')

服务主要进行数据库连接,路由处理,静态文件配置和页面模板渲染。

配置文件 - config.js

module.exports = {
    'secrect': 'linwalkernodelogindemo', //暂未用到,用于后期token验证
    'database': 'mongodb://localhost:27017/node-login'//填写本地 mongodb 连接地址
};

主要设置连接mongodb数据的连接地址

用户模型 - user.js

定义登入注册的用户模型

const mongoose = require('mongoose');
const Schema = mongoose.Schema
const UserSchema = new Schema({
    username: {
        type: String,
        unique: true,
        require: true
    },
    password: {
        type: String,
        require: true
    },
    email: {
        type: String,
    }
});

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

用户模型主要三个数据,用户名,密码和邮箱。

路由

路由总入口/routes/index.js引入所有路由,使用koa-router中间件

const router = require('koa-router')();
const home = require('./home');
const main = require('./main');
const editor = require('./editor');

router.use('/home', home.routes(), home.allowedMethods());
router.use('/main', main.routes(), main.allowedMethods());
router.use('/editor', editor.routes(), editor.allowedMethods());

module.exports = router;

三个主路由为/home,/main//editor,主要来看下/home

const router = require('koa-router')();
const userInfoController = require('./../controller/user-info');

const routers = router
    .get('/', async (ctx) => {
        const title = 'login home';
        await ctx.render('home', {
            title
        })
    })
    .post('/signup', userInfoController.signUp)
    .post('/signin', userInfoController.signIn)

module.exports = routers;

home.jsget请求返回home页面,两个post请求,分别是注册和登入处理。我们来看下登入请求处理user-info.js

const User = require('./../models/user');

module.exports = {
    async signUp (ctx) {
        ...
    },

    async signIn (ctx) {
        let result = {
            success: false,
            message: '用户不存在'
        };
        //从请求体中获得参数
        const { username,  password } = ctx.request.body;
        //检查数据库中是否存在该用户名
        await User.findOne({
            username
        }, (err, user) => {
            if (err) {
                throw err;
            }
            if (!user) {
                ctx.body = result;
            } else {
                //判断密码是否正确
                if (password === user.password) {
                    ctx.body = {success: true, message: '登入成功'}
                } else {
                    ctx.body = {success: false, message: '密码错误'}
                }
            }
        })
    }
}

登入请求处理过程为先检查用户名是否存在,在判断密码是否正确。在来看下页面发起请求的地方

登入请求

class LoginTab extends React.Component {
    handleSubmit = async(e) => {
        e.preventDefault();
        let values = await this.getFormValues();
        if (values) {
            fetch('/home/signin', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json; charset=utf-8'
                },
                body: JSON.stringify(values)
            }).then(res => {
                res.json().then(res => {
                    Message.info(res.message);
                    if (res.success) {
                        location.href = '/main';
                    }
                })
            })
        }
    }
    getFormValues() {
        let self = this;
        return new Promise((resolve, reject) => {
            self.props.form.validateFields((err, values) => {
                if (!err) {
                    resolve( values );
                } else {
                    reject( false );
                }
            })
        })
    }
    render() {
        const { getFieldDecorator } = this.props.form;
        return (
            <div style={{ width: "280px", margin: "0 auto" }}>
                <Form onSubmit={this.handleSubmit}>
                              ...      
                </Form>
            </div>
        )
    }
}
export default Form.create()(LoginTab);

表单提交按钮绑定handleSubmit事件,该事件先获取表单提交数据,再发起/home/signin的post请求,根据请求结果的success值,来决定是否跳转到成功页面。这里用到antd-design表单组件的相应属性。

操作演示

演示用户名不存在,密码错误及成功登入。

登入.gif

总结

  • 使用了koa框架,主要是路由和ctx上下文的处理,没用过的同学可以点击koa2教程去看看,这是koa的一个入门教程写的很不错;
  • 使用了mongoose操作数据库,栗子中涉及的不难,只是一个User模型,一个save保存数据和一个findOne查找,看下文档就明白,或则看下这篇文章
  • 使用antd-design 组件

备注

这个例子主要参考了:
项目1
项目2

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容