Используем сессии для авторизации
Все любят печеньки
Часто в веб-сервисах возникает необходимость идентифицировать текущего пользователя (т.е., что текущий пользователь - Вася Пупкин, модератор) или получить какую-либо информацию про него (текущий пользователь предпочитает зеленый цвет фона, заходил на сайт 10 раз).
Обычно для этого испольуются cookie файлы. О них мы сегодня и поговорим.
Cookie файлы - это небольшие текстые файлы, которые сайт может хранить в браузере пользователя. Браузер будет присылать их серверу вместе с каждым запросом. В ответе можно попросить браузер что-то удалить или добавить.
С точки зрения программиста бекенда, можно считать, что cookie файлы представляют из себя словарь. Про работу с "чистыми" куками можно почитать здесь.
Но с cookie файлами есть проблема - пользователь может добавлять, изменять, читать и удалять их по своему усмотрению. А значит мы не можем им доверять. Решение этой проблемы - использование сессий!
Сессии - безопасная альтернатива cookie
Сессии - это более безопасные способ хранить данные о пользователе, причем в разных языках этот механизм реализован по разному. Например, сессии в PHP - это когда мы храним данные на сервере, а у пользователя храним только ключ доступа к этим данным.
Во фласке все данные по-прежнему храняться в cookie, но подписываются секретным ключом. Благодаря этому пользователь может посмотреть или удалить данные, но изменить по своему усмотрению уже не может.
С точки зрения программиста, сессия - это словарь, который сохраняет свои значения между запросами пользователя (и в разных функциях).
- В начале программы нам нужно задать ключ для подписи cookie файлов и импортировать объект
session
из библиотекиflask
.
from flask import Flask, session
app = Flask(__name__)
# Details on the Secret Key: https://flask.palletsprojects.com/en/1.1.x/config/#SECRET_KEY
app.secret_key = 'BAD_SECRET_KEY'
- Когда мы хотим что-то записать о пользователе, мы просто кладем это в словарь
session
.
session['email'] = "lupa@glavbuh.ru"
- А когда хотим получить это обратно - просто берем из словаря session.
email = session.get('email')
P.S. Можно написать и session['email']
, но если почты там нет, вылетит ошибка. А метод get
просто вернет None
и программа продолжит свою работу.
Цветосайт
Ниже пример сервиса, в котором пользователь может выбирать цвет фона для страницы. Цвет мы запонимаем в словаре session
.
from flask import Flask, render_template, session, redirect
app = Flask(__name__)
app.secret_key = 'dfdfdf'
@app.route('/')
def index():
if 'color' in session:
color = session['color']
else:
color = "#FFF"
return render_template('index.html', color=color)
@app.route('/red')
def red():
session['color'] = '#F00'
return redirect('/')
@app.route('/blue')
def blue():
session['color'] = '#00F'
return redirect('/')
@app.route('/green')
def green():
session['color'] = '#0F0'
return redirect('/')
@app.route('/default')
def green():
del session['color']
return redirect('/')
app.run(debug=True)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body style="background-color: {{color}};">
<h1>Цветосайт!</h1>
<a href="/red">Хочу красный</a><br>
<a href="/blue">Хочу синий</a><br>
<a href="/green">Хочу зеленый</a><br>
<a href="/default">Хочу как обычно</a><br>
</body>
</html>
Авторизация
Для авторизации пользователей в фласке (да и любых сервисах в интернете) используются сессии. Идея в том, что после успешной авторизации (ввода правильного логина и пароля) пользователь получает временный токен, который храниться в cookie файле (в браузере клиента), а на стороне сервера к этому токену привязывается произвольная информация (например, имя пользователя).
Пример использования сессий можно увидеть в коде ниже. В нем при заходе пользователя на страницу входа, мы добавляем в сессию ключ auth
, и, если он есть, на главной странице показывается "секретный" текст.
from flask import Flask, session, redirect
# just serve all the static files under root
app = Flask(__name__)
app.secret_key = 'jrfasefasefgj'
@app.route('/')
def index():
if session.get('auth', False) == True:
return "<p>Это секретный раздел!</p><p><a href='/logout'>Выйти!</a></p>"
else:
return "<p>Вам сюда нельзя!</p><p><a href='/login'>Но можно войти...</a></p>"
@app.route('/login')
def login():
session['auth'] = True
return redirect('/')
@app.route('/logout')
def logout():
session.clear()
return redirect('/')
(debug=True, port='3000', host='0.0.0.0')