Сервис предоставляет два способа удостоверения пользователя
JWT
Используются два токена: verify & refresh
- Первый для удостоверения в запросах, второй для обновления данной пары токенов.
- Первый живет 30 мин, второй год.
- Первый многоразовый, второй одноразовый.
- Первый храним в LocalStorage или SessionStorage, второй только в памяти.
- Токены кодированы в Base64, https://jwt.io/, здесь можно увидеть наглядно что токен содержит. Вообще в сети есть и другие сервисы для декодирования. Состав токена мы можем менять.
Порядок запросов
- Логин по ссылке: /api/jwt/token/, пример запроса: клиент - https://httpie.io/
http post 77.223.101.127:9000/api/jwt/token/ username=root password=Http200 - Из полученной пары первый сеттим в заголовок 'HTTP_AUTHORIZATION': 'Bearer <token_verify>' для тех
запросов что требуют авторизации, пример:
http get 77.223.101.127:9000/api/user/list 'AUTHORIZATION:Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjIzOTQ2NTc4LCJqdGkiOiIzYWZjYzAzZDQ5YWU0OGYwODNlZWM3MjJiYWJmZjkwNCIsInVzZXJfaWQiOjIsIm5hbWUiOiJyb290IiwiZ3JvdXBzIjpbXX0.FrGn6hSwztUygKkttYYvVvFajCT62FzWU9WPgZTmDgk' - Перед каждым запросом смотрим на дату годности первого токена, если она истекла, то рефрешим всю пару по
ссылке:
/api/jwt/token/refresh/, пример:
http post 77.223.101.127:9000/api/jwt/token/refresh/ refresh=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTYyMzMxNDk2NCwianRpIjoiMjA2OTcyNTFjYzg2NDVlMDhjNmExYWMxNGE1MWMzMTEiLCJ1c2VyX2lkIjoyfQ.rYg_yw-prwyHBRI1UcGMqPo6SSH3lW54O_s0dbSrbxI - Иногда нужно просто верифицировать имеющийся токен, /api/jwt/token/verify/,
пример:
http post 77.223.101.127:9000/api/jwt/token/verify/ token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjIzMjk2NjA5LCJqdGkiOiI3ZDUyNWVmNzM2OWM0ZWUwOWExMjcwZTI4N2FhMWRhMCIsInVzZXJfaWQiOjJ9.f-oQJvmWS54t6Ep7K9bJxREu-FrwxfJa-xAZqIjuCjU
Basic auth
- Имеем один токен типа куки, кладем его в соответствующий заголовок.
- всё)
Порядок запросов
- Логин по ссылке: /api/rest-auth/login/, пример запроса:
http post 77.223.101.127:9000/api/rest-auth/login/ username=root password=Http200 - В ответе получим токен, который сеттим в заголовок 'HTTP_AUTHORIZATION': 'token <token>' для тех
запросов что требуют авторизации, например:
http post 77.223.101.127:9000/api/user/ 'Authorization:token 1f890d847a08df26952cdaa681a98465345a8c45'
Сравнение
- + ЖВТ не хранится в БД
- + Позволяет реализовать настоящий RESTfull API
- + Безопаснее
- + Сам по себе носитель инфы
- + Быстрее и, чем больше будет юзеров, тем разница будет заметнее.
- - Сложнее в использовании
API Endpoints
| Тип | Адрес | Параметры | Ответ, пример | Описание | Разрешения |
|---|---|---|---|---|---|
| POST | /api/rest-auth/registration/ | {'username': 'tst', 'email': 'test@test.loc', 'password1': '123root', 'password2': '123root'} | HTTP 201 | Регистрация юзера | any |
| POST | /api/dj-rest-auth/password/change/ | {'new_password1': 'Http900','new_password2': 'Http900'} | HTTP 200 {'detail': 'Новый пароль сохранён.'} | Изменение пароля | owner only |
| POST | /api/password/reset/confirm/ | {'email': 'test@list.ru'} | HTTP 200 | Запрос ссылки на восстановление доступа (сброс пароля) | any |
| POST | /api/password/reset/confirm/ | {'token':token, 'password':'Http500'} | HTTP 200 | Восстановление доступа (сброс пароля) | any |
| GET | /api/group/list/ | [{'id': 1, 'name': 'test_name'}] | Список групп | staff only | |
| POST | /api/group/create/ | {'name': 'test'} | HTTP 201 | Создание группы | staff only |
| PATCH | /api/group/1/update/ | {'name': 'test_name'} | HTTP 200 | Редактирование группы | staff only |
| GET | /api/group/users/test/?is_superuser=true&is_staff=true | {'name': 'test'} | HTTP 200 [{'username': 'root', 'email': 'user@loc.loc', 'groups': [1], 'id': 1}, {'username': 'test2', 'email': 'test2@loc.loc', 'groups': [1, 2], 'id': 2}] |
Получение списка пользователей, где test - имя группы, опциональный параметр, остальные
параметры могут принимать значения: 'date_joined', 'email', 'first_name', 'groups', 'id',
'is_active', 'is_staff', 'is_superuser', 'last_login', 'last_name', 'profile', 'user_permissions',
'username'. Если имя группы пропущено, то поиск пройдет по всем пользователям. Если в параметрах есть фильтр которого нет в модели пользователя, вернется 400 код. |
staff only |
| GET | /api/group/ | {'testGroup': {'id': 1, 'users': [{'user_id': 1, 'username': 'user', 'phone': 8885552277},
{'user_id': 2, 'username': 'test2'}, {'user_id': 3, 'username': 'test3'}]}, 'testGroup2': {'id':
2, 'users': [{'user_id': 2, 'username': 'test2'}]}}
состав полей может меняться
|
Список пользователей в разрезе групп | staff only | |
| GET | /api/user/filter/ | id, username, first_name, last_name, role, group, is_superuser, is_staff, is_active,
page, page_size, any
В поле group указываем имя группы. Поиск по этим значениям производится по вхождению в значение поля, те если есть пользователи тест1 и тест2, а в параметре username указано тест, то вернутся оба. Поиск с точным совпадением: id, role, is_superuser, is_staff, is_active. Поиск с совпадением по части: username, group, phone, last_name, first_name. Поля page, page_size - числа, первое номер запрашиваемой страницы, второе кол-во итемов на ней. Если они не указаны, то будут использованы значения по умолчанию 1 и 25 соответственно. Если запрос отправлен с полем any, то будет произведен поиск с частичным совпадением сразу по трем полям: last_name, phone, email. Все поля опциональны. Текстовые поля валидируются по длине, разрешается от 3 до 30 символов. |
HTTP 200
{'count': 18, 'next': 'http://testserver/api/user/filter/?page=3&page_size=2', 'previous': 'http://testserver/api/user/filter/?page_size=2', 'results': [{'username': 'test3', 'email': 'test3@loc.loc', 'groups': [{'id': 1, 'name': 'testGroup'}], 'id': 3, 'first_name': '', 'last_name': '', 'is_superuser': False, 'is_staff': False, 'is_active': True, 'profile': {'phone': '', 'role': 'client', 'delivery': ''}}, {'username': 'test5', 'email': 'test5@loc.loc', 'groups': [], 'id': 4, 'first_name': '', 'last_name': '', 'is_superuser': False, 'is_staff': False, 'is_active': True, 'profile': {'phone': '', 'role': 'client', 'delivery': ''}}]} Поле count содержит общее кол-во итемов в выборке. Поле previos содержит ссылку для предыдущей страницы, соотвественно поле next для следующей. Поле results содержит собственно данные. |
Получение списка пользователей. Если в параметрах есть фильтр которого нет в модели пользователя, вернется 400 код со списком допустимых полей. | staff only |
| GET | /api/user/list/ | [{'username': 'user', 'id': 1, 'groups': [{'id': 1, 'name': 'testGroup'}], 'phone': 8885552277},
{'username': 'test2', 'id': 2, 'groups': [{'id': 1, 'name': 'testGroup'}, {'id': 2, 'name':
'testGroup2'}]}, {'username': 'test3', 'id': 3, 'groups': [{'id': 1, 'name': 'testGroup'}]}]
состав полей может меняться
|
Список пользователей включая группы | authorized only | |
| POST | /api/user/list/ | filter=[1,2], если filter не указан или пустой, то вернет всех юзеров | [{'username': 'user', 'id': 1, 'groups': [{'id': 1, 'name': 'testGroup'}], 'phone': 8885552277},
{'username': 'test2', 'id': 2, 'groups': [{'id': 1, 'name': 'testGroup'}, {'id': 2, 'name':
'testGroup2'}]}, {'username': 'test3', 'id': 3, 'groups': [{'id': 1, 'name': 'testGroup'}]}]
состав полей может меняться
|
Список пользователей включая группы | authorized only |
| GET | /api/user/ | Все поля за исключением пароля | Текущий юзер | any, authorized only | |
| PATCH | /api/user/1/update/ | {'username': 'test_rename_user','first_name': 'Остап',# 'last_name': 'Бендер',
'password': 'Http700' # пароль будет просто проигнорирован
'profile': {'phone': 8885552277},}
допустимы все поля за исключением пароля
|
Все поля за исключением пароля, допустимо частичное обновления, те ни одно поле не обязательно | Изменение юзера | staff only |
| PATCH | /api/user/1/update/ | {"is_active": false} | HTTP 200. Пример бана юзера, осторожнее можно забанить самого себя и утратить доступ к админке | Бан юзера | staff only |
| GET | /api/user/1/ | Все поля за исключением пароля | Получение юзера | staff only | |
| PATCH | /api/user/1/group-update/ | {"groups":[1,2]} | HTTP-200 Все поля пользователя за исключением пароля или HTTP-400, если такой группы не существует. | Обновление состава групп юзера | staff only |
| DELETE | /api/group/1/ | HTTP 204 || 404 если группы не существует | Удаление группы | staff only | |
| DELETE | /api/user/1/delete/ | HTTP 204 || 404 если юзера не существует | Удаление юзера | staff only | |
| PATCH | /api/user/update/ | HTTP 200 | Обновление юзера | authorized only | |
| POST | /api/jwt/token/ |
payload = { username: process.env.telegram_username, password: process.env.telegram_password, days: 0, // дни истечения срок валидности токена hours: 3, // тоже, но часы minutes: 0, // тоже, минуты // полезная нагрузка токена, всё что сюда записано будет в поле payload.load load: { company_id: 333, registry_id: 555 } } техпроцесс 1. запрашиваем токен, из ответа берем только ACCESS токен, refresh отбрасываем, здесь он не нужен. 2. генерим ссылку для бота 3. отправляем, ждем) 4. сверяем данные в токене, тк они подписаны и подменить их не получиться, с данными в параметрах ссылки 5. если всё верно продолжаем обработку запроса |
HTTP 200 1. запрос токена: http post auth.macrobank.pro/api/jwt/token/ username=telegram_bot password='ххххххххх' load={"company_id":"tstID"} 2. верификация: http post auth.macrobank.pro/api/jwt/token/verify/ token=access_token |
Запрос JWT с определением срока действия и дополнительной нагрузкой, например компании для которой выдан токен. | authorized only |
- staff - любой юзер с правом входа в админ часть, сейчас это только админы, но можно предоставить право входа любому, что, однако, не даст ему админских прав.
- вместо имени для входа можно юзать емейл.
Политика безопасности в отношении пароля
- Пароль не должен быть слишком похож на другие атрибуты.
- Минимальная длина - 6 символов
- Пароль не может состоять только из цифр.
- Слишком простой и часто используемый пароль. Джанго сверяет пароль со своей БД в которой около 20000 простых паролей.