Я видел пару постов, в которых говорилось о чем-то похожем, хотя и не совсем о том, что я пытаюсь сделать. А именно, я наткнулся на https://www.jessym.com/articles/statele ... pring-boot, который представляет собой довольно сложное руководство, которое по-прежнему вписывается в Spring Security и имеет то, что автор называет «логины oauth2 без сохранения состояния». Проблема с их подходом заключается в том, что он по-прежнему использует файлы cookie, которых я бы предпочел избегать, поскольку они по-прежнему уязвимы для таких вещей, как атаки CSRF.

Здесь я представил графическое изображение того, чего я пытаюсь достичь.
В первом разделе показано поведение Spring Security по умолчанию (я использую Spring Security 6.2.0) со следующей конфигурацией и свойствами:
SecurityConfiguration.java:
@Configuration общественный класс SecurityConfiguration { частная статическая окончательная строка [] SWAGGER_URLS = { "/v3/api-docs/**", "/чванство-ui/**", "/v2/api-docs/**", "/чванство-ресурсы/**" }; @Бин public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity, ClientRegistrationRepository clientRegistrationRepository) выдает исключение { Строка base_uri = OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI; Резолвер DefaultOAuth2AuthorizationRequestResolver = новый DefaultOAuth2AuthorizationRequestResolver (clientRegistrationRepository, base_uri); resolver.setAuthorizationRequestCustomizer(OAuth2AuthorizationRequestCustomizers.withPkce()); вернуть httpSecurity .authorizeHttpRequests(c -> { // разрешаем кому-либо попасть на страницы ошибок c.dispatcherTypeMatchers(DispatcherType.ERROR).permitAll(); // разрешаем все URL-адреса с чванством c.requestMatchers(SWAGGER_URLS).permitAll(); // требовать аутентификацию во всех остальных случаях c.anyRequest().аутентифицированный(); }) .oauth2Login(c -> { c.authorizationEndpoint(auth -> auth.authorizationRequestResolver(resolver)); // используем PKCE }) .строить(); } // SpringHttpFirewall по умолчанию слишком строг @Бин общественный HttpFirewall getHttpFirewall() { StrictHttpFirewall strictHttpFirewall = новый StrictHttpFirewall(); strictHttpFirewall.setAllowUrlEncodedDoubleSlash (истина); вернуть строгийHttpFirewall; } @Бин общественный PasswordEncoder парольEncoder () { вернуть новый BCryptPasswordEncoder(); } } (соответствующие) application.properties:
# GitHub OAuth2 Spring.security.oauth2.client.registration.github.client-id=${GITHUB_CLIENT_ID} Spring.security.oauth2.client.registration.github.client-secret=${GITHUB_CLIENT_SECRET} Spring.security.oauth2.client.registration.github.scope=пользователь:прочитать Итак, по умолчанию я заметил, что Spring пройдет всю схему авторизации OAuth2, а затем в ответ на обратный вызов (redirect uri) добавит Set-Cookie с в нем JSESSIONID. Это управление сеансами с отслеживанием состояния, и оно по умолчанию сохраняет все данные, относящиеся к пользователю, на карте или в чем-то другом в памяти по предоставленному jsessionid.
Мне это не нравится по двум причинам:
[*]
Сеансы, хранящиеся в памяти, конечно, будут удалены, если приложение по какой-либо причине закроется. Это можно исправить, сохранив информацию о сеансе в базе данных или используя Redis, но тогда для каждого авторизованного HTTP-запроса требуется дополнительный запрос к базе данных для получения соответствующей информации о сеансе.
[*]
Аутентификация/авторизация на основе файлов cookie, как правило, уязвима для атак CSRF, поскольку все файлы cookie отправляются вместе с любым запросом, сделанным для домена, для которого хранится файл cookie. Это не меняется при использовании https: в этом случае файлы cookie просто шифруются, но отправляются все равно. Наличие чего-то вроде схемы на основе заголовка авторизации означает, что любой случайный запрос к API не будет просто волшебным образом аутентифицирован, для этого требуется некоторый Javascript во внешнем интерфейсе, чтобы фактически прикрепить этот заголовок.
Я хочу решить обе эти проблемы, используя токены JWT, указанные в заголовке авторизации, вместо JSESSIONID. Я хочу это сделать: в ответе на обратный вызов из моего приложения я хотел бы предоставить заголовок вместе с токеном JWT, который я генерирую после того, как отправлю код авторизации в службу аутентификации и получу обратно токен доступа. . Примечание. JWT, который я предоставляю браузеру, не будет таким же, как токен доступа, который я получаю от службы аутентификации. Это будет где-то сохранено (база данных, redis, w/e) для последующего использования при необходимости.
Это примерно то, чего я пытаюсь достичь. Пожалуйста, если кто-нибудь делал это раньше или имеет соответствующую информацию/статьи/документацию о том, как это сделать, я был бы очень признателен. Спасибо.