Вопрос или проблема
Я работаю с микросервисной архитектурой, где моя API-GATEWAY работает на порту 9090
, а сервис входа работает на порту 8082
.
Итак, проблема в следующем: когда я пытаюсь аутентифицироваться с помощью Google OAuth, запрос корректно передается в сервис входа, но сервис входа рассматривает его как статический ресурс для этого URL-адреса входа Google OAuth.
package com.example.login.Security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.example.login.Service.CustomUserService;
import com.example.login.oauth.config.OAuth2LoginFailureHandler;
import com.example.login.oauth.config.OAuth2LoginSuccessHandler;
import jakarta.servlet.http.HttpServletRequest;
@Configuration
public class AppConfig {
@Autowired
private JwtAuthenticationEntryPoint authenticationEntryPoint;
@Autowired
private JwtTokenValidattor jwtTokenValidator;
@Autowired
private CustomUserService customUserService;
@Autowired
private OAuth2LoginSuccessHandler oAuth2LoginSuccessHandler;
@Autowired
private OAuth2LoginFailureHandler oAuth2LoginFailureHandler;
@Autowired
private BCryptPasswordEncoder passwordEncoder;
private final String[] PUBLIC_URL = { "/login/jwt", "/login/register", "/login/api/payment/create",
"/login/api/payment/update", "/swagger-ui.html", "/swagger-ui/**", "/v3/api-docs/**", "/user/fetch/qrdata",
"/oauth2/**", "/login/oauth2/**", "/login/oauth2/authorization/google" };
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.cors(Customizer.withDefaults()).csrf(csrf -> csrf.disable())
.authorizeHttpRequests(
(auth) -> auth.requestMatchers(PUBLIC_URL).permitAll().anyRequest().authenticated())
.oauth2Login(oauth -> oauth.successHandler(oAuth2LoginSuccessHandler)
.failureHandler(oAuth2LoginFailureHandler))
.exceptionHandling((ex) -> ex.authenticationEntryPoint(this.authenticationEntryPoint))
.sessionManagement((s) -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
http.authenticationProvider(authenticationProvider());
http.addFilterBefore(this.jwtTokenValidator, UsernamePasswordAuthenticationFilter.class);
http.addFilterBefore((request, response, chain) -> {
if (request instanceof HttpServletRequest) {
HttpServletRequest httpRequest = (HttpServletRequest) request;
System.out.println("URL запроса : " + httpRequest.getRequestURI());
}
chain.doFilter(request, response);
}, UsernamePasswordAuthenticationFilter.class);
DefaultSecurityFilterChain defaultSecurityFilterChain = http.build();
return defaultSecurityFilterChain;
}
@Bean
public AuthenticationManager authenticationManagerBean(AuthenticationConfiguration authenticationConfiguration)
throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setUserDetailsService(this.customUserService);
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
return daoAuthenticationProvider;
}
@Bean
public OidcUserService oidService() {
return new OidcUserService();
}
}
package com.example.login.oauth.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import com.example.login.Security.JWTConstant;
@Configuration
public class OAuth2ClientConfig {
@Value("${app.base-url}")
private String baseUrl;
@Bean
public ClientRegistrationRepository clientRegistrationRepository() {
return new InMemoryClientRegistrationRepository(this.googleClientRegistration());
}
private ClientRegistration googleClientRegistration() {
return ClientRegistration.withRegistrationId(JWTConstant.GOOGLE_REGISTRATION_ID)
.clientId(JWTConstant.GOOGLE_CLIENT_ID)
.clientSecret(JWTConstant.GOOGLE_CLIENT_SECRET)
.redirectUri(baseUrl + JWTConstant.GOOGLE_REDIRECT_URI_SUFFIX)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.scope(JWTConstant.GOOGLE_SCOPE)
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST)
.authorizationUri(JWTConstant.GOOGLE_AUTHORISATION_URL)
.tokenUri(JWTConstant.GOOGLE_TOKEN_URI)
.userInfoUri(JWTConstant.GOOGLE_USER_INFO_URI)
.userNameAttributeName(JWTConstant.ATTRIBUTE_NAME)
.clientName(JWTConstant.GOOGLE_CLIENT_NAME)
.build();
}
}
Выше я поделился всей конфигурацией oauth и конфигурацией безопасности, где я правильно включил вход с помощью oauth2, но все равно сталкиваюсь с проблемой, которая ниже---->
URL запроса : /login/oauth2/authorization/google
2024-10-08T16:42:54.705+05:30 DEBUG 21452 --- [login-service] [nio-8082-exec-2] o.s.web.servlet.DispatcherServlet : GET "/login/oauth2/authorization/google", параметры={}
2024-10-08T16:42:54.717+05:30 DEBUG 21452 --- [login-service] [nio-8082-exec-2] o.s.w.s.handler.SimpleUrlHandlerMapping : Сопоставлено с ResourceHttpRequestHandler [classpath [META-INF/resources/], classpath [resources/], classpath [static/], classpath [public/], ServletContext [/]]
2024-10-08T16:42:54.732+05:30 DEBUG 21452 --- [login-service] [nio-8082-exec-2] o.s.w.s.r.ResourceHttpRequestHandler : Ресурс не найден
2024-10-08T16:42:54.737+05:30 DEBUG 21452 --- [login-service] [nio-8082-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Разрешено [org.springframework.web.servlet.resource.NoResourceFoundException: No static resource login/oauth2/authorization/google.]
2024-10-08T16:42:54.738+05:30 DEBUG 21452 --- [login-service] [nio-8082-exec-2] o.s.web.servlet.DispatcherServlet : Завершено 404 NOT_FOUND
Ответ или решение
Проблема, с которой вы столкнулись, заключается в том, что Spring Security не обрабатывает ваш запрос на аутентификацию через Google OAuth как ожидается, а вместо этого воспринимает его как запрос на статический ресурс. Вот несколько шагов, которые помогут вам решить эту проблему.
1. Убедитесь, что правильные URL-адреса разрешены
В вашем конфигурационном классе безопасности (AppConfig
), вы указали массив PUBLIC_URL
, который включает паттерны, связанные с OAuth2. Убедитесь, что в этом массиве прописан корректный путь:
private final String[] PUBLIC_URL = {
"/login/jwt",
"/login/register",
"/login/api/payment/create",
"/login/api/payment/update",
"/swagger-ui.html",
"/swagger-ui/**",
"/v3/api-docs/**",
"/user/fetch/qrdata",
"/oauth2/**", // Убедитесь, что этот паттерн тут
"/login/oauth2/**", // Это тоже должно быть
"/login/oauth2/authorization/google" // И это тоже
};
2. Настройте маршрутизацию запросов
Вам необходимо убедиться, что ваши запросы поступают в нужный контроллер, а не обрабатываются как статические ресурсы. Для этого добавьте в код мэппинг для обработки запросов OAuth:
http.authorizeHttpRequests(auth ->
auth.requestMatchers(PUBLIC_URL).permitAll()
.anyRequest().authenticated()
);
Эта часть кода должна быть corretamente настроена, чтобы разрешить доступ к /login/oauth2/authorization/google
.
3. Настройте контроллеры для обработки запросов
Если запросы все еще обрабатываются неправильно, убедитесь, что у вас существует контроллер, который может обрабатывать эти запросы. Если вы используете Spring Security с OAuth2, вы можете использовать стандартный механизм, предоставляемый Spring, чтобы обрабатывать OAuth2 запросы. Например:
@RestController
@RequestMapping("/login")
public class LoginController {
@GetMapping("/oauth2/authorization/google")
public String redirectGoogle() {
// Логика для обработки редиректа
return "redirect:/oauth2/authorization/google";
}
}
4. Проверьте настройки Redirection URL
В конфигурации OAuth у вас есть следующее:
.redirectUri(baseUrl + JWTConstant.GOOGLE_REDIRECT_URI_SUFFIX)
Убедитесь, что JWTConstant.GOOGLE_REDIRECT_URI_SUFFIX
корректен и совпадает с тем, что вы указали в консоли разработчика Google.
5. Логи и отладка
Если после всех настроек проблема остается, просмотрите логи более детально. Возможно, что сервер не видит ваши настройки или есть какой-то конфликт с другими конфигурациями. Включите режим отладки, чтобы посмотреть, как Spring обрабатывает входящие запросы.
Вы можете добавить следующее в ваш файл application.properties
:
logging.level.org.springframework=DEBUG
6. Зависимости и версии
Также проверьте, что версии ваших зависимостей Spring Boot и Spring Security соответствуют друг другу и поддерживают функциональность, которую вы используете.
Заключение
Эти шаги должны помочь вам устранить проблему с обработкой запросов OAuth2 в вашем сервисе аутентификации. Если проблема все еще не решена, вам может понадобиться предоставить больше информации о конфигурации вашего приложения и любые связанные запросы, которые вы делаете.