Stateful session management: Store session which associate with user, and store in the menory on server.

Sign Up:

app.route('/api/signup')
.post(createUser);
import {Request, Response} from 'express';
import {db} from './database'; import * as argon2 from 'argon2';
import {validatePassword} from './password-validation';
import {randomBytes} from './security.utils';
import {sessionStore} from './session-store'; export function createUser (req: Request, res: Response) {
const credentials = req.body; const errors = validatePassword(credentials.password); if (errors.length > 0) {
res.status(400).json({
errors
});
} else {
createUserAndSession(res, credentials);
}
} async function createUserAndSession(res, credentials) {
// Create a password digest
const passwordDigest = await argon2.hash(credentials.password);
// Save into db
const user = db.createUser(credentials.email, passwordDigest);
// create random session id
const sessionId = await randomBytes(32).then(bytes => bytes.toString('hex'));
// link sessionId with user
sessionStore.createSession(sessionId, user);
// set sessionid into cookie
res.cookie('SESSIONID', sessionId, {
httpOnly: true, // js cannot access cookie
secure: true // enable https only
});
// send back to UI
res.status(200).json({id: user.id, email: user.email});
}

Password validation:

import * as passwordValidator from 'password-validator';

// Create a schema
const schema = new passwordValidator(); // Add properties to it
schema
.is().min(7) // Minimum length 7
.has().uppercase() // Must have uppercase letters
.has().lowercase() // Must have lowercase letters
.has().digits() // Must have digits
.has().not().spaces() // Should not have spaces
.is().not().oneOf(['Passw0rd', 'Password123']); // Blacklist these values export function validatePassword(password: string) {
return schema.validate(password, {list: true});
}

Random bytes generator:

const util = require('util');
const crypto = require('crypto'); // convert a callback based code to promise based
export const randomBytes = util.promisify(
crypto.randomBytes
);

Session storage:

import {Session} from './session';
import {User} from '../src/app/model/user';
class SessionStore {
private sessions: {[key: string]: Session} = {}; createSession(sessionId: string, user: User) {
this.sessions[sessionId] = new Session(sessionId, user);
} findUserBySessionId(sessionId: string): User | undefined {
const session = this.sessions[sessionId];
return this.isSessionValid(sessionId) ? session.user : undefined;
} isSessionValid(sessionId: string): boolean {
const session = this.sessions[sessionId];
return session && session.isValid();
} destroySession(sessionId: string): void {
delete this.sessions[sessionId];
}
} // We want only global singleton
export const sessionStore = new SessionStore();

In menory database:

import * as _ from 'lodash';
import {LESSONS, USERS} from './database-data';
import {DbUser} from './db-user'; class InMemoryDatabase { userCounter = 0; createUser(email, passwordDigest) {
const id = ++this.userCounter;
const user: DbUser = {
id,
email,
passwordDigest
}; USERS[id] = user; return user;
} findUserByEmail(email: string): DbUser {
const users = _.values(USERS);
return _.find(users, user => user.email === email);
}
} export const db = new InMemoryDatabase();

Login:

app.route('/api/login')
.post(login);
import {Request, Response} from 'express';
import {db} from './database';
import {DbUser} from './db-user';
import * as argon2 from 'argon2';
import {randomBytes} from './security.utils';
import {sessionStore} from './session-store'; export function login(req: Request, res: Response) { const info = req.body;
const user = db.findUserByEmail(info.email); if (!user) {
res.sendStatus(403);
} else {
loginAndBuildResponse(info, user, res);
}
} async function loginAndBuildResponse(credentials: any, user: DbUser, res: Response) {
try {
const sessionId = await attemptLogin(credentials, user);
res.cookie('SESSIONID', sessionId, {httpOnly: true, secure: true});
res.status(200).json({id: user.id, email: user.email});
} catch (err) {
res.sendStatus(403);
}
} async function attemptLogin(info: any, user: DbUser) {
const isPasswordValid = await argon2.verify(user.passwordDigest, info.password); if (!isPasswordValid) {
throw new Error('Password Invalid');
} const sessionId = await randomBytes(32).then(bytes => bytes.toString('hex'));
sessionStore.createSession(sessionId, user); return sessionId;
}

Logout:

app.route('/api/logout')
.post(logout);
import {Response, Request} from 'express';
import {sessionStore} from './session-store'; export const logout = (req: Request, res: Response) => {
console.log(req.cookies['SESSIONID']);
const sessionId = req.cookies['SESSIONID'];
sessionStore.destroySession(sessionId);
res.clearCookie('SESSIONID');
res.sendStatus(200);
};

[Node] Stateful Session Management for login, logout and signup的更多相关文章

  1. Spring Security笔记:自定义Login/Logout Filter、AuthenticationProvider、AuthenticationToken

    在前面的学习中,配置文件中的<http>...</http>都是采用的auto-config="true"这种自动配置模式,根据Spring Securit ...

  2. login/logout切换

    1. 前端按钮 <img border="0" width="18" height="18" src="<%=base ...

  3. YII session存储 调用login方法

    当要进行用户的session存储的时候,可以调用里面的login方法进行存储

  4. node express session

    在express4.0版本以上,需要单独增加session模块:express-session:https://www.npmjs.com/package/express-session 具体做法是, ...

  5. node中session存储与销毁,及session的生命周期

    1.首先在使用session之前需要先配置session的过期时间等,在入口文件app.js中 app.use(express.session({ cookie: { maxAge: config.g ...

  6. session management

    The session does not created until the HttpServletRequest.getSession() method is called.

  7. Use Spring transaction to simplify Hibernate session management

    Spring对Hibernate有很好的支持    DataSource ->SessionFactory-> HibernateTranscationManagerHibernate中通 ...

  8. node中session的管理

    请看这个博客:   http://spartan1.iteye.com/blog/1729148 我自己的理解 session俗称会话. 第一次访问服务器的时候由服务器创建,相当于一个cookie(就 ...

  9. Apache Shiro Session Management

    https://shiro.apache.org/session-management.html#session-management https://shiro.apache.org/session ...

随机推荐

  1. thinkphp路由的作用

    thinkphp路由的作用 问题 请问一下什么是thinkPHP路由,路由有什么作用?谢谢 解答 网络访问地址从来都是映射访问的,最初是这样,主机名(电脑名称)=>ip地址(如局域网192.16 ...

  2. css3透明度

    http://www.haorooms.com/post/css_common //透明度 div{ background: #00c2de; opacity: 0.9; filter: alpha( ...

  3. ES6特性-对比两个值是否相等

    因为JavaScript中有语言缺陷,所以出了个Object.is()

  4. vue抽取公共方法———方法一

    方法一:Vue插件 1.概述 作用:满足vue之外的需求,特定场景的需求 比如说,让你在每个单页面组件里,都可以调用某个方法(公共方法),或者共享某个变量等 2.使用方法 [声明插件]- [写插件]- ...

  5. ajax动态更新下拉列表

    前面做了一个ajax的小demo,今天看一个动态更新下拉列表,或者也叫级联更新下拉列表,这个也是利用ajax的异步调用去后台实现数据请求.然后回到前台完毕下拉列表数据的更新,以增强web应用的交互性. ...

  6. Java解析注解

    package com.itbuluoge.anno; import java.lang.reflect.Method; import java.util.ArrayList; import java ...

  7. 你如何理解 HTML5 的 section?会在什么场景使用?为什么这些场景使用 section 而不是 div?

    section元素表示文档或应用的一个部分.所谓“部分”,这里是指按照主题分组的内容区域,通常会带有标题.[也就是每个section对应不同的主题.注意是内容本身的主题,而不是其他人为设定的划分标准. ...

  8. javascript进阶教程第一章案例实战

    javascript进阶教程第一章案例实战 一.学习任务 通过几个案例练习回顾学过的知识 通过练习积累JS的使用技巧 二.实例 练习1:删除确认提示框 实例描述: 防止用户小心单击了“删除”按钮,在用 ...

  9. Python: PS 滤镜--扇形变换

    本文用 Python 实现 PS 滤镜中的一种几何变换特效,称为扇形变换,将图像扭曲成一个扇形,具体的算法原理和效果图可以参考以前的博客: http://blog.csdn.net/matrix_sp ...

  10. C# 开发 —— 数组类对象接口

    数组类型是从抽象基类 Array 派生的引用类型,通过new运算符创建数组并将数组元素初始化为他们的默认值 一维数组 type[] arrayname; 数组的长度不是声明的一部分,而且数组必须在访问 ...