add files

main
Lowlights 2024-03-20 18:25:07 +06:00
parent f0382cc7ee
commit 4de1d3d9ff
15 changed files with 5366 additions and 140 deletions

212
README.md
View File

@ -1,2 +1,214 @@
# Harmony # 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 файл улучшит документацию проекта и поможет другим разработчикам понять, как использовать эти возможности в своих проектах.

Binary file not shown.

5049
debug.log

File diff suppressed because it is too large Load Diff

View File

@ -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
}

View File

@ -35,8 +35,7 @@ INSTALLED_APPS = [
'django.contrib.sites', 'django.contrib.sites',
'allauth', 'allauth',
'allauth.account', 'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.openid_connect',
'django.contrib.admin', 'django.contrib.admin',
'django.contrib.auth', 'django.contrib.auth',
'django_extensions', 'django_extensions',

View File

@ -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

View File

@ -11,10 +11,6 @@ urlpatterns = [
path('about/', views.about, name='about'), path('about/', views.about, name='about'),
path('', views.callback, name='product_list'), path('', views.callback, name='product_list'),
path('products/', views.callback, name='product_list'), path('products/', views.callback, name='product_list'),
path('<slug:category_slug>/', views.callback, path('<slug:category_slug>/', views.callback,name='product_list_by_category'),
name='product_list_by_category'), path('<int:id>/<slug:slug>/', views.product_detail,name='product_detail'),
path('<int:id>/<slug:slug>/', views.product_detail, path('about/', views.about, name='about'),]
name='product_detail'),
path('about/', views.about, name='about'),
]

View File

@ -1,14 +1,13 @@
import requests import requests
from django.shortcuts import render,get_object_or_404 from django.shortcuts import get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect
import logging import logging
from djangoProject1 import settings from djangoProject1 import settings
from .models import Category, Product from .models import Category, Product
from cart.forms import CartAddProductForm from cart.forms import CartAddProductForm
from jose import jwt from jose import jwt
from django.contrib import messages 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): def about(request):
return render(request, 'main/about.html') return render(request, 'main/about.html')
#Получение access token пользователя
def exchange_code_for_token(authorization_code, redirect_uri): def exchange_code_for_token(authorization_code, redirect_uri):
token_endpoint = 'https://auth.myterior.kz/realms/Harmony/protocol/openid-connect/token' token_endpoint = 'https://auth.myterior.kz/realms/Harmony/protocol/openid-connect/token'
client_id = 'admin-cli' 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("Failed to exchange code: HTTP status", response.status_code)
print("Response body:", response.text) print("Response body:", response.text)
raise Exception('Failed to exchange authorization code for tokens') raise Exception('Failed to exchange authorization code for tokens')
#Через access_token получать данные о пользователе декодировав его в json
def get_user_info(access_token): def get_user_info(access_token):
userinfo_endpoint = 'https://auth.myterior.kz/realms/Harmony/protocol/openid-connect/userinfo' userinfo_endpoint = 'https://auth.myterior.kz/realms/Harmony/protocol/openid-connect/userinfo'
headers = {'Authorization': f'Bearer {access_token}'} headers = {'Authorization': f'Bearer {access_token}'}
@ -62,7 +65,7 @@ def get_user_info(access_token):
else: else:
print("Failed to fetch user info: HTTP status", response.status_code) print("Failed to fetch user info: HTTP status", response.status_code)
return None return None
import jwt
def decode_access_token(access_token): def decode_access_token(access_token):
@ -70,98 +73,130 @@ def decode_access_token(access_token):
return payload return payload
def callback(request,category_slug=None): def callback(request, category_slug=None):
#Получение кода авторизации из запроса
context = {} context = {}
# Получение кода авторизации из запроса.
# где клиент получает код после аутентификации пользователя на сервере.
authorization_code = request.GET.get('code') authorization_code = request.GET.get('code')
if authorization_code: if authorization_code:
try: try:
# Обмен кода на access_token с помощью функции exchange_code_for_token.
# Этот токен необходим для доступа к защищенным ресурсам (например, к информации о пользователе)
# на сервере аутентификации.
access_token = exchange_code_for_token(authorization_code, settings.KEYCLOAK_CONFIG['CALLBACK_URL']) access_token = exchange_code_for_token(authorization_code, settings.KEYCLOAK_CONFIG['CALLBACK_URL'])
# Декодирование access_token для получения информации о пользователе.
# Это может включать имя пользователя, email и другие данные, в зависимости от настроек сервера.
user_info = decode_access_token(access_token) user_info = decode_access_token(access_token)
# Сохранение полученной информации о пользователе в сессии.
# Это позволяет использовать данные пользователя в дальнейшем, не обращаясь к серверу аутентификации.
request.session['user_info'] = user_info request.session['user_info'] = user_info
# Добавление информации о пользователе в контекст для отображения на странице.
context['userinfo'] = request.session.get('user_info', {}) context['userinfo'] = request.session.get('user_info', {})
except Exception as e: except Exception as e:
# В случае ошибки (например, проблемы с обменом кода или декодированием токена)
# добавляем информацию об ошибке в контекст.
context['error'] = str(e) context['error'] = str(e)
else: else:
# Если код авторизации не найден в запросе, сообщаем об этом через контекст.
context['error'] = "Authorization code not found." context['error'] = "Authorization code not found."
# Загрузка всех категорий и продуктов для отображения на странице.
# Если указан category_slug, фильтруем продукты по данной категории.
category = None category = None
categories = Category.objects.all() categories = Category.objects.all()
products = Product.objects.filter(available=True) products = Product.objects.filter(available=True)
if category_slug: if category_slug:
category = get_object_or_404(Category, category = get_object_or_404(Category, slug=category_slug)
slug=category_slug)
products = products.filter(category=category) 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 from django.shortcuts import render, redirect
def profile(request): def profile(request):
# Проверка метода запроса: если POST, значит пользователь отправил форму для обновления своих данных.
if request.method == 'POST': if request.method == 'POST':
# Получение текущей информации о пользователе из сессии.
user_info = request.session.get('user_info', {}) user_info = request.session.get('user_info', {})
# Обновление информации о пользователе данными из формы.
# Если какое-то поле не было предоставлено, используется текущее значение из сессии.
user_info['given_name'] = request.POST.get('first_name', user_info.get('given_name', '')) 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['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['preferred_username'] = request.POST.get('username', user_info.get('preferred_username', ''))
user_info['email'] = request.POST.get('email', user_info.get('email', '')) user_info['email'] = request.POST.get('email', user_info.get('email', ''))
# Сохранение обновленной информации о пользователе обратно в сессию.
request.session['user_info'] = user_info request.session['user_info'] = user_info
# После обновления информации редиректим пользователя на страницу callback,
# которая, скорее всего, отображает информацию о профиле или подтверждение об обновлении данных.
return render(request, 'main/callback.html') return render(request, 'main/callback.html')
else: else:
# Если метод запроса не POST, пользователь просто посещает страницу профиля,
# мы загружаем текущую информацию о пользователе из сессии и передаем ее в контекст шаблона.
context = {'userinfo': request.session.get('user_info', {})} context = {'userinfo': request.session.get('user_info', {})}
# Отображаем страницу профиля пользователя, передавая информацию о пользователе в контекст.
return render(request, 'main/callback.html', context) return render(request, 'main/callback.html', context)
# Настройте логирование # логирование
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def get_keycloak_admin_token(): def get_keycloak_admin_token():
# Формируем данные для запроса токена
data = { data = {
'client_id': settings.KEYCLOAK_CONFIG['CLIENT_ID'], 'client_id': settings.KEYCLOAK_CONFIG['CLIENT_ID'], # ID клиента
'client_secret': settings.KEYCLOAK_CONFIG['CLIENT_SECRET'], 'client_secret': settings.KEYCLOAK_CONFIG['CLIENT_SECRET'], # Секрет клиента
'grant_type': 'client_credentials', 'grant_type': 'client_credentials', # Тип авторизации
} }
# Отправка запроса для получения токена администратора Keycloak
response = requests.post( response = requests.post(
f"{settings.KEYCLOAK_CONFIG['SERVER_URL']}/realms/{settings.KEYCLOAK_CONFIG['REALM']}/protocol/openid-connect/token", f"{settings.KEYCLOAK_CONFIG['SERVER_URL']}/realms/{settings.KEYCLOAK_CONFIG['REALM']}/protocol/openid-connect/token",
data=data data=data
) )
# Возвращаем токен доступа из ответа
return response.json()['access_token'] return response.json()['access_token']
def get_user_sessions(admin_token, user_id): def get_user_sessions(admin_token, user_id):
# Установка заголовков с токеном администратора для авторизации запроса
headers = {'Authorization': f'Bearer {admin_token}'} headers = {'Authorization': f'Bearer {admin_token}'}
# Запрос на получение списка сессий пользователя в Keycloak
response = requests.get( response = requests.get(
f"{settings.KEYCLOAK_CONFIG['SERVER_URL']}/admin/realms/{settings.KEYCLOAK_CONFIG['REALM']}/users/{user_id}/sessions", f"{settings.KEYCLOAK_CONFIG['SERVER_URL']}/admin/realms/{settings.KEYCLOAK_CONFIG['REALM']}/users/{user_id}/sessions",
headers=headers headers=headers
) )
# Проверка успешности запроса и возвращение результата
if response.status_code == 200: if response.status_code == 200:
return response.json() return response.json()
else: else:
logger.error(f"Error fetching user sessions: {response.status_code}") logger.error(f"Error fetching user sessions: {response.status_code}")
return [] return []
def logout_user(admin_token, session_id):
def logout_user(admin_token,session_id): # Установка заголовков с токеном администратора для авторизации запроса
headers = { headers = {'Authorization': f'Bearer {admin_token}'}
'Authorization': f'Bearer {admin_token}', # Отправка запроса на удаление сессии пользователя по ID сессии
}
response = requests.delete( response = requests.delete(
f"{settings.KEYCLOAK_CONFIG['SERVER_URL']}/admin/realms/{settings.KEYCLOAK_CONFIG['REALM']}/sessions/{session_id}", f"{settings.KEYCLOAK_CONFIG['SERVER_URL']}/admin/realms/{settings.KEYCLOAK_CONFIG['REALM']}/sessions/{session_id}",
headers=headers headers=headers
) )
# Проверка успешности запроса на удаление
return response.status_code == 204 return response.status_code == 204
def get_user_id_from_session(request): def get_user_id_from_session(request):
# Получение информации о пользователе из сессии
user_info = request.session.get('user_info', {}) 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): if isinstance(user_id, str):
return user_id return user_id
else: else:
@ -169,40 +204,55 @@ def get_user_id_from_session(request):
return None 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) user_id = get_user_id_from_session(request)
# Получение административного токена для обращения к Keycloak API.
admin_token = get_keycloak_admin_token() admin_token = get_keycloak_admin_token()
if not admin_token: if not admin_token:
# Логгирование ошибки, если не удалось получить токен администратора.
logger.error("Can't obtain admin token.") logger.error("Can't obtain admin token.")
# Отображение сообщения об ошибке пользователю.
messages.error(request, "Can't obtain admin token for logout.") messages.error(request, "Can't obtain admin token for logout.")
# Перенаправление на страницу выхода/авторизации в случае ошибки.
return redirect(settings.KEYCLOAK_CONFIG['LOGOUT_REDIRECT_URL']) return redirect(settings.KEYCLOAK_CONFIG['LOGOUT_REDIRECT_URL'])
# Получение списка активных сессий пользователя через Keycloak API.
sessions = get_user_sessions(admin_token, user_id) sessions = get_user_sessions(admin_token, user_id)
if sessions is None or not sessions: if sessions is None or not sessions:
# Логгирование, если сессии не найдены.
logger.error("Can't find user sessions.") logger.error("Can't find user sessions.")
# Уведомление пользователя о невозможности найти активные сессии.
messages.error(request, "No active sessions found for user.") messages.error(request, "No active sessions found for user.")
redirect_uri = settings.KEYCLOAK_CONFIG['CALLBACK_URL'] # Перенаправление на callback URL.
return redirect(redirect_uri) return redirect(settings.KEYCLOAK_CONFIG['CALLBACK_URL'])
# Флаг, указывающий на успешный выход из всех сессий.
all_sessions_logged_out = True all_sessions_logged_out = True
for session in sessions: for session in sessions:
# Попытка выхода из каждой сессии через Keycloak API.
if not logout_user(admin_token, session['id']): if not logout_user(admin_token, session['id']):
# Если выход из какой-либо сессии не удался, флаг устанавливается в False.
all_sessions_logged_out = False all_sessions_logged_out = False
logger.error(f"Failed to log out session {session['id']}") logger.error(f"Failed to log out session {session['id']}")
if all_sessions_logged_out: if all_sessions_logged_out:
# Логгирование успешного выхода из всех сессий.
logger.info("User successfully logged out from all Keycloak sessions.") logger.info("User successfully logged out from all Keycloak sessions.")
# Уведомление пользователя о успешном выходе.
messages.success(request, "Successfully logged out.") messages.success(request, "Successfully logged out.")
else: else:
# Уведомление пользователя, если выход был выполнен не из всех сессий.
messages.warning(request, "Partial logout. Some sessions may still be active.") messages.warning(request, "Partial logout. Some sessions may still be active.")
# Очистка сессии Django после выхода пользователя.
request.session.flush() request.session.flush()
redirect_uri = settings.KEYCLOAK_CONFIG['CALLBACK_URL'] # Перенаправление пользователя на callback URL после выхода.
return redirect(redirect_uri) return redirect(settings.KEYCLOAK_CONFIG['CALLBACK_URL'])
from django.http import JsonResponse
def check_user_authenticated(request): def check_user_authenticated(request):

View File

View File

@ -1,16 +1,14 @@
import logging import logging
from django.http import HttpResponse
from django.views.decorators.http import require_http_methods
from django.shortcuts import redirect from django.shortcuts import redirect
from django.conf import settings from django.conf import settings
from keycloak import KeycloakOpenID from keycloak import KeycloakOpenID
from urllib.parse import urlencode
from django.contrib.auth import logout
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def keycloak_login(request):
def keycloak_login(request):
# Инициализация клиента Keycloak с конфигурационными данными из настроек Django.
keycloak_openid = KeycloakOpenID( keycloak_openid = KeycloakOpenID(
server_url=settings.KEYCLOAK_CONFIG['SERVER_URL'], server_url=settings.KEYCLOAK_CONFIG['SERVER_URL'],
client_id=settings.KEYCLOAK_CONFIG['CLIENT_ID'], client_id=settings.KEYCLOAK_CONFIG['CLIENT_ID'],
@ -18,29 +16,31 @@ def keycloak_login(request):
client_secret_key=settings.KEYCLOAK_CONFIG['CLIENT_SECRET'] client_secret_key=settings.KEYCLOAK_CONFIG['CLIENT_SECRET']
) )
# Установка URL для перенаправления пользователя после аутентификации в Keycloak.
redirect_uri = settings.KEYCLOAK_CONFIG['CALLBACK_URL'] redirect_uri = settings.KEYCLOAK_CONFIG['CALLBACK_URL']
# Получение URL для аутентификации пользователя через Keycloak.
auth_url = keycloak_openid.auth_url(redirect_uri=redirect_uri) auth_url = keycloak_openid.auth_url(redirect_uri=redirect_uri)
# Логгирование успешной обработки запроса.
logger.info('Запрос успешно обработан') logger.info('Запрос успешно обработан')
# Перенаправление пользователя на страницу аутентификации Keycloak.
return redirect(auth_url) return redirect(auth_url)
from django.http import HttpResponse
from django.views.decorators.http import require_http_methods
import logging
@require_http_methods(["GET"]) @require_http_methods(["GET"])
def keycloak_redirect(request): def keycloak_redirect(request):
# Извлечение кода авторизации из параметров запроса.
# Extract the authorization code from the query parameters
authorization_code = request.GET.get('code') authorization_code = request.GET.get('code')
if authorization_code: if authorization_code:
# Proceed with the token exchange process here # Если код авторизации получен, продолжается процесс обмена токенами.
print(authorization_code) print(authorization_code)
logger.info(' 2 Запрос успешно обработан') logger.info(' 2 Запрос успешно обработан')
return HttpResponse("Authorization code received.") return HttpResponse("Authorization code received.")
else: else:
# Если код авторизации отсутствует, возвращается ошибка.
return HttpResponse("Authorization code not found.", status=400) return HttpResponse("Authorization code not found.", status=400)