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. js如何生成[n,m]的随机数(整理总结)

    js如何生成[n,m]的随机数(整理总结) 一.总结 一句话总结: // max - 期望的最大值 // min - 期望的最小值 parseInt(Math.random()*(max-min+1) ...

  2. Ionic2集成ArcGIS JavaScript API.md

    1. Ionic同原生ArcGIS JavaScript API结合 1.1. 安装esri-loader 在工程目录下命令行安装: npm install angular2-esri-loader ...

  3. cf 828 A. Restaurant Tables

    A. Restaurant Tables time limit per test 1 second memory limit per test 256 megabytes input standard ...

  4. 昼猫笔记 JavaScript -- 闭包

      本次主要内容是 闭包 阅读时间: 约 3分钟 记得点个赞支持支持我哦 初步了解 先看下代码,输出结果是多少? function fn1 () { var a = 2 function fn2 () ...

  5. Hexo 自动同步

    灵感 最近认证阿里云学生用户,参与ESC服务器9.9元/月的活动,准备先搭建一个博客网站,写写自已的心得以及经验.之前也搭建过网站,最后由于个人没时间(没时间是假的,就是懒.哈哈)的原因导致最后服务器 ...

  6. android对话框显示异常报错:You need to use a Theme.AppCompat theme (or descendant) with this activity.

    今天写android实验碰到到一个问题,在用AlertDialog.Builder类构建一个对话框之后,调用Builder.show()方法时抛出异常如下: - ::-/xyz.qlrr.sqlite ...

  7. linux 查看tomcat 实时日志

    进入tomcat下logs文件夹下,若没有Catalina.out文件先去启动服务在回到logs文件夹输入 tail -f catalina.out ,可看到实时日志

  8. myeclipse中断点调试

    在代码最左端,也就是行号位置处双击.会出现一个实心小圆点.即增加的断点.debug启动程序,就会运行到断点处: 按F5是进去方法里面. 按F6是一步一步走, 按F7是跳出方法里面(按F5后再按F7就跳 ...

  9. Reuse Is About People and Education, Not Just Architecture

     Reuse Is About People and Education, Not Just Architecture Jeremy Meyer you MigHT AdopT THE AppRoA ...

  10. SpringMVC-@RequestMapping的参数和用法

    RequestMapping里面的注解包含的参数如图: RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上.用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径. ...