Логирование событий аутентификации в Showcase

Материал из Course Orchestra
Перейти к: навигация, поиск

Настройка

Для настройки логирования событий аутентификации в Showcase (логирование факта входа в систему - аутенитфикации, логирование ошибок аутентификации, логирования выхода из системы, логирование завершения пользовательской сессии по таймайту) необходимо:

1. Создать хранимую процедуру логирования в базе данных, которая на вход будет получать следующие параметры:

@session_context - контекст (xml)

@data - данные (xml)

@type - тип события (nvarchar(10))

Данная процедура будет записывать данные в некоторую таблицу лога.

Вместо процедуры можно создать скрипт celesta или процедуру на python в соответствии с принципом универсальных источников Showcase.

2. Добавить в genaralapp.properties следующую строку:

  security.logging.proc = dbo.securitylogging

, где dbo.securitylogging - имя процедуры или скрипта для логирования, созданной в п.1. Данная функция или процедура будут выполнены при наступлении одного из указанных выше событий аутентификации Showcase

Процедура логирования.

Для @type возможны 4 значения (события):

LOGIN - успешный вход в систему

LOGINERROR - вход в систему не успешен

LOGOUT - пользовательский выход из системы (переход по ссылке "Выход")

SESSSIONTIMEOUT - завершение пользовательской сессии

В случае события LOGIN в атрибут @data передается xml вида:

< data >
   <HttpSessionId>7B6C709767CFD64051DEDF3B7618788C</HttpSessionId>
   <Browser>FIREFOX</Browser>
   <BrowserVersion>33.0</BrowserVersion>
   <IP>localhost</IP>
   <Host>127.0.0.1</Host>    
   <OS>WINDOWS</OS>
   <OSVersion>nt 6.3</OSVersion>
   <UserAgent>mozilla/5.0 (windows nt 6.3; wow64; rv:33.0) gecko/20100101 firefox/33.0</UserAgent>
< /data >

HttpSessionId - идентификатор сессии

Browser - название браузера

BrowserVersion - версия браузера

IP - ip клиента

Host - dns имя склиента (если не определено то ip)

OS - имя операционной системы

OSVersion - версия ОС

UserAgent - значение из http заголовка для User-Agent (на основе которого выполнялась попытка определить Browser, BrowserVersion, OS, OSVersion)


В случае события LOGINERROR в @data передается xml вида:

< data >
   <SecurityLastExeption>Bad credentials</SecurityLastExeption>
   <OS>WINDOWS</OS>
   <IP>172.16.1.132</IP>
   <UserAgent>mozilla/5.0 (windows nt 6.3; win64; x64) applewebkit/537.36 (khtml, like gecko) chrome/58.0.3029.110 safari/537.36</UserAgent>
   <OSVersion>nt 6.3</OSVersion>
   <Host>172.16.1.132</Host>
   <BrowserVersion>58.0.3029.110</BrowserVersion>
   <errorData>
       <password>Password</password>
       <Message>Bad credentials</Message>
       <domain></domain>
       <name>FORM</name>
       <username>user1</username>
   </errorData>
   <HttpSessionId>4CA631B3977D462A8144368BC838DB87</HttpSessionId>
   <Browser>CHROME</Browser>
< /data >

SecurityLastExeption - сообщение об ошибке неуспешного входа

errorData - в этой секции содержатся данные, идентифицирующие пользователя, вход которого был не успешен

Остальные параметры идентичны параметрам, возвращаемым при событии LOGIN.


В случае события LOGOUT формируется xml вида

< data >
   <HttpSessionId>7B6C709767CFD64051DEDF3B7618788C</HttpSessionId>
< /data >

Т.е. передается только HttpSessionId (возможности получить остальные параметры в данных случаях нет)


А в случае события SESSIONTIMEOUT - xml вида

< data >
   <HttpSessionId>7B6C709767CFD64051DEDF3B7618788C</HttpSessionId>
   <UserName>admin</UserName>
< /data >

Т.е. помимо HttpSessionId, передаётся ещё параметр UserName, отвечающий за имя пользователя, сессия которого истекла

Пример celesta-скрипта для всех случаев логирования

def loginLogoutProc(context, data, type):
    u"""Процедура, запускающаяся при входе и выходе из Showcase"""
    if type == 'LOGIN':

        sid = context.getUserId()

        userLang = userLangCursor(context)
        if userLang.tryGet(sid):
            u"Установка языка интерфейса"
            UserDataUtils.setLocaleFromCelestaLoggingProc(context.getSessionId(), userLang.langid)

        u"""Изменения должны быть сохранены даже в случае ошибки при загрузке страницы"""
        context.commit()

        u"""Логируем"""
        logger = WombatLogger(context, {"type": "login_ok"})
        logger.info({"initiator": get_user_repr(context, context.getUserId())})
    
    elif type == "LOGINERROR":

        data = json.loads(XMLJSONConverter.xmlToJson(data))["data"]
        # too many login attempts
        regexp = re.compile("^User '.+' is blocked by mellophone. Time to unlock: (\d+) s.$")
        result = regexp.match(data["SecurityLastExeption"])
        if result:
            block_min = getUserdataSettings(context, "audit.failedLoginBlockMinutes", "10")
            logger = WombatLogger(context, {"type": "user_block_attempts"})
            logger.info({"username": data["errorData"]["username"],
                         "block_min": block_min})

        logger = WombatLogger(context, {"type": "login_fail"})
        logger.info({"username": get_user_repr(context, data["errorData"]["username"])})

    elif type == 'LOGOUT':
        logger = WombatLogger(context, {"type": "logout"})
        logger.info({"initiator": get_user_repr(context, context.getUserId())})
    
    elif type == 'SESSIONTIMEOUT':
        from nsi.function.person import getSubjectIdByUsername

        data = json.loads(XMLJSONConverter.xmlToJson(data))["data"]
        sid = getSubjectIdByUsername(context, data["UserName"])

        logger = WombatLogger(context, {"type": "login_timeout"})
        logger.info({"user": get_user_repr(context, sid)})