Ошибка при выходе из системы 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
)
Вернуться на верх