Полный код и инструкции по быстрому воспроизведению проблемы приведены ниже.
ПРОБЛЕМА:
HttpSession
становится null
после пользовательской реализации DefaultOAuth2RequestFactory
заменяет текущий AuthorizationRequest
с сохраненным AuthorizationRequest
. Это приводит к отказу последующего запроса на /oauth/token
, потому что CsrfFilter в цепочке фильтров Spring Security, предшествующей конечной точке /oauth/token
, не может найдите session
Csrf token
в null
session
, чтобы сравнить с Csrf token
request
. ПРОЦЕСС УПРАВЛЕНИЯ ВО ВРЕМЯ ОШИБКИ:
На следующей блок-схеме показано, как Шаг 14 и Шаг 15 каким-то образом null
уточняют HttpSession
. (Или, возможно, не соответствует JSESSIONID
.) SYSO
в начале CustomOAuth2RequestFactory.java
на шаге 14 показывает, что действительно существует HttpSession
, который на самом деле содержит правильный CsrfToken
. Тем не менее, каким-то образом HttpSession
становится null
к тому времени, когда Шаг 15 инициирует вызов от клиента по URL-адресу localhost:8080/login
обратно к конечной точке localhost:9999/oauth/token
.
Точки останова были добавлены в каждую строку HttpSessionSecurityContextRepository
, упомянутый в приведенных ниже журналах отладки. (Он расположен в папке Maven Dependencies
проекта authserver
eclipse.) Эти точки останова подтвердили, что HttpSession
является null
, когда последний запрос к /oauth/token
делается в блок-схеме ниже. (Внизу слева на блок-схеме.) null
HttpSession
может быть связано с тем, что JSESSIONID
, оставшийся в браузере, устарел после запуска пользовательского кода DefaultOAuth2RequestFactory
.
Как можно исправить эту проблему, чтобы тот же HttpSession
оставался во время последнего вызова конечной точки /oauth/token
после завершения шага 15 на блок-схеме?
СООТВЕТСТВУЮЩИЙ КОД И ЖУРНАЛЫ:
Полный код CustomOAuth2RequestFactory.java
можно просмотреть на сайте обмена файлами, нажав на эту ссылку. Мы можем предположить, что null
session
возникает либо из-за 1.) JSESSIONID
, не обновленного в браузере кодом в CustomOAuth2RequestFactory
, либо 2.) HttpSession
на самом деле null
-ифицированного.
В журналах отладки Spring Boot для вызова /oauth/token
после шага 15 четко указано, что к этому моменту HttpSession
нет, и их можно прочитать следующим образом:
2016-05-30 15:33:42.630 DEBUG 13897 --- [io-9999-exec-10] o.s.security.web.FilterChainProxy : /oauth/token at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2016-05-30 15:33:42.631 DEBUG 13897 --- [io-9999-exec-10] o.s.security.web.FilterChainProxy : /oauth/token at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2016-05-30 15:33:42.631 DEBUG 13897 --- [io-9999-exec-10] w.c.HttpSessionSecurityContextRepository : No HttpSession currently exists
2016-05-30 15:33:42.631 DEBUG 13897 --- [io-9999-exec-10] w.c.HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: null. A new one will be created.
2016-05-30 15:33:42.631 DEBUG 13897 --- [io-9999-exec-10] o.s.security.web.FilterChainProxy : /oauth/token at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2016-05-30 15:33:42.631 DEBUG 13897 --- [io-9999-exec-10] o.s.s.w.header.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@2fe29f4b
2016-05-30 15:33:42.631 DEBUG 13897 --- [io-9999-exec-10] o.s.security.web.FilterChainProxy : /oauth/token at position 4 of 12 in additional filter chain; firing Filter: 'CsrfFilter'
2016-05-30 15:33:42.644 DEBUG 13897 --- [io-9999-exec-10] o.s.security.web.csrf.CsrfFilter : Invalid CSRF token found for http://localhost:9999/uaa/oauth/token
2016-05-30 15:33:42.644 DEBUG 13897 --- [io-9999-exec-10] w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2016-05-30 15:33:42.644 DEBUG 13897 --- [io-9999-exec-10] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
ПОВТОРНОЕ СОЗДАНИЕ ПРОБЛЕМЫ НА ВАШЕМ КОМПЬЮТЕРЕ:
Вы можете воссоздать проблему на любом компьютере всего за несколько минут, выполнив следующие простые действия:
1.) Загрузите заархивированную версию приложения с сайта обмена файлами, нажав на эту ссылку.
2.) Разархивируйте приложение, набрав: tar -zxvf oauth2.tar(4).gz
3.) Запустите приложение authserver
, перейдя к oauth2/authserver
и набрав mvn spring-boot:run
.
4.) Запустите приложение resource
, перейдя к oauth2/resource
и набрав mvn spring-boot:run
.
5.) Запустите приложение ui
, перейдя к oauth2/ui
и набрав mvn spring-boot:run
.
6.) Откройте веб-браузер и перейдите к http : // localhost : 8080
7.) Нажмите Login
, затем введите Frodo
в качестве пользователя и MyRing
в качестве пароля, а затем нажмите, чтобы отправить.
8.) Введите 5309
в качестве Pin Code
и нажмите «Отправить». Это приведет к ошибке, показанной выше.
В журналах отладки Spring Boot будет отображаться МНОГО SYSO
, что дает значения переменных, таких как XSRF-TOKEN
и HttpSession
, на каждом шаге, показанном на блок-схеме. SYSO
помогает сегментировать журналы отладки, чтобы их было легче интерпретировать. И все SYSO
выполняются одним классом, вызываемым другими классами, поэтому вы можете манипулировать классом, генерирующим SYSO
, чтобы изменять отчеты повсюду в потоке управления. Класс, генерирующий SYSO
, называется TestHTTP
, а его исходный код можно найти в том же пакете demo
.
ИСПОЛЬЗУЙТЕ ОТЛАДЧИК:
1.) Выберите окно терминала, в котором запущено приложение authserver
, и введите Ctrl-C
, чтобы остановить приложение authserver
.
2.) Импортируйте три приложения (authserver
, resource
и ui
) в eclipse как существующие проекты maven.
3.) В обозревателе проектов eclipse приложения authserver
нажмите, чтобы развернуть папку Maven Dependencies
, затем прокрутите ее вниз, чтобы развернуть Spring-Security-web...
jar, как показано оранжевым кружком на изображение ниже. Затем прокрутите, чтобы найти и развернуть пакет org.springframework.security.web.context
. Затем дважды щелкните, чтобы открыть класс HttpSessionSecurityContextRepository
, выделенный синим цветом на снимке экрана ниже. Добавьте точки останова в каждую строку этого класса. Вы можете сделать то же самое с классом SecurityContextPersistenceFilter
в том же пакете. Эти точки останова позволят вам увидеть значение HttpSession
, которое в настоящее время становится null
перед окончанием потока управления, но должно иметь допустимое значение, которое можно сопоставить с XSRF-TOKEN
, чтобы решить эту проблему. ОП.
4.) В пакете demo
приложения добавьте точки останова внутри файла CustomOAuth2RequestFactory.java
. Затем Debug As... Spring Boot App
для запуска отладчика.
5.) Затем повторите шаги с 6 по 8 выше. Вы можете очистить кеш браузера перед каждой новой попыткой. И вы можете открыть вкладку «Сеть» инструментов разработчика браузера.