Ошибка входа в систему пользователя ColdFusion после тайм-аута сеанса

Недавно мы перешли на cf11 для проекта и столкнулись с необычной проблемой:

Когда пользователь разрешает тайм-аут своего сеанса и пытается снова войти в систему, ему требуется две попытки для успешного входа в систему.

Когда пользователь вручную выходит из системы, у него не возникает проблем со входом в систему.

Этой проблемы не было в CF8. Я изучил пользовательские области и не вижу разницы. Я пытался добавить код выхода перед входом в систему в надежде, что смогу сделать состояние таким же. Ни то, ни другое не сработало. Это известная проблема? И у вас есть предложение, что я могу попробовать?

РЕДАКТИРОВАТЬ:

У меня есть Application.cfc и result.cfm в корне проекта. У меня есть папка signin/ для страниц, которые не вошли в систему. Она содержит signin.cfm и onsignin.cfm, которые обрабатывают аутентификацию. При запуске кода дождитесь истечения времени сеанса, прежде чем снова войти в систему с тем же именем пользователя.

вход/signin.cfm

<form action="onsignin.cfm" method="POST" >
    User name: <input name="login" type="text" />
    <input type="submit" value="Login" name="btnSubmit" >
</form>

вход/onsignin.cfm

<cffunction name="authenticate" access="public" returntype="void">
    <cfargument name="login" />
    <cflogin idletimeout="3600">
        <cfloginuser name="#arguments.login#" password="1234AbCd" roles="admin,developer,login_session,login_signoff" />
    </cflogin>
    <cfreturn />
</cffunction>

<cfscript>
    authenticate(trim(Login));
    writeOutput("At /signin/onsignin.cfm<br/>");
    writeOutput("IsUserLoggedIn: #IsUserLoggedIn()#<br /><hr/>");
</cfscript>

<cflocation url="../result.cfm" addToken="no" /><!--- before we get to result.cfm onRequestStart() in Application.cfc is triggered. --->

Приложение.cfc

<cfcomponent>
    <cfset THIS.Name = "LoginTest" />
    <cfset THIS.SessionManagement = true />
    <cfset THIS.ClientManagement = false />
    <cfset THIS.LoginStorage = "session" />
    <cfset THIS.setClientCookies = false />
    <cfset This.sessiontimeout= createTimeSpan(0,0,0,20)/><!--- 20second timeout to show the session problem --->

    <cffunction name="outputCurrentLoginState" access="private">
        <cfargument name="currentFunction" type="string" required="true"/>
        <cfargument name="TargetPage" type="string" required="true"/>
        <cfscript>
            writeOutput("In function: #arguments.currentFunction# state is <br />");
            writeOutput("TargetPage: #arguments.TargetPage# <br />");
            writeOutput("GetAuthUser: #GetAuthUser()#<br />");
            writeOutput("GetUserRoles: #GetUserRoles()#<br />");
            writedump(session);
            writedump(cookie);
            writeOutput("IsUserLoggedIn: #IsUserLoggedIn()#<br /><hr />");
            /*use writeLog() to view to Console */
        </cfscript>
    </cffunction>

    <cffunction name="OnRequestStart" access="public" returntype="boolean">
        <cfargument name="TargetPage" type="string" required="true"/>
        <cfset outputCurrentLoginState("OnRequestStart",arguments.TargetPage)/>
        <cfif not IsDefined("Cookie.CFID")>
            <CFLOCK SCOPE="SESSION" TYPE="exclusive" TIMEOUT="5">
                <cfcookie name="CFID" value="#SESSION.CFID#" secure="false" httpOnly="true" />
                <cfcookie name="CFTOKEN" value="#SESSION.CFTOKEN#" secure="false" httpOnly="true" />
            </CFLOCK>
        </cfif>
        <cfreturn true />
    </cffunction>

    <cffunction name="OnRequest" access="public">
        <cfargument name="TargetPage" type="string" required="true"/>
        <cfset outputCurrentLoginState("OnRequest",arguments.TargetPage)/>
        <cfif findNoCase("signin/", arguments.TargetPage)>
            <cflogout/>
        </cfif>
        <cfinclude template="#ARGUMENTS.TargetPage#" />
    </cffunction>
</cfcomponent>

результат.cfm

<cfscript>
    writeOutput("GetAuthUser: #GetAuthUser()#<br />");
    writeOutput("GetUserRoles: #GetUserRoles()#<br />");
    writeOutput("--- IsUserLoggedIn: #IsUserLoggedIn()#<br />");
    writeOutput("At /result.cfm<hr/>");
</cfscript>

Обновление: теперь у меня есть приведенный выше тестовый код, который не работает для cf11, я попробовал его на сервере cf8, и в cf8 он работает так, как я ожидал. Когда время сеанса истекает, у пользователя не возникает проблем с созданием нового сеанса. Только в cf11 он не работает.


person user619882    schedule 05.03.2015    source источник
comment
Нет, боюсь, это не известная проблема. Что вам нужно сделать, так это дать нам код для просмотра. Не фактическое приложение, а минимальный случай, демонстрирующий проблему (см. sscce.org). Недостаточно, чтобы продолжить предоставленную вами информацию.   -  person Adam Cameron    schedule 05.03.2015
comment
Чистый выстрел в темноте, но возможно ли, что, когда время сеанса пользователя истекает и пользователь переходит на экран входа в систему, у вас есть cfid и cftoken как часть URL-адреса? Это может привести к срабатыванию старого сеанса. Как сказал @AdamCameron, не видя никакого кода, все, что мы можем сделать, это строить догадки.   -  person CFML_Developer    schedule 05.03.2015
comment
Спасибо за ответ. Вы правы — я должен был предоставить код. Я попытался удалить код приложения, но, к сожалению, проблема исчезла. Я отредактировал вопрос, чтобы дать немного больше деталей.   -  person user619882    schedule 06.03.2015
comment
Если вы удалили код приложения и проблема исчезла, очевидно, что проблема связана с вашим кодом. Правильно? Так что начните возвращать код приложения, часть за частью, пока он снова не сломается. Это подскажет, где проблема.   -  person Miguel-F    schedule 06.03.2015
comment
Да, у меня была трудная задача — разобрать код до костей, чтобы четко показать проблему. Мне это удалось. (Извините за задержку.)   -  person user619882    schedule 08.03.2015
comment
Я подозреваю, что это может быть как-то связано с новым атрибутом allowconcurrent, который был добавлен в ColdFusion 11 и по умолчанию имеет значение true. Попробуйте установить для этого атрибута значение false <cflogin idletimeout="3600" allowconcurrent="false">, чтобы тег cflogin работал так, как он использовался в ColdFusion 8. Я думаю, что настоящий корень проблемы в том, что у вас более короткий тайм-аут сеанса (здесь 20 секунд), чем у тегов cflogin idletimeout ( 3600 секунд здесь). Поскольку вы установили loginStorage на session, тег cflogin пытается удержать пользователя, но сеанс разрывается.   -  person Miguel-F    schedule 09.03.2015
comment
Спасибо, Мигель — у меня было 20 секунд в тестовом коде, так что было бы легко воссоздать ошибку. В производстве он намного дольше. Я пытался изменить idletimeout, чтобы он был меньше или соответствовал sessiontimeout, но это не повлияло на результат, и ошибка осталась той же. Однако замена allowconcurrent на false действительно меняет результат. Спасибо, что заметили это. Изменение allowconcurrent не будет приемлемым решением для моего приложения. Это похоже на недокументированную ошибку в cf11.   -  person user619882    schedule 09.03.2015
comment
Я разместил ответ для других пользователей, чтобы найти легче. Пожалуйста, смотрите мой ответ там.   -  person Miguel-F    schedule 09.03.2015


Ответы (3)


У меня есть работа, которая будет достаточно хороша для моего варианта использования. Старый код:

<cflogin idletimeout="3600">
<cfloginuser name="#yourlogin#" password="#yourpassword#" roles="#yourroles#" />
</cflogin>

Новый код:

<cflogin idletimeout="3600" allowconcurrent="false">
<cfloginuser name="#yourlogin##createUUID()#" password="#yourpassword#" roles="#yourroles#" />
</cflogin>

Добавление случайного значения к атрибуту cfloginuser name должно сделать всех уникальными, даже если они используют одни и те же учетные данные, когда вы проверяете их по базе данных. Это немного хак, но он решает проблему. Спасибо всем за помощь... Особенно Мигелю за то, что он ответил на allowconcurrent.

person user619882    schedule 11.03.2015

Я добавил следующий комментарий к 3839458:


Другой обходной путь — продублировать файл cflogin. Пример:

<cflogin ..>
<cflogin ..>

Когда оба имеют allowconcurrent=true (по умолчанию), оба будут работать. isUserLoggedIn() возвращает YES после 1-го, но 1-й вход на самом деле терпит неудачу. 2-й работает и входит в систему правильно.

Репродукция прикреплена как Application.cfc

Когда THIS.loginStorage="cookie", проблема не повторяется, если все еще присутствует старый файл cookie cfauthorization.


Спасибо!,

-Аарон

person Aaron Neff    schedule 17.05.2015

Обновить

Adobe уже сообщала об этой проблеме — ошибка 3839458. Я предлагаю вам добавить свой опыт и проголосовать за эту ошибку. В настоящее время он имеет статус «ToTrack» по причине «PRNeedInfo». Я также проголосовал за него и добавил ссылку на этот вопрос для получения дополнительной информации.


Появилось благодаря комментариям

Я думаю, проблема в том, что вы установили для атрибута idletimeout тега <cflogin> значение (3600 секунд), которое больше, чем значение времени ожидания вашего сеанса (20 секунд). Это неверный подход. Я понимаю, что вы установили время ожидания сеанса на 20 секунд для простоты тестирования. Тем не менее, не имеет смысла иметь более длительный idletimeout тайм-аут сеанса, когда вы устанавливаете loginStorage равным session. Тег <cflogin> пытается сохранить активным сеанс пользователя, но сам сеанс разрывается вне его контроля. Это напрашивается на неприятности, на мой взгляд. Оставьте параметр idletimeout меньше или по крайней мере равным параметру тайм-аута сеанса.

Я подозреваю, что разница, которую вы видите между версиями ColdFusion, может быть связана с новым атрибутом, который был добавлен к тегу <cflogin> в ColdFusion 11. Атрибут allowconcurrent (ссылка на документацию). По умолчанию для этого параметра установлено значение true, что означает, что одновременные сеансы входа должны быть разрешены. Попробуйте установить для этого атрибута значение false, например, <cflogin idletimeout="3600" allowconcurrent="false">. Я считаю, что это заставит тег <cflogin> работать так же, как в ColdFusion 8.

Вы упоминаете в комментариях, что установка allowconcurrent на false не является приемлемым решением. Почему? Вот как это работает для вас в ColdFusion 8. Я чувствую, что поведение, которое вы видите, «работает так, как задумано». Однако, если вы считаете, что это ошибка, сообщите об ошибке в Adobe.

Кстати, я также заметил, что вы устанавливаете ClientManagement и setClientCookies на false. Тем не менее, в вашем методе OnRequestStart вы устанавливаете эти файлы cookie. Почему? Они не нужны для управления сеансом. Сервер ColdFusion сделает это за вас.

person Miguel-F    schedule 09.03.2015
comment
Привет, Мигель. От allowconcurrent до false нам не подходит, потому что в CF8 это не работает. В CF8 вы можете войти в систему несколько раз, и у нее нет этой проблемы со входом — вот почему allowconcurrent = "true" является значением по умолчанию в CF11. Поэтому я не думаю, что можно утверждать, что он работает так, как задумано. Кстати, я устанавливаю файлы cookie вручную, потому что хочу переопределить настройки по умолчанию. Если удалить код cfcookie, ошибка будет та же. - person user619882; 09.03.2015
comment
И, по-видимому, об этом была открыта ошибка - bugbase.adobe.com/index. .cfm?event=bug&id=3839458 Я предлагаю вам добавить свой опыт и проголосовать за эту ошибку. В настоящее время он имеет статус ToTrack по причине PRNeedInfo. - person Miguel-F; 11.03.2015