Доброго времени суток codeby !
План :
Запланировал разобрать аутентификацию и авторизацию веб-приложений на примере Flask. Это первая часть из моей серии, т.к информации достаточно много и я стараюсь правильно ее распределить. Я сам если честно не люблю тонны скучных определений, поэтому постараюсь донести свои мысли более-менее интересно (не факт) Но все же теория - основа доказательства (только что придумал) и блин, я не понимаю откуда мое непреодолимое желание ставить скобки )) (ам сори)
Итак, если кратко, то в этой части хочу разобрать что вообще такое Фласк (если кто не знаком), для чего используются печеньки и сессии в веб-приложениях, запустить свое приложение для тестов и примеров.
Ну ок че ? Погнали)
О Flask :
Flask — микро-фреймворк для создания
Вот так просто вы можете поднять свой веб-сервер на localhost:5000. Если вы хотите поднять сервер на конкретном адресе, изменить порт или использовать отладку ( желательно ), вам следует переопределить метод запуска как :
Маршруты :
Маршруты URL создаются с помощью декоратора @app.route. Функция render_template возвращает html шаблон. Все шаблоны html должны находится в каталоге templates внутри приложения. В каталоге static находятся подкаталоги css img js
Я не использовал всю мощь шаблонов jinja2 в полной мере, а просто нарисовал html примерно вот так :
Таким образом структура приложения внутри папки project :
Авторизация :
Авторизация - это механизм предоставляющий пользователю (после аутентификации) доступ к тем или иным ресурсам. В своем приложении я буду использовать расширения Flask-Login для авторизации пользователя. Авторизация происходит с помощью функции login_user() но Flask-Login ожидает от нас модель пользователя, которую нам необходимо создать, и чтобы не прописывать методы вручную можно наследоваться от UserMixin в db_models.py
login_user(user) вызывается в после проверки логина и пароля в форме, создает объект пользователя и заносит данные о нем в сессию.
С помощью декоратора @login_manager.user_loader при каждом запросе клиента будет загружаться информация о пользователе.
Декоратора @login_required ограничивает доступ к маршруту не авторизованных пользователей.
Главная страница возвращает заглушку.
Cookie и сессии :
Файлы куки - это небольшие фрагменты данных, которые хранятся на вашем компьютере веб-браузером, и их первоначальная цель - запоминать информацию о состоянии при просмотре различных веб-сайтов (страниц).
Сессии также используются для хранения данных пользователя, но в отличие от печенек (которые полностью хранятся на стороне клиента) при сессиях в куках может хранится только идентификатор сессии. Другими словами сессии - это частный случай cookies, сервер кодирует данные и передает получившееся значение клиенту, клиент при следующих запросах передает эти данные обратно в заголовке Set-Cookies : после чего сервер проводит их декодирование и валидацию. При конфигурации приложения во Flask указывается секретный ключ, по которому приложение проверяет криптографически, были ли изменены данные сессии. Это так называемые - клиентские сессии. Фласк использует по умолчанию именно их.
Существуют серверные сессии, которые хранятся на стороне сервера, а в запросе клиента передается идентификатор, по которому сессия может быть валидирована и получена из БД.
Я добавил серверные сессии с помощью flask_sessionstore.
СУБД :
Чтобы работать с БД существует модуль flask_sqlalchemy. В данный момент я использую MySQL. Конфигурация приложения flask_sessionstore и flask_sqlalchemy находится в __init__.py :
В __init__ импортируются все модули из пакета а start.py находится каталогом выше в Project и содержит from project_x import app
Таким образом происходит запуск приложения.
Серверные сессии :
При создании приложения создаются модели БД.
При первом запросе происходит редирект на /auth и устанавливаются куки сессии :
Отправляем данные из формы для авторизации (предварительно конечно есть форма регистрации) и получаем токен :
В клиентской куки передается только ай ди сессии. Для токена устанавливается значение fresh=True, если данные в куки или БД побьются, свежесть=false.
Чекнем :
Извиняюсь за поехавшие таблицы.
Мы также можем обратиться к объекту сессии, чтобы провести проверку дополнительно. Если убить сессию из БД Flask все равно считает пользователя авторизованным (не знаю почему, видимо я что то упустил) поэтому проверю свежий ли токен :
Я использовал простой метод авторизации и во Flask есть возможность это улучшить используя WTForms. В частности достаточно просто реализуется защита от CSRF атак.
Далее планирую реализовать формы и JSON WEB TOKEN (без запросов к БД) авторизацию, рассмотреть другие протоколы.
Спасибо за внимание !
План :
Запланировал разобрать аутентификацию и авторизацию веб-приложений на примере Flask. Это первая часть из моей серии, т.к информации достаточно много и я стараюсь правильно ее распределить. Я сам если честно не люблю тонны скучных определений, поэтому постараюсь донести свои мысли более-менее интересно (не факт) Но все же теория - основа доказательства (только что придумал) и блин, я не понимаю откуда мое непреодолимое желание ставить скобки )) (ам сори)
Итак, если кратко, то в этой части хочу разобрать что вообще такое Фласк (если кто не знаком), для чего используются печеньки и сессии в веб-приложениях, запустить свое приложение для тестов и примеров.
Ну ок че ? Погнали)
О Flask :
Flask — микро-фреймворк для создания
Ссылка скрыта от гостей
(Web Server Gateway Interface) приложений на языке Python. Точнее сказать можно, но думаю не нужно. Собственно, что означает микро и основная документация расположена
Ссылка скрыта от гостей
, пока же мы запустим минимальное приложение для старта :
Код:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Index Page'
if __name__ == '__main__':
app.run()
Вот так просто вы можете поднять свой веб-сервер на localhost:5000. Если вы хотите поднять сервер на конкретном адресе, изменить порт или использовать отладку ( желательно ), вам следует переопределить метод запуска как :
Python:
app.run(host='ip', port='port', debug=True)
Маршруты :
Python:
@app.route("/", methods=["GET", "POST"])
def main():
return render_template('index.html')
Маршруты URL создаются с помощью декоратора @app.route. Функция render_template возвращает html шаблон. Все шаблоны html должны находится в каталоге templates внутри приложения. В каталоге static находятся подкаталоги css img js
Я не использовал всю мощь шаблонов jinja2 в полной мере, а просто нарисовал html примерно вот так :
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>project_xxs</title>
</head>
<body>
<div class="container">
<div class="alert alert-danger col-md-3" role="alert">
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
</div>
<form class ="col-md-3 col-sm-6" action="/auth" method="POST">
<img src="{{ url_for('static', filename='img/auth.png') }}" class="img">
<div class="form-group">
<label for="exampleInputEmail1" class="mt-1">username</label>
<input name="username" type="text" class="form-control mt-2" id="exampleInputEmail1">
</div>
<div class="form-group">
<label for="exampleInputPassword1" class="mt-1">password</label>
<input name="password" type="password" class="form-control mt-2" id="exampleInputPassword1">
<button type="submit" class="btn btn-primary mt-3">auth</button>
</div>
</form>
</div>
</body>
</html>
Таким образом структура приложения внутри папки project :
Авторизация :
Авторизация - это механизм предоставляющий пользователю (после аутентификации) доступ к тем или иным ресурсам. В своем приложении я буду использовать расширения Flask-Login для авторизации пользователя. Авторизация происходит с помощью функции login_user() но Flask-Login ожидает от нас модель пользователя, которую нам необходимо создать, и чтобы не прописывать методы вручную можно наследоваться от UserMixin в db_models.py
Python:
# -*- coding: utf-8 -*-
from flask_login import UserMixin
from project_x import db
class Users(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(32), unique=True, nullable=False)
password = db.Column(db.String(128), nullable=False)
login_user(user) вызывается в после проверки логина и пароля в форме, создает объект пользователя и заносит данные о нем в сессию.
С помощью декоратора @login_manager.user_loader при каждом запросе клиента будет загружаться информация о пользователе.
Python:
@login_manager.user_loader
def load_user(user_id):
return Users.query.get(user_id)
Декоратора @login_required ограничивает доступ к маршруту не авторизованных пользователей.
Python:
@app.route("/", methods=["GET", "POST"])
@login_required
def main():
return render_template('index.html')
Главная страница возвращает заглушку.
Cookie и сессии :
Файлы куки - это небольшие фрагменты данных, которые хранятся на вашем компьютере веб-браузером, и их первоначальная цель - запоминать информацию о состоянии при просмотре различных веб-сайтов (страниц).
Сессии также используются для хранения данных пользователя, но в отличие от печенек (которые полностью хранятся на стороне клиента) при сессиях в куках может хранится только идентификатор сессии. Другими словами сессии - это частный случай cookies, сервер кодирует данные и передает получившееся значение клиенту, клиент при следующих запросах передает эти данные обратно в заголовке Set-Cookies : после чего сервер проводит их декодирование и валидацию. При конфигурации приложения во Flask указывается секретный ключ, по которому приложение проверяет криптографически, были ли изменены данные сессии. Это так называемые - клиентские сессии. Фласк использует по умолчанию именно их.
Существуют серверные сессии, которые хранятся на стороне сервера, а в запросе клиента передается идентификатор, по которому сессия может быть валидирована и получена из БД.
Я добавил серверные сессии с помощью flask_sessionstore.
СУБД :
Чтобы работать с БД существует модуль flask_sqlalchemy. В данный момент я использую MySQL. Конфигурация приложения flask_sessionstore и flask_sqlalchemy находится в __init__.py :
Python:
# -*- coding: utf8 -*-
import os
from flask_sqlalchemy import SQLAlchemy
from flask import Flask, session
from flask_sessionstore import Session
app = Flask(__name__)
app.config.from_object(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:1234@localhost/project_x?charset=utf8mb4'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SECRET_KEY'] = str(os.urandom(64).hex())
db = SQLAlchemy(app)
app.config['SESSION_TYPE'] = 'sqlalchemy'
app.config['SESSION_SQLALCHEMY'] = db
app.config['SESSION_SQLALCHEMY_TABLE'] = 'sessions'
Session(app)
from project_x import db_models, routes
#session.app.session_interface.db.create_all()
#db.create_all()
app.run()
В __init__ импортируются все модули из пакета а start.py находится каталогом выше в Project и содержит from project_x import app
Таким образом происходит запуск приложения.
Серверные сессии :
При создании приложения создаются модели БД.
При первом запросе происходит редирект на /auth и устанавливаются куки сессии :
Отправляем данные из формы для авторизации (предварительно конечно есть форма регистрации) и получаем токен :
В клиентской куки передается только ай ди сессии. Для токена устанавливается значение fresh=True, если данные в куки или БД побьются, свежесть=false.
Чекнем :
Извиняюсь за поехавшие таблицы.
Мы также можем обратиться к объекту сессии, чтобы провести проверку дополнительно. Если убить сессию из БД Flask все равно считает пользователя авторизованным (не знаю почему, видимо я что то упустил) поэтому проверю свежий ли токен :
Python:
if session['_fresh'] == False:
return redirect(url_for('auth_user'))
Я использовал простой метод авторизации и во Flask есть возможность это улучшить используя WTForms. В частности достаточно просто реализуется защита от CSRF атак.
Далее планирую реализовать формы и JSON WEB TOKEN (без запросов к БД) авторизацию, рассмотреть другие протоколы.
Спасибо за внимание !
Последнее редактирование: