Сесии

HTTP протокол

  • Stateless протокол.
  • Заявките са независими помежду си.
  • Не могат да се проследяват свързани заявки.
  • Как се идентифицират потребителите?

Сесия

  • Поредица от непрекъснати действия на потребител на дадено уеб приложение в рамките на определен период от време.
  • Данните се съхраняват под формата на наредени двойки ключ - стойност.

Къде се съхраняват сесиите?

  • в бисквитки в браузъра на потребителя
  • в localStorage
  • в sessionStorage
  • в паметта на backend приложението
  • в база данни
  • в кеш паметта на backend приложението

Съхраняване на сесия в кеша

Предимства

  • бързо извличане на данни
  • по-малко зависимости
  • може да се използва за няколко приложения
  • управлява се автоматично

Недостатъци

  • допълнителен ресурс
  • не е подходящо за малки приложения
  • нулиране на кеша => унищожаване на всички сесии

Сесии в контекста на Express

Как да създадем сесия с Express?

							
import * as express from 'express';
import * as uuid from 'uuid/v4';
import * as session from 'express-session';
import * as Memcached from 'memcached';
import * as memcached from 'connect-memcached';

const app = express();
const memcachedServer = new Memcached(`${MEMCACHED_HOST}:${MEMCACHED_PORT}`);
const MemcachedStore = memcached(session);

app.use(session({
	genid: (req) => {
		return uuid.v4().toString();
	},
	secret: SESSION_SECRET_KEY,
	store   : new MemcachedStore({
		hosts: [`${MEMCACHED_HOST}:${MEMCACHED_PORT}`], 
		secret: MEMCACHED_SECRET_KEY
	})
}));							
							
						

Как да съхраняваме данни в сесия с Express?

							
app.get('/', function(req, res, next) {
	let sessData = req.session;
	sessData.someAttribute = "foo";
	res.send('Returning with some text');
});															   
							
						

Как да извличаме данни от сесия с Express?

							
app.get('/bar', function(req, res, next) {
	let someAttribute = req.session.someAttribute;
	res.send(`This will print the attribute I set earlier: ${someAttribute}`);
});																							  
							
						

Как да нулираме сесия с Express?

							
app.get('/logout', function(req, res, next) {
	req.session.destroy((error) => {
		if (error) {
			console.error(error);
		}
	});
});																							  
							
						

Бисквитки

Mалка част от данни, която се съхранява в браузъра на потребителя.

Наредена двойка име - стойност.

Имат определен живот.

Cookies в Express?

							
import * as express from 'express';
import * as cookieParser from 'cookie-parser';
	
const app = express();

app.use(cookieParser());

app.get('/', function (req, res) {
	const token = 'some token';
	console.log('Cookies: ', req.cookies);
	res.cookie('user', token, { maxAge: 60 * 60 * 24 * 30, httpOnly: true, secure: true });
	res.setHeader('Set-Cookie', `user=${token};`);
	res.send(token);
});
							
						

Други начини за управление на сесии

  • URL Rewriting
  • JSON Web Tokens (JWT)

Оторизация и автентикация

Оторизация - процес на предоставяне на възможност на някого за достъп до даден ресурс.

Автентикация - идентифициране на потребител.

Пароли

Никога не трябва паролите да се съхраняват в чист вид, както в модела на данните, така и в самата база данни.

Хеширащи функции

На даден низ съпоставят друг низ с фиксиран размер.

Хеширащите функции имат две важни свойства:

  • Функцията е необратима.
  • Функцията е детерминистична.

Хеширане на пароли в Express?

						
import * as bcrypt from 'bcrypt';

bcrypt.hash(user.password, 10, async (error: Error, hash: string) => {
	await User.create(
		{ username: user.username, password: hash, email: user.email }, 
		(error: Error, newUser: IUser) => {
			if (error) {
				console.error(error);
			}
		});
});
						
					

Автентикация с Express?

						
import { Request, Response } from 'express';
import * as bcrypt from 'bcrypt';
import UserController from '../controllers/user-controller';

let controller = new UserController();

const auth = async (request: Request, response: Response, next: () => void) => {
	const { username, password } = request.body;

	const user = await controller.findUser(username);

	if (user) {
		bcrypt.compare(
			password, 
			user.password, 
			(error: Error, result: boolean) => {
				if (result) {
					next();
				} else {
					response.status(401).send('Unauthorized');
				}
			});
	}
}
						
					

Въпроси?