У меня есть размещенный сайт с Apache httpd (порты 80 и 443) и Wildfly 15 (порт 8080). Мой веб-сервер настроен для обработки http и https и настроен для связи с Wildfly с помощью этих команд.
ProxyPass / http://myhost.com:8080/
ProxyPassReverse / http://myhost.com:8080/
У меня есть приложение Java 11 Spring 5, развернутое в Wildfly в виде файла WAR. Он настроен на использование Google OAuth, чтобы пользователи могли проходить аутентификацию в моем приложении. Я пытаюсь использовать некоторые API YouTube, для которых требуется специальная «область действия», что означает наличие только https в моем списке «Авторизованные URI перенаправления». Однако мне нужно иметь «http://myhost.com:8080/login/oauth2/code/google» в этом списке прямо сейчас, чтобы пользователи могли успешно войти в систему, что нарушает требования API YouTube.
Я понимаю, почему в этом URI есть «http» и «8080», потому что запрос поступает из моего приложения, развернутого в Wildfly. Но мне нужно изменить его на «https://myhost.com/login/oauth2/code/google».
Как мне это сделать?
Ниже приведены некоторые дополнительные настройки, но, похоже, их недостаточно.
@PropertySource("classpath:application.properties")
@Configuration
@EnableWebSecurity
public class SecurityConfiguration
{
@Value("${spring.security.oauth2.client.registration.google.redirect-uri}")
private String redirectUri;
@Bean
public SecurityFilterChain filterChain(
HttpSecurity http) throws Exception
{
http.cors().and().csrf().disable()//
.authorizeRequests()//
.antMatchers("/secure/**").authenticated()//
.antMatchers("/api/**", "/login/**").permitAll()// for redirectUri
.antMatchers("/**").permitAll()//
.antMatchers("/logout").permitAll()//
.and()//
.sessionManagement()//
.sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
.and()//
.userDetailsService(userDetailsManager())//
.oauth2Login()// because we need to authorize our users, not just be a web client
//.oauth2Client()// not this
.redirectionEndpoint().baseUri(this.redirectUri)//
.and()//
.clientRegistrationRepository(this.securityService.getClientRegistrationRepository())//
.authorizedClientService(this.securityService.getAuthorizedClientService())//
.loginPage(SecurityController.LOGIN_PAGE_MAPPING)//
.defaultSuccessUrl(loginSuccessUrl)//
//.successHandler(this.loginSuccessHandler)//
.failureUrl("/login-failure-page")//
.and()//
.logout()//
.clearAuthentication(true)//
.invalidateHttpSession(true)//
.deleteCookies("JSESSIONID")//
.logoutSuccessUrl(SecurityController.LOGOUT_PAGE_MAPPING).permitAll()
// Gotta get back to the correct port after login.
.and()//
.requestCache().requestCache(requestCache()); // port mapper here
// For Firefox and h2-console
http.headers().frameOptions().disable();
return http.build();
}
}
application.properties:
spring.security.oauth2.client.registration.google.redirect-uri=https://myhost.com/login/oauth2/code/google
spring.security.oauth2.client.registration.google.redirectUri=https://myhost.com/login/oauth2/code/google
spring.security.oauth2.client.registration.google.preEstablishedRedirectUri=https://myhost.com/login/oauth2/code/google
spring.security.oauth2.client.use-current-uri=false
Я также определил это для CORS
@Bean
public WebMvcConfigurer corsConfigurer()
{
return new WebMvcConfigurer()
{
@Override
public void addCorsMappings(
CorsRegistry registry)
{
registry.addMapping("/**")//
.allowedOrigins(/*"http://myhost.com:8080",*/ "https://myhost.com",
"https://myhost.com:8080")//
.allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
}
};
}
Если я это сделаю, то при попытке запустить JavaScript на своем сайте я получу сообщение «CORS Missing Allow Origin/Invalid CORS request».
CSRF и CORS — это разные механизмы безопасности, решающие разные угрозы. Активация защиты CSRF не должна вызывать проблем с CORS, вы должны были изменить несколько вещей одновременно.
да, было что-то еще, что было причиной этого. Нашёл и исправил это. Все еще нужна помощь по основной проблеме.




Вы можете обслуживать свое приложение Spring Boot с помощью SSL, используя свойства server.ssl.
Если у вас еще нет сертификата для myhost.com (например, в вашей среде разработки), вы можете найти то, что я размещаю там, полезным для создания самозаверяющего SSL-сертификата и добавления его в свой файл JDK/JREs cacerts. Вы также найдете инструкции по добавлению этого сертификата в доверенные корневые сертификаты вашей ОС.
Если вы работаете с приложениями-сервлетами, я предлагаю вам использовать любой порт, кроме 8080 при использовании https.
Опция выше позволяет использовать https://myhost.com:8080 вместо http://myhost.com:8080 (но, как упоминалось выше, по историческим причинам использовать https://myhost.com:8443 в приложениях сервлетов было бы намного проще).
Если вы не хотите, чтобы трафик к вашему приложению Spring был защищен и хотите сохранить http://myhost.com:8080, вам необходимо настроить URI перенаправления кода авторизации на https://myhost.com/login/oauth2/code/google, как вы пытаетесь сделать в свойствах. Дело в том, что, поскольку вы предоставляете только часть своей конфигурации, мы не можем понять, почему это не работает.
Конфигурация, которую вы предоставляете, довольно запутана и небезопасна (например, приложения с входом OAuth2 подвергаются атакам CSRF, поэтому отключать защиту CSRF — большая ошибка). С помощью этого стартера, который я написал, ваша конфигурация может быть такой простой, как:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-addons-starter-oidc</artifactId>
<version>7.1.8</version>
</dependency>
@Configuration
@EnableMethodSecurity
public class SecurityConfig {
}
oauth2-redirect-socket: https://myhost.com
oauth2-issuer: https://accounts.google.com
oauth2-client-id: change-me.apps.googleusercontent.com
oauth2-client-secret: change-me
spring:
security:
oauth2:
client:
provider:
oauth2:
issuer-uri: ${oauth2-issuer}
registration:
authorization-code:
authorization-grant-type: authorization_code
client-id: ${oauth2-client-id}
client-secret: ${oauth2-client-secret}
provider: oauth2
scope:
- openid
- profile
- email
- offline_access
com:
c4-soft:
springaddons:
oidc:
ops:
- iss: ${oauth2-issuer}
# skipping issuer configuration which is not used in your case
client:
# this forces to build redirect URIs pointing to the SSL gateway
client-uri: ${oauth2-redirect-socket}
security-matchers:
- /**
permit-all:
# what is not listed below requires requests to be authorized
- /login/**
- /oauth2/**
- /
cors:
- path: "/**"
allowed-origin-patterns:
- ${oauth2-redirect-socket}
Если вы не хотите использовать «мой» стартер, обратитесь к этому параграфу README. Он содержит ссылки на руководства по написанию конфигурации безопасности самостоятельно.
У меня есть сертификат SSL для Apache. https сначала проходит через Apache через порт 443, а затем запросы передаются Wildfly.
тогда почему бы вам не настроить свой Spring OAuth2-клиент так, чтобы он давал URI обратного вызова, указывающий на https-сервер Apache, а не на себя?
Это именно то, с чем мне нужна помощь. Я пытался это сделать, но не нашел волшебной формулы. Вот почему я добавил в вопрос свою конфигурацию безопасности.
Вы имеете в виду что-то вроде того, что написано во втором абзаце руководства по входу в систему OAuth2 ?
Соответствует ли первая строка приведенного выше фрагмента файла application.properties тому, что говорится во втором абзаце? Если да, то да, я попробовал, и это не сработало.
Я показал всем свой код, который уже получил в Интернете. Это не работает. Я ищу кого-нибудь, кто укажет на места в моем коде и скажет: «Это неправильно, вот что правильно».
Ваша конфигурация запутана, а предоставленные вами фрагменты неполны. Например, там есть ссылка на this.redirectUri, но мы понятия не имеем, как это установлено. Также вы используете очень устаревшие свойства, а некоторые определены в формате double. Сделайте уборку.
Я добавил еще немного кода конфигурации. Кроме того, я новичок в Spring Security, и я собрал это со всех веб-страниц, которые смог найти, пытаясь использовать самые последние версии. Однако я так и не нашел страницу, скажем, специально для Spring Security 5, где бы упоминалось, какие вещи устарели, а какие новые. Если вы знаете о такой странице, пожалуйста, дайте мне знать.
У меня есть набор руководств на Github, но все они написаны с использованием Spring Boot 3/Security 6.
Спасибо за помощь. Я отмечаю ваш ответ как правильный, поскольку вы предоставили мне все подробности, но я добавлю еще один ответ, показывающий, как все сложилось.
Спасибо за голоса (думаю, вы попросили других людей из вашей команды тоже нажать стрелку вверх ;). Это заставило меня еще раз прочитать ответ и понять, что ссылки для написания конфы я не ставил без своего стартера. Я убежден, что этот стартер очень удобен, но я также считаю, что очень важно понимать, что он делает и что нужно сделать, чтобы отказаться, если вам когда-нибудь понадобится.
ага, а команда? лол, это сольная работа. Впервые использую OAuth2, Google API, Spotify API и, может быть, еще 1-2 впервые, которые я не могу вспомнить навскидку.
@ch4mp дал мне необходимую информацию, но я собираюсь рассказать здесь о том, что мне нужно было сделать, чтобы все заработало. Во-первых, я не думал о том, чтобы сделать Wildfly безопасным, но вы можете, и я это сделал. Моя хостинговая компания установила сертификаты с моего сервера Apache на Wildfly.
Затем я изменил свой файл конфигурации Apache, чтобы использовать это:
ProxyPass / https://hostname.com:8443/
ProxyPassReverse / https://hostname.com:8443/
но дополнительным изменением было добавление следующего, потому что без него ничего не работало.
SSLProxyEngine on
Мне все еще нужно очистить конфигурацию безопасности OAuth2, но ch4mp дал мне много работы. Я рассматриваю это как второстепенную проблему, связанную с получением URI перенаправления Oauth2 для использования https вместо http.
Отключать защиту CSRF при включенном
oauth2Login— очень плохая идея: запросы к вашему приложению авторизуются с помощью файлов cookie сеанса, что делает его уязвимым для атак CSRF.