想写了一个系列文章,就是剖析一个MVC架构的koa2博客项目,架构设计如上,(干巴巴的文章
1.判断用户名是否存在
routerAPI
// 用户名是否存在
router.post('/isExist', async (ctx, next) => {
//从客户端那拿到了 username
const { userName } = ctx.request.body
console.log(ctx.request.body);
//然后传给后端
ctx.body = await isExist(userName)
// ctx.body=ctx
})
复制代码
controller
async function isExist(userName) {
const userInfo = await getUserInfo(userName)
if (userInfo) {
// { errno: 0, data: {....} }
return new SuccessModel(userInfo)
} else {
// { errno: 10003, message: '用户名未存在' }
return new ErrorModel(registerUserNameNotExistInfo)
}
}
复制代码
server
/**
* 获取用户信息
* @param {string} userName 用户名
* @param {string} password 密码
*/
async function getUserInfo(userName, password) {
// 查询条件
const whereOpt = {
userName
}
//这里有传密码就返回了密码
if (password) {
Object.assign(whereOpt, { password })
}
// 查询
const result = await User.findOne({
attributes: ['id', 'userName', 'nickName', 'picture', 'city'],
where: whereOpt
})
if (result == null) {
// 未找到
return result
}
// 格式化-->这里是用来判断是否用户有自己的图像在上面
//没有就用自定义头像图片
const formatRes = formatUser(result.dataValues)
return formatRes
}
复制代码
model
//关联的数据库字段
// users
const User = seq.define('user', {
userName: {
type: STRING,
allowNull: false,
unique: true,
comment: '用户名,唯一'
},
password: {
type: STRING,
allowNull: false,
comment: '密码'
},
nickName: {
type: STRING,
allowNull: false,
comment: '昵称'
},
gender: {
type: DECIMAL,
allowNull: false,
defaultValue: 3,
comment: '性别(1 男性,2 女性,3 保密)'
},
picture: {
type: STRING,
comment: '头像,图片地址'
},
city: {
type: STRING,
comment: '城市'
}
})
复制代码
2.用户登陆
routerAPI
// 登录
router.post('/login', async (ctx, next) => {
const { userName, password } = ctx.request.body
console.log('request-body:',ctx.request.body)
ctx.body = await login(ctx, userName, password)
})
复制代码
controller
async function login(ctx, userName, password) {
// 获取用户信息
//docrypto是用来加密密码的
const userInfo = await getUserInfo(userName, doCrypto(password))
if (!userInfo) {
// 登录失败
return new ErrorModel(loginFailInfo)
}
// 登录成功
if (ctx.session.userInfo == null) {
ctx.session.userInfo = userInfo
//知识补充那里有详细介绍
}
return new SuccessModel()
}
复制代码
server
//userinfo 同上
复制代码
model
//user类 同上
复制代码
utils
const crypto = require('crypto')
const { CRYPTO_SECRET_KEY } = require('../conf/secretKeys')
//crypto_secret_key是自定义的随机值,用于数据加密加盐
/**
* md5 加密
* @param {string} content 明文
*/
function _md5(content) {
const md5 = crypto.createHash('md5')
return md5.update(content).digest('hex')
}
/**
* 加密方法
* @param {string} content 明文
*/
function doCrypto(content) {
//md5的加密,设计上是不可逆的,就是我没办法通过结果反推原始值,但它已经被破解了;
//可以通过crypto_secret_key加盐的方法进行进一步保障
//只要crypto_secret_key没泄漏就没问题
const str = `password=${content}&key=${CRYPTO_SECRET_KEY}`
return _md5(str)
}
复制代码
补充知识说明
1.关于session和cookie
(1)生动形象理解Cookie和Session的关系
1.Session是保存在服务器端,Cookie是保存在客户端。
2.每次用户访问网站的时候,相当于去串门。
3.用户带着cookie去服务器家,当当当敲门。
4.服务器问是谁啊?
5.用户:是我(cookie)啊!
6.服务器:让我来确认一下(session确认)。
7.服务器确认完毕后,放用户进门。
(2)实际网站登录请求的响应头
1.这是一个网站登录之后返回的响应头,可以看到服务器要求浏览器设置的Cookies有好几个;这
就是Cookies的来源,而token一般会作为用户的唯一凭证【登录成功,响应头set-cookies,浏览器设置Cookies】
2.当浏览器下一次再请求该网站时,浏览器会把这些Cookies放到请求头一起提交到服务器;而Cookies携带了SessionID信息 (token)【再次请求,带上Cookies,包含SessionID】
3.服务器通过SessionID即可找到对应的用户Session信息,然后判断该用户的登录状态【服务器根据SessionID获取用户登录态】
4.如果Session中某些设置登录状态的变量是有效期内的,证明用户处于登录状态【Session有效,用户已登录】
5.此时服务器就会返回需要登录之后才可以查看的网页内容,浏览器再进行解析便可以看到了【返回请求响应内容】
6.当Cookie无效或者Session已过期后,我们再访问网站就需要重新登录了【Cookie无效,Session过期,要再次登录】
2.md5
crypto模块的目的是为了提供通用的加密和哈希算法。用纯JavaScript代码实现这些功能不是不可能,但速度会非常慢。Nodejs用C/C++实现这些算法后,通过cypto这个模块暴露为JavaScript接口,这样用起来方便,运行速度也快。
MD5是一种常用的哈希算法,用于给任意数据一个“签名”。这个签名通常用一个十六进制的字符串表示:
const crypto = require('crypto');
const hash = crypto.createHash('md5');
// 可任意多次调用update():
hash.update('Hello, world!');
hash.update('Hello, nodejs!');
console.log(hash.digest('hex')); // 7e1977739c748beac0c0fd14fd26a544
复制代码
update()
方法默认字符串编码为UTF-8
,也可以传入Buffer。
如果要计算SHA1,只需要把'md5'
改成'sha1'
,就可以得到SHA1的结果1f32b9c9932c02227819a4151feed43e131aca40
。
还可以使用更安全的sha256
和sha512
。
3.关于md5后的一个小想法
我上面utils里面的密码,是加密而且用前端的secret_key加盐,md5是哈希加密不可逆,安全有保障了
那如果我有一个需求是,我数据库拿到加密的密码后,是要去能够自己解密后看原始值的,而且要保障安全性,那要怎么搞呢
下面这个算法是对称加密的,应该能实现我的那个需求(?好困,懒得研究,大佬看到后告诉我,不熬夜了
