Node.js_express_中间件 middleware_登录/注册实例源代码
静态资源:
都写死了的资源,如 css,html
解析规则:
所有路由和中间件都在一个数组中,js 引擎会按照代码先后顺序添加路由和中间件
当请求发送到服务器时,服务器获取当前的请求信息(请求方式、请求路由路径)
遍历数组,找到第一个匹配(请求路由路径和请求方式必须完全一致)到的路由或者中间件,执行其回调函数
意味着: 声明多个同名路由时,始终解析第一个
如果没找到,返回一个状态码为 404 的响应, Cannot GET / xxx 或者 Cannot POST / xxx
中间件 middleware
当有多个路由做同一件事情,这时就会交给中间件去完成
本质上就是一个函数 (request, response, next)=>{}
express 框架 实现服务器 完全是由 路由 和 中间件 组成的
需要调用 next() 方法,才会接下来处理下面的中间件或者路由,否则卡住了
- app.use(express.static('./public')); //默认调用next
接受请求,通过分析参数,找到了 public 对应资源就返回响应
将该文件夹下所有静态资源暴露出去
例如: 文件夹有
public/index.html
public/css/index.css
就可在浏览器访问
127.0.0.1:3000/index.html
127.0.0.1:3000/css/index.css
- app.use(express.urlencoded({extended: true})); //默认调用next
解析 请求体 数据,结果数据挂载到 req.body 上
- 实例分析:
// 1. 导入 express 模块
const express = require('express'); // 2. 创建 app 应用对象
const app = express(); // 3. 写业务逻辑:处理请求,返回响应 /**** 配置内置 中间件 (express 自带) ****/
// 将该文件夹下所有静态资源暴露出去
// 接受请求,通过分析参数,找到了 public 对应资源就返回响应
app.use(express.static('./public')); // public 下有 index.html css/index.css
// 可在127.0.0.1:3000/index.html css/index.css // 解析请求体数据,结果数据挂载到 req.body 上
app.use(express.urlencoded()); // 默认调用 next()
/**** 以上两个一般结合使用 ****/ // 中间件默认能接收并处理所有请求
// 需要调用 next() 方法,才会接下来处理下面的中间件或者路由,否则卡住了
app.use((request, response, next)=>{
next(); // 调用下一个中间件或者路由
});
/**************************************/ // route 路由的组成: app.请求方式('/路由路径', 句柄函数);
app.get('/login', (request, response)=>{
console.log(request.body);
response.send('Login Page Response!');
}); app.post('/register', (request, response)=>{
console.log(request.query);
response.send('Register Page Response!');
}); // 4. 监听端口号:一个端口号 有且只能运行 一个程序
app.listen(3000, err=>console.log(err?err:'服务器启动成功 : http://127.0.0.1:3000'));
登录/注册实例
- 什么时候用 get ,什么时候用 post?
get 请求 只有 请求字符串,
post 请求 既有 请求字符串,又有 表单数据 form-data
1. 凡是涉及到用户的隐私数据,就用 post,相对安全
2. 其他就用 get
- 业务逻辑
1. 导入 exoress 框架
2. 注册路由
由于默认访问不到静态资源,所以1引入中间件,暴露静态资源
默认不能解析 请求体 ,则2引入中间件,解析 请求体 数据(优先级低于上一中间件,避免多余分析)
① 获取用户提交的表单数据 req.body
② 对数据进行正则验证(验证数据的规范)
③ 检查用户名是否存在
连接数据库
User.findOne();
④ 保存在数据库中
User.create();
⑤ 无论 失败/成功 都要返回
3. 登录路由
4. 设置端口号,启动服务器监听
- 初次尝试,源代码
package.json
{
"name": "node_express",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"express": "^4.16.4",
"mongoose": "^5.4.0"
}
}
/route/register.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>用户注册</title> <link rel="stylesheet" type="text/css" href="css/index.css"/>
</head> <body>
<div id="outer_box" class="register">
<h2>用户注册</h2>
<form action="http://localhost:3000/register" method="post">
<div class="clothes">
<label for="input_name">用 户 名</label>
<input id="input_name" type="text" name="user_name" placeholder="请输入用户名" />
</div> <div class="clothes">
<label for="input_pwd">密 码</label>
<input id="input_pwd" type="password" name="user_pwd" placeholder="请输入密码" />
</div> <div class="clothes">
<label for="input_repwd">确认密码</label>
<input id="input_repwd" type="password" name="user_repwd" placeholder="请再次输入密码" />
</div> <div class="clothes">
<label for="input_email">注册邮箱</label>
<input id="input_email" type="text" name="user_email" placeholder="请输入邮箱地址" />
</div> <div class="clothes">
<button class="register btn" type="submit">注册</button>
<a class="btn" href="http://localhost:3000/login">
<button type="button">登录</button>
</a>
</div>
</form>
</div> <script type="text/javascript" src="../index.js"></script>
</body>
</html>
/route/login.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>用户登录</title> <link rel="stylesheet" type="text/css" href="css/index.css"/>
</head> <body>
<div id="outer_box" class="login">
<h2>用户登录</h2>
<form action="http://localhost:3000/login" method="post">
<div class="clothes">
<label for="input_name">用 户 名</label>
<input id="input_name" type="text" name="user_name" placeholder="请输入用户名" />
</div> <div class="clothes">
<label for="input_pwd">密 码</label>
<input id="input_pwd" type="password" name="user_pwd" placeholder="请输入密码" />
</div> <div class="clothes">
<a class="btn" href="http://localhost:3000/register">
<button type="button">注册</button>
</a>
<button class="login btn" type="submit">登录</button>
</div>
</form>
</div> </body>
</html>
/route/css/index.css
body {
width: 100%;
height: 100%; color: #000;
background: #b9c2a4;
background-size: cover; /* 指定背景图片大小 */
} /*************************************************/
#outer_box {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #1a45c3;
} #outer_box.login {
color: #9e098b;
} #outer_box.register {
color: #1a45c3;
} #outer_box>h2{
padding-bottom: 40px;
margin-left: -50px;
} .clothes {
width: 260px;
display: flex;
justify-content: space-between;
margin: 20px 0;
font-size: 18px;
line-height: 32px;
} .clothes>label{
width: 80px;
text-align: center;
} .clothes>input{
width: 170px;
height: 32px;
} button {
width: 100%;
height: 100%; font-size: 16px;
background-color: #c4ceda;
cursor: pointer;
} .clothes .btn{
width: 64px;
height: 32px;
margin: 0 20px;
} .clothes button.register{
background-color: #1a45c3;
color: #fff;
} .clothes button.login{
background-color: #9e098b;
color: #fff;
}
/db/connectDB.js
const mongoose = require('mongoose'); const promiseConnect = new Promise((resolve, reject)=>{
mongoose.connect('mongodb://localhost:27017/user_database', {useNewUrlParser:true})
mongoose.connection.once('open', err=>{
if(err){
console.log(err);
reject(err);
}else{
resolve(true);
};
});
}); module.exports = promiseConnect;
/db/tableModel.js
const mongoose = require('mongoose'); const Schema = mongoose.Schema;
const studentsSchema = new Schema({
"userName": {
"type": String,
"default": "test"
},
"userPassword": {
"type": String,
"default": "123456"
},
"userEmail": {
"type": String,
"unique": true
},
"createTime": {
"type": Date,
"default": Date.now()
}
}); const studentsModel = mongoose.model("user_info", studentsSchema); module.exports = studentsModel;
index.js
const express = require('express');
const promiseConnect = require('./db/connectDB.js');
const userInfoModel = require('./db/tableModel.js'); promiseConnect.then(async result=>{
if(result){
isConeected = true;
};
}).catch(err=>console.log(err)); const app = express(); /*********************** 中间件 **********************/
// 暴露路由 login.html register.html
app.use(express.static('route')); // 默认调用 next(); // 将 用户输入的数据 挂载到 请求体 request.body 上
app.use(express.urlencoded({extended: true})); // 默认调用 next(); /************************ get ***********************/
app.get('/', (request, response)=>{
response.redirect('./login.html');
}); app.get('/login', (request, response)=>{
response.redirect('./login.html');
}); app.get('/register', (request, response)=>{
response.redirect('./register.html');
}); /************************ post ***********************/ let isConeected = false;
let canBeCreated = false;
let createSuccess = false; let logined = false; app.post('/register', async (request, response)=>{
if(isConeected){
let uName = request.body['user_name'];
let uPwd = request.body['user_pwd'];
let urePwd = request.body['user_repwd'];
let uEmail = request.body['user_email'];
userInfo = {
"userName": uName,
"userPassword": uPwd,
"userEmail": uEmail
}; canBeCreated = false;
createSuccess = false;
someThingWrong = false; console.log('\n------------------注册--------------------');
if(urePwd !== uPwd){
console.log("(づ╥﹏╥)づ[两次输入不一致`]");
response.redirect('./register.html');
return ;
}else if(!(/^[a-zA-Z][a-zA-Z0-9_]{5,20}$/.test(uName))){
console.log("(づ╥﹏╥)づ[用户名不合法`]");
response.redirect('./register.html');
return ;
}else if(!(/^[a-zA-Z0-9_]{6,20}$/.test(uPwd))){
console.log("(づ╥﹏╥)づ[密码不合法`]");
response.redirect('./register.html');
return ;
}else if(!(/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(uEmail))){
console.log('(づ╥﹏╥)づ[邮箱不合法`]');
response.redirect('./register.html');
return ;
}else{
canBeCreated = true;
const badEmail = await userInfoModel.findOne({"userEmail": uEmail});
if(badEmail){
console.log('(づ╥﹏╥)づ[邮箱已存在`]');
response.redirect('./register.html');
return ;
};
}; const fond = await userInfoModel.findOne({"userName": uName});
if(!fond && canBeCreated){
await userInfoModel.create(userInfo);
createSuccess = true;
console.log('(o゜▽゜)o☆[注册成功!]☆');
}else{
console.log('(づ╥﹏╥)づ[用户名已存在`]');
};
}; if(createSuccess){
response.redirect('./login.html');
}else{
response.redirect('./register.html');
};
}); app.post('/login',async (request, response)=>{
if(isConeected){
let uName = request.body['user_name'];
let uPwd = request.body['user_pwd'];
userInfo = {
"userName": uName,
"userPassword": uPwd
}; logined = false; console.log('\n------------------登录--------------------');
if(!(/^[a-zA-Z][a-zA-Z0-9_]{5,20}$/.test(uName))){
logined = false;
// 用户名不存在
}else if(!(/^[a-zA-Z0-9_]{6,20}$/.test(uPwd))){
logined = false;
// 密码错误
}; const findName = await userInfoModel.findOne({"userName": uName});
const findPwd = await userInfoModel.findOne({"userPassword": uPwd});
if(findName && findPwd){
logined = true;
};
}; console.log(logined?'(o゜▽゜)o☆[登录成功!]☆':'(づ╥﹏╥)づ[用户名或密码错误`]');
response.redirect('./login.html');
}); /**************** 监听 3000, 启动服务器 ***************/
app.listen(3000, err=>console.log(err?err:'\n\n服务器已启动: http://localhost:3000\nHunting Happy!'));
改进后,源代码
package.json
{
"name": "node_express",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"express": "^4.16.4",
"mongoose": "^5.4.0"
}
}
templates/login.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>用户登录</title> <link rel="stylesheet" type="text/css" href="css/index.css"/>
</head> <body>
<div id="outer_box" class="login">
<h2>用户登录</h2>
<form action="http://localhost:3000/login" method="post">
<div class="clothes">
<label for="input_name">用 户 名</label>
<input id="input_name" type="text" name="user_name" placeholder="请输入用户名" />
</div> <div class="clothes">
<label for="input_pwd">密 码</label>
<input id="input_pwd" type="password" name="user_pwd" placeholder="请输入密码" />
</div> <div class="clothes">
<a class="btn" href="http://localhost:3000/register">
<button type="button">注册</button>
</a>
<button class="login btn" type="submit">登录</button>
</div>
</form>
</div>
</body>
</html>
templates/register.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>用户注册</title> <link rel="stylesheet" type="text/css" href="css/index.css"/>
</head> <body>
<div id="outer_box" class="register">
<h2>用户注册</h2>
<form action="http://localhost:3000/register" method="post">
<div class="clothes">
<label for="input_name">用 户 名</label>
<input id="input_name" type="text" name="user_name" placeholder="请输入用户名" />
</div> <div class="clothes">
<label for="input_pwd">密 码</label>
<input id="input_pwd" type="password" name="user_pwd" placeholder="请输入密码" />
</div> <div class="clothes">
<label for="input_repeat_pwd">确认密码</label>
<input id="input_repeat_pwd" type="password" name="user_repeat_pwd" placeholder="请再次输入密码" />
</div> <div class="clothes">
<label for="input_email">注册邮箱</label>
<input id="input_email" type="text" name="user_email" placeholder="请输入邮箱地址" />
</div> <div class="clothes">
<button class="register btn" type="submit">注册</button>
<a class="btn" href="http://localhost:3000/login">
<button type="button">登录</button>
</a>
</div>
</form>
</div>
</body>
</html>
templates/css/index.css
@charset "utf-8"; * {
margin: 0px;
padding: 0px;
} .clearfix {
zoom:;
} .clearfix:before,
.clearfix:after {
content: "";
display: table;
clear: both;
} .unSelectedAble {
/* 内容不可以被选中 */
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
} body {
width: 100%;
height: 100%; color: #000;
background: #b9c2a4;
background-size: cover; /* 指定背景图片大小 */
} /*************************************************/
#outer_box {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #1a45c3;
} #outer_box.login {
color: #9e098b;
} #outer_box.register {
color: #1a45c3;
} #outer_box>h2{
padding-bottom: 40px;
margin-left: -50px;
} .clothes {
width: 260px;
display: flex;
justify-content: space-between;
margin: 20px 0;
font-size: 18px;
line-height: 32px;
} .clothes>label{
width: 80px;
text-align: center;
} .clothes>input{
width: 170px;
height: 32px;
} button {
width: 100%;
height: 100%; font-size: 16px;
background-color: #c4ceda;
cursor: pointer;
} .clothes .btn{
width: 64px;
height: 32px;
margin: 0 20px;
} .clothes button.register{
background-color: #1a45c3;
color: #fff;
} .clothes button.login{
background-color: #9e098b;
color: #fff;
}
db/index.js
const mongoose = require('mongoose'); module.exports = new Promise((resolve, reject)=>{
mongoose.connect('mongodb://localhost:27017/user_database', {useNewUrlParser:true})
mongoose.connection.once('open', err=>{
if(err){
console.log(err);
reject(err);
}else{
resolve('数据库已连接');
};
});
});
models/index.js
const mongoose = require('mongoose'); const Schema = mongoose.Schema;
const fieldSchema = new Schema({
"userName": {
"type": String,
"unique": true,
"required": true
},
"userPassword": {
"type": String,
"unique": true,
"required": true
},
"userEmail": {
"type": String,
"unique": true,
"required": true
},
"createTime": {
"type": Date,
"default": Date.now()
}
}); module.exports = mongoose.model("user_info", fieldSchema);
index.js
const express = require('express');
const promiseConnect = require('./db');
const userInfoModel = require('./models'); const app = express(); /*********************** 中间件 **********************/
// 暴露路由 login.html register.html
app.use(express.static('templates')); // 默认调用 next(); // 将 用户输入的数据 挂载到 请求体 request.body 上
app.use(express.urlencoded({extended: true})); // 默认调用 next(); /************************ get ***********************/
app.get('/', (request, response)=>{
response.redirect('./login.html');
}); app.get('/login', (request, response)=>{
response.redirect('./login.html');
}); app.get('/register', (request, response)=>{
response.redirect('./register.html');
}); /************************ post ***********************/
let logged = false ;
promiseConnect.then(async result=>{
console.log(result); app.post('/register', async (request, response)=>{
const {
user_name:uName,
user_pwd:uPwd,
user_repeat_pwd:urePwd,
user_email:uEmail,
} = request.body; /**** 解构赋值 ****/
// let uName = request.body['user_name'];
// let uPwd = request.body['user_pwd'];
// let urePwd = request.body['user_repeat_pwd'];
// let uEmail = request.body['user_email'];
userInfo = {
"userName": uName,
"userPassword": uPwd,
"userEmail": uEmail
}; let errInfo = {}; if(urePwd !== uPwd){
errInfo.repeatPassword = '两次输入不一致';
};
if(!(/^[a-zA-Z][a-zA-Z0-9_]{5,20}$/.test(uName))){
errInfo.name = '用户名不合法';
};
if(!(/^[a-zA-Z0-9_]{6,20}$/.test(uPwd))){
errInfo.password = '密码不合法';
};
if(!(/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(uEmail))){
errInfo.email = '邮箱不合法';
}; const badEmail = await userInfoModel.findOne({"userEmail": uEmail});
if(badEmail){
errInfo.emailRegistered = '邮箱已被注册';
}; if(errInfo.repeatPassword || errInfo.name || errInfo.password || errInfo.email){
response.send(errInfo);
return;
}; const fond = await userInfoModel.findOne({"userName": uName});
if(fond){
response.send({"error":'用户名已被注册'});
}else{
await userInfoModel.create(userInfo);
response.send({"success":'注册成功'});
};
}); app.post('/login',async (request, response)=>{
logged = false;
let uName = request.body['user_name'];
let uPwd = request.body['user_pwd'];
userInfo = {
"userName": uName,
"userPassword": uPwd
}; if(!(/^[a-zA-Z][a-zA-Z0-9_]{5,20}$/.test(uName))){
logged = false; // 用户名不存在
}else if(!(/^[a-zA-Z0-9_]{6,20}$/.test(uPwd))){
logged = false; // 密码错误
}; const findName = await userInfoModel.findOne({"userName": uName});
const findPwd = await userInfoModel.findOne({"userPassword": uPwd});
if(findName && findPwd){
logged = true;
}; response.send(logged?{"success":'登录成功'}:{"error":'用户名或密码错误'});
});
}).catch(err=>console.log(err)); /**************** 端口号 3000, 启动服务器 ***************/
app.listen(3000, err=>console.log(err?err:'\n\n服务器已启动: http://localhost:3000\nHunting Happy!'));
Node.js_express_中间件 middleware_登录/注册实例源代码的更多相关文章
- Vue学习之路之登录注册实例代码
Vue学习之路之登录注册实例代码:https://www.jb51.net/article/118003.htm vue项目中路由验证和相应拦截的使用:https://blog.csdn.net/wa ...
- vue-cli——vue-resource登录注册实例
前言 使用vue-resource请求接口非常方便,在使用前需安装vue-resource依赖并在入口文件main.js中声明. 实例功能简述 本实例只有简单的两个模块:登录和注册,主要演示如何用vu ...
- 2.node.js (二)服务器登录注册 与 包的发布
get: 不安全 小 2k 数据会在地址栏上显示 从服务器获取 快 post: 相对安全 https 大 1G 不会 向服务器发送 慢 get:直接解析url地址 借助 url模块 var urlOb ...
- ASP.NET简单登录注册实例
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx. ...
- node+mysql+express实现登录/注册/修改密码/删除用户 接口
实现用户的注册.登录.修改密码.删除用户操作 用到的数据库:nodecms:表:user 目录结构: db目录下存放数据库操作语句: userSQL.js 用户有关的操作语句 router目录 接口路 ...
- Node.js_express_浏览器存储技术 Cookie(服务器将少量数据交于浏览器存储管理)
浏览器存储技术 Cookie 服务器将少量数据交于浏览器存储管理 解决 http 无状态协议的问题(无法区分多次请求是否发送自同一客户端) 一个网页一般最多 20个的 cookie,每个 cookie ...
- Node.js_express_服务器渲染页面 ejs
服务器渲染页面 ejs 高效的 js 模版引擎 将数据提前渲染到页面上, 再将渲染好的页面返回响应给浏览器 提高首页加载速度 SEO 提前处理,提高加载速度 下载 ejs 包 npm install ...
- Node.js_express_临时会话对象 session
临时会话对象 session 也是用来 解决 http 无状态协议的问题(无法区分多次请求是否发送自同一客户端) npm install express-session npm install con ...
- Nodejs学习总结 -Express 登录注册示例(二)
项目创建后,我们来做个登录注册实例,详细操作步骤如下. 1.新建项目demo ,具体操作步骤参考上一章内容 https://www.cnblogs.com/Anlycp/ 2.添加mysql和sess ...
随机推荐
- 模板方法模式-Template Method(Java实现)
模板方法模式-Template Method 在模板模式中, 处理的流程被定义在父类中, 而具体的处理则交给了子类. 类关系图很简单: Template接口 这里定义了子类需要实现的方法(before ...
- 巧用border制作箭头
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- DirectX11 With Windows SDK--09 纹理映射与采样器状态
前言 在之前的DirectX SDK中,纹理的读取使用的是D3DX11CreateShaderResourceViewFromFile函数,现在在Windows SDK中已经没有这些函数,我们需要找到 ...
- Linux运维(首页)
系统学习,以此见证学习历程 Linux运维基础 安装vmware+centos Linux基础 Linux的一些问题 Ubuntu遇到的bug linux_网易云音乐安装 linux_添加图标 遇到的 ...
- oldboy s21day13装饰器和推导式
#!/usr/bin/env python# -*- coding:utf-8 -*- # 2.请为 func 函数编写一个装饰器,添加上装饰器后可以实现:执行func时,先输入"befor ...
- WEB内容换行
word-wrap:break-word 单词间换行 word-break:break-all 单词内也可以换行 white-space属性指定元素内的空白怎样处理 normal 默认.空白会被浏览器 ...
- word插入公式不自动斜体的解决办法
1.word-视图-宏 2.自己随便输入一个宏名,比如就叫InsertEqua,然后将 Sub InsertEqua() Selection.OMaths.Add Range:=Selection.R ...
- How far away ? HDU - 2586 【LCA】【RMQ】【java】
题目大意:求树上任意两点距离. 思路: dis[i]表示i到根的距离(手动选根),则u.v的距离=dis[u]+dis[v]-2*dis[lca(u,v)]. lca:u~v的dfs序列区间里,深度最 ...
- 快速查看linux命令的用法----------TLDR
之前我们如果用一个命令,但是忘了具体的参数是什么的时候,通常会用man,比如 man tar 但是man有时候特别的冗长,你要找到想要的例子非常困难,所以tldr命令就是一个很好的补充,里边会有经常用 ...
- mybatis(入门级项目)
框架的搭建:(两个java类,两个xml配置文件) 1.导入jar包,日志debug文件以及数据库的参数文件 2.建立持久化类(和数据库的列值相同的类) user类的一个扩展类: userQueryV ...