Ошибка при выходе из системы Django SAML
В моем проекте Django я использую python3-saml для входа в систему с помощью SSO. Вход работает как ожидалось, но выход из системы не удается с сообщением об ошибке "Не определено имя хоста". Я действительно не знаю, как решить эту проблему, поскольку единственным параметром, передаваемым для выхода из системы, является запрос, а в запросе отсутствуют 'http_host' и 'server_name', читайте здесь.
Моя часть выхода из системы выглядит следующим образом:
def get(self, request, pkuser=None):
try:
get_user_model().objects.get(pk=pkuser)
except get_user_model().DoesNotExist:
return redirect('HomePage')
logger = logging.getLogger('iam')
logger.info('IAM logout')
auth = OneLogin_Saml2_Auth(request, custom_base_path=settings.SAML_FOLDER)
logger.info('account logout')
# OneLogin_Saml2_Utils.delete_local_session()
try:
auth.logout(
name_id=request.session['samlNameId'],
session_index=request.session['samlSessionIndex'],
nq=request.session['samlNameIdNameQualifier'],
name_id_format=request.session['samlNameIdFormat'],
spnq=request.session['samlNameIdSPNameQualifier']
)
logger.info('account logout success')
OneLogin_Saml2_Utils.delete_local_session()
logger.info('account logout: deleted local session')
except Exception as e:
logger.info('account logout failed: {}'.format(str(e)))
logout(request)
return redirect('HomePage')
Возможно, я использую не тот пакет...? Любая помощь или совет будут оценены по достоинству.
Я думаю, что это происходит потому, что в методе logout
отсутствует http_host
и server_name
.
Для устранения этой проблемы измените объект запроса так, чтобы он включал атрибуты http_host
и server_name
перед вызовом метода logout.
def get(self, request, pkuser=None):
try:
get_user_model().objects.get(pk=pkuser)
except get_user_model().DoesNotExist:
return redirect('HomePage')
logger = logging.getLogger('iam')
logger.info('IAM logout')
auth = OneLogin_Saml2_Auth(request, custom_base_path=settings.SAML_FOLDER)
logger.info('account logout')
request.http_host = 'your_http_host'
request.server_name = 'your_server_name'
try:
auth.logout(
name_id=request.session['samlNameId'],
session_index=request.session['samlSessionIndex'],
nq=request.session['samlNameIdNameQualifier'],
name_id_format=request.session['samlNameIdFormat'],
spnq=request.session['samlNameIdSPNameQualifier']
)
logger.info('account logout success')
OneLogin_Saml2_Utils.delete_local_session()
logger.info('account logout: deleted local session')
except Exception as e:
logger.info('account logout failed: {}'.format(str(e)))
logout(request)
return redirect('HomePage')
В обработчике для вашего ACS URL вы также будете создавать объект из OneLogin_Saml2_Auth(), который теоретически работает. Проверьте, отличается ли настройка запроса к нему от настройки здесь.
Одна вещь, которая выделяется между этим и моим кодом, заключается в том, что в моем коде есть строка перед конструктором request_annotated = saml2_prepare_request(request)
(все имена в этой строке, вероятно, будут отличаться от request
, но формат останется тем же), где вы передаете request_annotated
конструктору OneLogin_Saml2_Auth
, а не request
. Если это так, продублируйте эту строку. Библиотека ожидает, что в словаре запроса есть некоторые специфические вещи, аннотированные к нему. Код для этой функции в моем Django выглядит так:
def saml2_prepare_request(request):
return {
'http_host': request.META['HTTP_HOST'],
'script_name': request.META['PATH_INFO'],
'server_port': request.META['SERVER_PORT'],
'get_data': request.GET.copy(),
'post_data': request.POST.copy()
}
Сообщение об ошибке "Имя хоста не определено" говорит о том, что метод OneLogin_Saml2_Auth.logout пытается построить URL для запроса на выход, но у него недостаточно информации для этого.
Метод OneLogin_Saml2_Auth.logout требует параметр returnTo, который представляет собой URL, на который должен быть перенаправлен браузер пользователя после обработки запроса на выход. Вы можете попробовать указать этот параметр в своем коде следующим образом:
auth.logout(
name_id=request.session['samlNameId'],
session_index=request.session['samlSessionIndex'],
nq=request.session['samlNameIdNameQualifier'],
name_id_format=request.session['samlNameIdFormat'],
spnq=request.session['samlNameIdSPNameQualifier'],
returnTo='http://localhost:8000/logout/'
)
Замените 'http://localhost:8000/logout/' на фактический URL конечной точки выхода из системы.
В качестве альтернативы можно попробовать использовать метод request.build_absolute_uri для построения URL returnTo на основе текущего запроса:
returnTo = request.build_absolute_uri(reverse('logout'))
auth.logout(
name_id=request.session['samlNameId'],
session_index=request.session['samlSessionIndex'],
nq=request.session['samlNameIdNameQualifier'],
name_id_format=request.session['samlNameIdFormat'],
spnq=request.session['samlNameIdSPNameQualifier'],
returnTo=returnTo
)