add files
parent
f0382cc7ee
commit
4de1d3d9ff
212
README.md
212
README.md
|
@ -1,2 +1,214 @@
|
|||
# Harmony
|
||||
|
||||
Давайте добавим раздел о запуске вашего проекта Django в README файл, чтобы новые пользователи и разработчики могли легко начать работу.
|
||||
|
||||
---
|
||||
|
||||
## Запуск проекта Django
|
||||
|
||||
Чтобы запустить проект Django локально, следуйте этим шагам:
|
||||
|
||||
### Шаг 1: Клонирование репозитория
|
||||
|
||||
|
||||
|
||||
```bash
|
||||
git clone https://git.myterior.kz/Lowlight_Akbota/Harmony
|
||||
cd djangoproject1
|
||||
```
|
||||
|
||||
|
||||
### Шаг 2: Установка зависимостей
|
||||
|
||||
Убедитесь, что у вас установлен Python и pip. Затем установите зависимости проекта:
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
Это установит все необходимые библиотеки Python, указанные в файле `requirements.txt`.
|
||||
|
||||
### Шаг 3: Настройка базы данных
|
||||
|
||||
Проекты Django часто используют базу данных для хранения данных. Выполните миграции, чтобы настроить вашу базу данных:
|
||||
|
||||
```bash
|
||||
python manage.py migrate
|
||||
```
|
||||
|
||||
### Шаг 4: Создание суперпользователя (необязательно)
|
||||
|
||||
Чтобы получить доступ к административной панели Django, создайте суперпользователя:
|
||||
|
||||
```bash
|
||||
python manage.py createsuperuser
|
||||
```
|
||||
|
||||
Следуйте инструкциям на экране, чтобы завершить создание.
|
||||
|
||||
### Шаг 5: Запуск сервера разработки
|
||||
|
||||
Запустите локальный сервер разработки Django:
|
||||
|
||||
```bash
|
||||
python manage.py runserver
|
||||
```
|
||||
|
||||
После запуска сервера, ваше приложение будет доступно по адресу [http://localhost:8000](http://localhost:8000) в вашем веб-браузере.
|
||||
|
||||
### Шаг 6: Переход к аутентификации через Keycloak
|
||||
|
||||
Чтобы начать процесс аутентификации через Keycloak, перейдите по URL, который вы настроили для входа через Keycloak (например, `/login`), который инициирует перенаправление на страницу входа Keycloak.
|
||||
|
||||
---
|
||||
|
||||
Добавив этот раздел в ваш README файл, вы предоставите четкие инструкции по запуску и базовой настройке вашего Django проекта. Это облегчит новым пользователям и разработчикам начало работы с вашим проектом и поможет им быстрее ориентироваться в его структуре и функциональности.
|
||||
|
||||
|
||||
|
||||
Давайте интегрируем Keycloak с Django и добавим соответствующий раздел в README, чтобы описать процесс интеграции и использования. Это будет дополнительный раздел в вашем README файле, посвященный настройке аутентификации через Keycloak.
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## Интеграция Keycloak с Django
|
||||
|
||||
Keycloak предоставляет систему управления идентификацией и доступом, которую можно интегрировать с вашим приложением Django для аутентификации пользователей. Ниже приведены шаги для настройки и интеграции Keycloak с Django.
|
||||
|
||||
### Шаг 1: Настройка Keycloak
|
||||
|
||||
1. **Создание Realm**: Войдите в административную панель Keycloak и создайте новый realm.
|
||||
|
||||
2. **Создание Client**: Внутри созданного realm создайте новый client. Задайте `Client ID` и укажите `Valid Redirect URIs` (например, `http://localhost:8000/*` для разработки). Также, выберите `confidential` в качестве типа доступа и сохраните секретный ключ клиента.
|
||||
|
||||
3. **Пользователи**: Создайте пользователей в Keycloak, которые будут использоваться для входа в ваше Django приложение.
|
||||
|
||||
### Шаг 2: Настройка Django
|
||||
|
||||
Для интеграции Keycloak с Django, вам понадобится установить библиотеку, которая упростит взаимодействие с Keycloak, например, `python-keycloak` или аналогичную.
|
||||
|
||||
#### Установка зависимостей
|
||||
|
||||
```bash
|
||||
pip install python-keycloak
|
||||
```
|
||||
|
||||
#### Конфигурация
|
||||
|
||||
Добавьте настройки Keycloak в `settings.py` вашего проекта Django:
|
||||
|
||||
```python
|
||||
KEYCLOAK_CONFIG = {
|
||||
'SERVER_URL': 'http://keycloak-server/auth/',
|
||||
'REALM': 'your-realm',
|
||||
'CLIENT_ID': 'your-client-id',
|
||||
'CLIENT_SECRET': 'your-client-secret',
|
||||
'CALLBACK_URL': 'http://localhost:8000/callback/',
|
||||
}
|
||||
```
|
||||
|
||||
### Шаг 3: Реализация Аутентификации
|
||||
|
||||
Используйте предоставленные ранее функции для реализации процесса аутентификации:
|
||||
|
||||
- `keycloak_login` для инициации процесса входа через Keycloak.
|
||||
- `keycloak_redirect` для обработки перенаправления от Keycloak после аутентификации пользователя.
|
||||
|
||||
### Шаг 4: Маршрутизация
|
||||
|
||||
Добавьте URL-маршруты в `urls.py` для обработки входа через Keycloak и обратного перенаправления:
|
||||
|
||||
```python
|
||||
from django.urls import path
|
||||
from .views import keycloak_login, keycloak_redirect
|
||||
|
||||
urlpatterns = [
|
||||
path('login/', keycloak_login, name='keycloak_login'),
|
||||
path('callback/', keycloak_redirect, name='keycloak_redirect'),
|
||||
]
|
||||
```
|
||||
|
||||
### Шаг 5: Запуск
|
||||
|
||||
Запустите ваше приложение Django и используйте `/login` для начала процесса аутентификации через Keycloak.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Понял, давайте включим в README детали о функциях, которые вы мне предоставили, описывая их использование в контексте интеграции Keycloak с Django. Это поможет создать полное руководство по интеграции.
|
||||
|
||||
---
|
||||
|
||||
## Использование Keycloak для аутентификации в Django
|
||||
|
||||
После настройки Keycloak и Django, вам нужно будет использовать следующие функции для обработки аутентификации:
|
||||
|
||||
### Функция `keycloak_login`
|
||||
|
||||
Эта функция инициирует процесс аутентификации пользователя, перенаправляя его на страницу входа в Keycloak.
|
||||
|
||||
```python
|
||||
def keycloak_login(request):
|
||||
# Создаем экземпляр Keycloak OpenID клиента с вашими настройками
|
||||
keycloak_openid = KeycloakOpenID(
|
||||
server_url=settings.KEYCLOAK_CONFIG['SERVER_URL'],
|
||||
client_id=settings.KEYCLOAK_CONFIG['CLIENT_ID'],
|
||||
realm_name=settings.KEYCLOAK_CONFIG['REALM'],
|
||||
client_secret_key=settings.KEYCLOAK_CONFIG['CLIENT_SECRET']
|
||||
)
|
||||
|
||||
# Получаем URL для аутентификации от Keycloak и перенаправляем пользователя
|
||||
redirect_uri = settings.KEYCLOAK_CONFIG['CALLBACK_URL']
|
||||
auth_url = keycloak_openid.auth_url(redirect_uri=redirect_uri)
|
||||
return redirect(auth_url)
|
||||
```
|
||||
|
||||
### Функция `keycloak_redirect`
|
||||
|
||||
Эта функция обрабатывает перенаправление от Keycloak после аутентификации пользователя, извлекая код авторизации и обменивая его на токен доступа.
|
||||
|
||||
```python
|
||||
@require_http_methods(["GET"])
|
||||
def keycloak_redirect(request):
|
||||
# Извлекаем код авторизации из запроса
|
||||
authorization_code = request.GET.get('code')
|
||||
if authorization_code:
|
||||
# Здесь вы можете обменять код на токен и произвести дальнейшие действия
|
||||
return HttpResponse("Authorization code received.")
|
||||
else:
|
||||
return HttpResponse("Authorization code not found.", status=400)
|
||||
```
|
||||
|
||||
### Взаимодействие с Keycloak
|
||||
|
||||
Для управления сессиями и пользователями, вы можете использовать функции `get_keycloak_admin_token`, `get_user_sessions`, и `logout_user`. Эти функции позволяют вам программно управлять сессиями пользователя в Keycloak, включая их выход из системы.
|
||||
|
||||
#### Получение административного токена
|
||||
|
||||
```python
|
||||
def get_keycloak_admin_token():
|
||||
# Код для получения административного токена Keycloak
|
||||
```
|
||||
|
||||
#### Получение сессий пользователя
|
||||
|
||||
```python
|
||||
def get_user_sessions(admin_token, user_id):
|
||||
# Код для получения списка сессий пользователя
|
||||
```
|
||||
|
||||
#### Выход пользователя
|
||||
|
||||
```python
|
||||
def logout_user(admin_token, session_id):
|
||||
# Код для завершения сессии пользователя
|
||||
```
|
||||
|
||||
### Интеграция с вашим Django приложением
|
||||
|
||||
Используйте эти функции в вашем Django приложении для управления процессом аутентификации и сессиями пользователя. Вы можете настроить перенаправления, обработку ошибок и уведомления для пользователя в соответствии с вашими требованиями безопасности и пользовательским опытом.
|
||||
|
||||
---
|
||||
|
||||
Это руководство по интеграции Keycloak с Django поможет обеспечить безопасную и удобную систему аутентификации в вашем веб-приложении. Включение этих функций и их описаний в ваш README файл улучшит документацию проекта и поможет другим разработчикам понять, как использовать эти возможности в своих проектах.
|
BIN
db.sqlite3
BIN
db.sqlite3
Binary file not shown.
Binary file not shown.
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"realm": "Harmony",
|
||||
"auth-server-url": "https://auth.myterior.kz",
|
||||
"ssl-required": "external",
|
||||
"resource": "admin-cli",
|
||||
"credentials": {
|
||||
"secret": "wOVphEiLVBS1AlNKRpaQpD4yQh5Wm3TJ"
|
||||
},
|
||||
"confidential-port": 0
|
||||
}
|
||||
|
||||
|
|
@ -35,8 +35,7 @@ INSTALLED_APPS = [
|
|||
'django.contrib.sites',
|
||||
'allauth',
|
||||
'allauth.account',
|
||||
'allauth.socialaccount',
|
||||
'allauth.socialaccount.providers.openid_connect',
|
||||
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django_extensions',
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
%PDF-1.3
|
||||
%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com
|
||||
1 0 obj
|
||||
<<
|
||||
/F1 2 0 R
|
||||
>>
|
||||
endobj
|
||||
2 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
3 0 obj
|
||||
<<
|
||||
/Contents 7 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 6 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
4 0 obj
|
||||
<<
|
||||
/PageMode /UseNone /Pages 6 0 R /Type /Catalog
|
||||
>>
|
||||
endobj
|
||||
5 0 obj
|
||||
<<
|
||||
/Author (anonymous) /CreationDate (D:20240218230455-06'00') /Creator (ReportLab PDF Library - www.reportlab.com) /Keywords () /ModDate (D:20240218230455-06'00') /Producer (ReportLab PDF Library - www.reportlab.com)
|
||||
/Subject (unspecified) /Title (untitled) /Trapped /False
|
||||
>>
|
||||
endobj
|
||||
6 0 obj
|
||||
<<
|
||||
/Count 1 /Kids [ 3 0 R ] /Type /Pages
|
||||
>>
|
||||
endobj
|
||||
7 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 102
|
||||
>>
|
||||
stream
|
||||
GapQh0E=F,0U\H3T\pNYT^QKk?tc>IP,;W#U1^23ihPEM_?CW4KISi90MntRifICK%KE/ee05&l(FoZ!9neZ[Kb,ht@Ke@a%(R!A~>endstream
|
||||
endobj
|
||||
xref
|
||||
0 8
|
||||
0000000000 65535 f
|
||||
0000000073 00000 n
|
||||
0000000104 00000 n
|
||||
0000000211 00000 n
|
||||
0000000414 00000 n
|
||||
0000000482 00000 n
|
||||
0000000778 00000 n
|
||||
0000000837 00000 n
|
||||
trailer
|
||||
<<
|
||||
/ID
|
||||
[<58e49d6780c80c154396c8a9030fddee><58e49d6780c80c154396c8a9030fddee>]
|
||||
% ReportLab generated PDF document -- digest (http://www.reportlab.com)
|
||||
|
||||
/Info 5 0 R
|
||||
/Root 4 0 R
|
||||
/Size 8
|
||||
>>
|
||||
startxref
|
||||
1029
|
||||
%%EOF
|
Binary file not shown.
Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 1.9 MiB |
Binary file not shown.
Binary file not shown.
10
main/urls.py
10
main/urls.py
|
@ -11,10 +11,6 @@ urlpatterns = [
|
|||
path('about/', views.about, name='about'),
|
||||
path('', views.callback, name='product_list'),
|
||||
path('products/', views.callback, name='product_list'),
|
||||
path('<slug:category_slug>/', views.callback,
|
||||
name='product_list_by_category'),
|
||||
path('<int:id>/<slug:slug>/', views.product_detail,
|
||||
name='product_detail'),
|
||||
path('about/', views.about, name='about'),
|
||||
|
||||
]
|
||||
path('<slug:category_slug>/', views.callback,name='product_list_by_category'),
|
||||
path('<int:id>/<slug:slug>/', views.product_detail,name='product_detail'),
|
||||
path('about/', views.about, name='about'),]
|
||||
|
|
122
main/views.py
122
main/views.py
|
@ -1,14 +1,13 @@
|
|||
import requests
|
||||
from django.shortcuts import render,get_object_or_404
|
||||
from django.http import HttpResponse, HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404
|
||||
import logging
|
||||
from djangoProject1 import settings
|
||||
from .models import Category, Product
|
||||
from cart.forms import CartAddProductForm
|
||||
from jose import jwt
|
||||
from django.contrib import messages
|
||||
|
||||
|
||||
import jwt
|
||||
from django.http import JsonResponse
|
||||
|
||||
|
||||
|
||||
|
@ -30,6 +29,8 @@ def product_detail(request, id, slug):
|
|||
def about(request):
|
||||
return render(request, 'main/about.html')
|
||||
|
||||
|
||||
#Получение access token пользователя
|
||||
def exchange_code_for_token(authorization_code, redirect_uri):
|
||||
token_endpoint = 'https://auth.myterior.kz/realms/Harmony/protocol/openid-connect/token'
|
||||
client_id = 'admin-cli'
|
||||
|
@ -53,6 +54,8 @@ def exchange_code_for_token(authorization_code, redirect_uri):
|
|||
print("Failed to exchange code: HTTP status", response.status_code)
|
||||
print("Response body:", response.text)
|
||||
raise Exception('Failed to exchange authorization code for tokens')
|
||||
|
||||
#Через access_token получать данные о пользователе декодировав его в json
|
||||
def get_user_info(access_token):
|
||||
userinfo_endpoint = 'https://auth.myterior.kz/realms/Harmony/protocol/openid-connect/userinfo'
|
||||
headers = {'Authorization': f'Bearer {access_token}'}
|
||||
|
@ -62,7 +65,7 @@ def get_user_info(access_token):
|
|||
else:
|
||||
print("Failed to fetch user info: HTTP status", response.status_code)
|
||||
return None
|
||||
import jwt
|
||||
|
||||
|
||||
def decode_access_token(access_token):
|
||||
|
||||
|
@ -70,98 +73,130 @@ def decode_access_token(access_token):
|
|||
return payload
|
||||
|
||||
|
||||
def callback(request,category_slug=None):
|
||||
#Получение кода авторизации из запроса
|
||||
def callback(request, category_slug=None):
|
||||
context = {}
|
||||
# Получение кода авторизации из запроса.
|
||||
# где клиент получает код после аутентификации пользователя на сервере.
|
||||
authorization_code = request.GET.get('code')
|
||||
if authorization_code:
|
||||
try:
|
||||
# Обмен кода на access_token с помощью функции exchange_code_for_token.
|
||||
# Этот токен необходим для доступа к защищенным ресурсам (например, к информации о пользователе)
|
||||
# на сервере аутентификации.
|
||||
access_token = exchange_code_for_token(authorization_code, settings.KEYCLOAK_CONFIG['CALLBACK_URL'])
|
||||
# Декодирование access_token для получения информации о пользователе.
|
||||
# Это может включать имя пользователя, email и другие данные, в зависимости от настроек сервера.
|
||||
user_info = decode_access_token(access_token)
|
||||
# Сохранение полученной информации о пользователе в сессии.
|
||||
# Это позволяет использовать данные пользователя в дальнейшем, не обращаясь к серверу аутентификации.
|
||||
request.session['user_info'] = user_info
|
||||
|
||||
|
||||
# Добавление информации о пользователе в контекст для отображения на странице.
|
||||
context['userinfo'] = request.session.get('user_info', {})
|
||||
|
||||
except Exception as e:
|
||||
# В случае ошибки (например, проблемы с обменом кода или декодированием токена)
|
||||
# добавляем информацию об ошибке в контекст.
|
||||
context['error'] = str(e)
|
||||
else:
|
||||
# Если код авторизации не найден в запросе, сообщаем об этом через контекст.
|
||||
context['error'] = "Authorization code not found."
|
||||
|
||||
# Загрузка всех категорий и продуктов для отображения на странице.
|
||||
# Если указан category_slug, фильтруем продукты по данной категории.
|
||||
category = None
|
||||
categories = Category.objects.all()
|
||||
products = Product.objects.filter(available=True)
|
||||
if category_slug:
|
||||
category = get_object_or_404(Category,
|
||||
slug=category_slug)
|
||||
category = get_object_or_404(Category, slug=category_slug)
|
||||
products = products.filter(category=category)
|
||||
return render(request, 'main/product/list.html',{'category': category,
|
||||
'categories': categories,
|
||||
'products': products})
|
||||
|
||||
# Рендеринг страницы с продуктами, передавая информацию о категориях, продуктах и контекст с данными пользователя или ошибками.
|
||||
return render(request, 'main/product/list.html',
|
||||
{'category': category, 'categories': categories, 'products': products})
|
||||
|
||||
|
||||
from django.shortcuts import render, redirect
|
||||
|
||||
def profile(request):
|
||||
# Проверка метода запроса: если POST, значит пользователь отправил форму для обновления своих данных.
|
||||
if request.method == 'POST':
|
||||
|
||||
# Получение текущей информации о пользователе из сессии.
|
||||
user_info = request.session.get('user_info', {})
|
||||
|
||||
# Обновление информации о пользователе данными из формы.
|
||||
# Если какое-то поле не было предоставлено, используется текущее значение из сессии.
|
||||
user_info['given_name'] = request.POST.get('first_name', user_info.get('given_name', ''))
|
||||
user_info['family_name'] = request.POST.get('last_name', user_info.get('family_name', ''))
|
||||
user_info['preferred_username'] = request.POST.get('username', user_info.get('preferred_username', ''))
|
||||
user_info['email'] = request.POST.get('email', user_info.get('email', ''))
|
||||
|
||||
|
||||
# Сохранение обновленной информации о пользователе обратно в сессию.
|
||||
request.session['user_info'] = user_info
|
||||
|
||||
|
||||
# После обновления информации редиректим пользователя на страницу callback,
|
||||
# которая, скорее всего, отображает информацию о профиле или подтверждение об обновлении данных.
|
||||
return render(request, 'main/callback.html')
|
||||
else:
|
||||
|
||||
# Если метод запроса не POST, пользователь просто посещает страницу профиля,
|
||||
# мы загружаем текущую информацию о пользователе из сессии и передаем ее в контекст шаблона.
|
||||
context = {'userinfo': request.session.get('user_info', {})}
|
||||
|
||||
# Отображаем страницу профиля пользователя, передавая информацию о пользователе в контекст.
|
||||
return render(request, 'main/callback.html', context)
|
||||
|
||||
|
||||
|
||||
# Настройте логирование
|
||||
# логирование
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def get_keycloak_admin_token():
|
||||
# Формируем данные для запроса токена
|
||||
data = {
|
||||
'client_id': settings.KEYCLOAK_CONFIG['CLIENT_ID'],
|
||||
'client_secret': settings.KEYCLOAK_CONFIG['CLIENT_SECRET'],
|
||||
'grant_type': 'client_credentials',
|
||||
'client_id': settings.KEYCLOAK_CONFIG['CLIENT_ID'], # ID клиента
|
||||
'client_secret': settings.KEYCLOAK_CONFIG['CLIENT_SECRET'], # Секрет клиента
|
||||
'grant_type': 'client_credentials', # Тип авторизации
|
||||
}
|
||||
|
||||
# Отправка запроса для получения токена администратора Keycloak
|
||||
response = requests.post(
|
||||
f"{settings.KEYCLOAK_CONFIG['SERVER_URL']}/realms/{settings.KEYCLOAK_CONFIG['REALM']}/protocol/openid-connect/token",
|
||||
data=data
|
||||
)
|
||||
return response.json()['access_token']
|
||||
# Возвращаем токен доступа из ответа
|
||||
return response.json()['access_token']
|
||||
|
||||
|
||||
def get_user_sessions(admin_token, user_id):
|
||||
# Установка заголовков с токеном администратора для авторизации запроса
|
||||
headers = {'Authorization': f'Bearer {admin_token}'}
|
||||
# Запрос на получение списка сессий пользователя в Keycloak
|
||||
response = requests.get(
|
||||
f"{settings.KEYCLOAK_CONFIG['SERVER_URL']}/admin/realms/{settings.KEYCLOAK_CONFIG['REALM']}/users/{user_id}/sessions",
|
||||
headers=headers
|
||||
)
|
||||
# Проверка успешности запроса и возвращение результата
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
else:
|
||||
logger.error(f"Error fetching user sessions: {response.status_code}")
|
||||
return []
|
||||
|
||||
|
||||
def logout_user(admin_token,session_id):
|
||||
headers = {
|
||||
'Authorization': f'Bearer {admin_token}',
|
||||
}
|
||||
def logout_user(admin_token, session_id):
|
||||
# Установка заголовков с токеном администратора для авторизации запроса
|
||||
headers = {'Authorization': f'Bearer {admin_token}'}
|
||||
# Отправка запроса на удаление сессии пользователя по ID сессии
|
||||
response = requests.delete(
|
||||
f"{settings.KEYCLOAK_CONFIG['SERVER_URL']}/admin/realms/{settings.KEYCLOAK_CONFIG['REALM']}/sessions/{session_id}",
|
||||
headers=headers
|
||||
)
|
||||
# Проверка успешности запроса на удаление
|
||||
return response.status_code == 204
|
||||
|
||||
def get_user_id_from_session(request):
|
||||
# Получение информации о пользователе из сессии
|
||||
user_info = request.session.get('user_info', {})
|
||||
user_id = user_info.get('sub')
|
||||
user_id = user_info.get('sub') # 'sub' обычно используется как идентификатор пользователя
|
||||
# Проверка валидности формата ID пользователя
|
||||
if isinstance(user_id, str):
|
||||
return user_id
|
||||
else:
|
||||
|
@ -169,40 +204,55 @@ def get_user_id_from_session(request):
|
|||
return None
|
||||
|
||||
|
||||
def admin_logout_user(request,category_slug = None):
|
||||
|
||||
def admin_logout_user(request, category_slug=None):
|
||||
# Получение ID пользователя из сессии текущего запроса.
|
||||
user_id = get_user_id_from_session(request)
|
||||
|
||||
|
||||
# Получение административного токена для обращения к Keycloak API.
|
||||
admin_token = get_keycloak_admin_token()
|
||||
if not admin_token:
|
||||
# Логгирование ошибки, если не удалось получить токен администратора.
|
||||
logger.error("Can't obtain admin token.")
|
||||
# Отображение сообщения об ошибке пользователю.
|
||||
messages.error(request, "Can't obtain admin token for logout.")
|
||||
# Перенаправление на страницу выхода/авторизации в случае ошибки.
|
||||
return redirect(settings.KEYCLOAK_CONFIG['LOGOUT_REDIRECT_URL'])
|
||||
|
||||
# Получение списка активных сессий пользователя через Keycloak API.
|
||||
sessions = get_user_sessions(admin_token, user_id)
|
||||
if sessions is None or not sessions:
|
||||
# Логгирование, если сессии не найдены.
|
||||
logger.error("Can't find user sessions.")
|
||||
# Уведомление пользователя о невозможности найти активные сессии.
|
||||
messages.error(request, "No active sessions found for user.")
|
||||
redirect_uri = settings.KEYCLOAK_CONFIG['CALLBACK_URL']
|
||||
return redirect(redirect_uri)
|
||||
# Перенаправление на callback URL.
|
||||
return redirect(settings.KEYCLOAK_CONFIG['CALLBACK_URL'])
|
||||
|
||||
# Флаг, указывающий на успешный выход из всех сессий.
|
||||
all_sessions_logged_out = True
|
||||
for session in sessions:
|
||||
# Попытка выхода из каждой сессии через Keycloak API.
|
||||
if not logout_user(admin_token, session['id']):
|
||||
# Если выход из какой-либо сессии не удался, флаг устанавливается в False.
|
||||
all_sessions_logged_out = False
|
||||
logger.error(f"Failed to log out session {session['id']}")
|
||||
|
||||
if all_sessions_logged_out:
|
||||
# Логгирование успешного выхода из всех сессий.
|
||||
logger.info("User successfully logged out from all Keycloak sessions.")
|
||||
# Уведомление пользователя о успешном выходе.
|
||||
messages.success(request, "Successfully logged out.")
|
||||
else:
|
||||
# Уведомление пользователя, если выход был выполнен не из всех сессий.
|
||||
messages.warning(request, "Partial logout. Some sessions may still be active.")
|
||||
|
||||
# Очистка сессии Django после выхода пользователя.
|
||||
request.session.flush()
|
||||
redirect_uri = settings.KEYCLOAK_CONFIG['CALLBACK_URL']
|
||||
return redirect(redirect_uri)
|
||||
# Перенаправление пользователя на callback URL после выхода.
|
||||
return redirect(settings.KEYCLOAK_CONFIG['CALLBACK_URL'])
|
||||
|
||||
|
||||
from django.http import JsonResponse
|
||||
|
||||
|
||||
def check_user_authenticated(request):
|
||||
|
|
Binary file not shown.
|
@ -1,16 +1,14 @@
|
|||
|
||||
import logging
|
||||
|
||||
|
||||
from django.http import HttpResponse
|
||||
from django.views.decorators.http import require_http_methods
|
||||
from django.shortcuts import redirect
|
||||
from django.conf import settings
|
||||
from keycloak import KeycloakOpenID
|
||||
from urllib.parse import urlencode
|
||||
from django.contrib.auth import logout
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
def keycloak_login(request):
|
||||
|
||||
|
||||
def keycloak_login(request):
|
||||
# Инициализация клиента Keycloak с конфигурационными данными из настроек Django.
|
||||
keycloak_openid = KeycloakOpenID(
|
||||
server_url=settings.KEYCLOAK_CONFIG['SERVER_URL'],
|
||||
client_id=settings.KEYCLOAK_CONFIG['CLIENT_ID'],
|
||||
|
@ -18,29 +16,31 @@ def keycloak_login(request):
|
|||
client_secret_key=settings.KEYCLOAK_CONFIG['CLIENT_SECRET']
|
||||
)
|
||||
|
||||
|
||||
# Установка URL для перенаправления пользователя после аутентификации в Keycloak.
|
||||
redirect_uri = settings.KEYCLOAK_CONFIG['CALLBACK_URL']
|
||||
# Получение URL для аутентификации пользователя через Keycloak.
|
||||
auth_url = keycloak_openid.auth_url(redirect_uri=redirect_uri)
|
||||
# Логгирование успешной обработки запроса.
|
||||
logger.info('Запрос успешно обработан')
|
||||
# Перенаправление пользователя на страницу аутентификации Keycloak.
|
||||
return redirect(auth_url)
|
||||
|
||||
|
||||
|
||||
|
||||
from django.http import HttpResponse
|
||||
from django.views.decorators.http import require_http_methods
|
||||
|
||||
import logging
|
||||
@require_http_methods(["GET"])
|
||||
def keycloak_redirect(request):
|
||||
|
||||
# Extract the authorization code from the query parameters
|
||||
# Извлечение кода авторизации из параметров запроса.
|
||||
authorization_code = request.GET.get('code')
|
||||
|
||||
if authorization_code:
|
||||
# Proceed with the token exchange process here
|
||||
# Если код авторизации получен, продолжается процесс обмена токенами.
|
||||
print(authorization_code)
|
||||
logger.info(' 2 Запрос успешно обработан')
|
||||
return HttpResponse("Authorization code received.")
|
||||
else:
|
||||
return HttpResponse("Authorization code not found.", status=400)
|
||||
# Если код авторизации отсутствует, возвращается ошибка.
|
||||
return HttpResponse("Authorization code not found.", status=400)
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue