Размещенный сервер авторизации не перенаправляет на локальный клиент - PullRequest
0 голосов
/ 13 октября 2018

Итак, я следовал руководству здесь для реализации Spring Authorization Server.Мне удалось подготовить клиент и сервер к тестированию.Причина, по которой мне нужен сервер авторизации, заключается в том, что мне нужно иметь возможность аутентифицировать несколько микросервисов, которые работают вместе.

Я запустил сервер и клиент на своем компьютере.Сервер авторизации на localhost:9999 и клиент на localhost:8080/client (установка пути контекста клиентского приложения в / client).Аутентификация для клиента отлично работает в этом сценарии.Чтобы сделать это проще, я решил разместить сервер авторизации в AWS, используя Elastic Beanstalk.Для обеспечения секретности я буду использовать SERVER_URL в качестве URL-адреса размещенного сервера авторизации.

После размещения сервера я запускаю клиент с помощью размещенного сервера авторизации с правильными токенами и URL-адресами авторизации.Как только я перехожу на localhost:8080, меня перенаправляют на SERVER_URL, где на главной странице отображается ссылка для входа в Google OAuth.При нажатии на эту ссылку я перехожу на страницу входа в Google, и я захожу в свою учетную запись Google.После входа в Google он перенаправляет обратно на SERVER_URL/login?code=the_code&state=the_state.Это не то, что я хочу.После входа в Google пользователь должен быть перенаправлен обратно на localhost:8080/login?code=the_code&state=the_state.

Я исследовал несколько дней, но, похоже, не могу найти решение этой проблемы.Мне нужно иметь возможность тестировать несколько микросервисов на локальном хосте с размещенным сервером.

Класс основного приложения моего сервера авторизации по умолчанию (я ничего не добавил).Вот моя конфигурация безопасности:

@Configuration
@EnableWebSecurity
@EnableOAuth2Client
@EnableAuthorizationServer
@Order(200)
public class OAuthSecurityConfiguration extends WebSecurityConfigurerAdapter {

    private final String GOOGLE_LOGIN_FILTER = "/login/google";

    @Autowired
    OAuth2ClientContext oauth2ClientContext;

    @Bean
    @ConfigurationProperties("google")
    public ClientResources google() {
        return new ClientResources();
    }

    private Filter ssoFilter() {
        return ssoFilter(google(), GOOGLE_LOGIN_FILTER);
    }

    private Filter ssoFilter(ClientResources client, String path) {
        OAuth2ClientAuthenticationProcessingFilter googleFilter = new OAuth2ClientAuthenticationProcessingFilter(GOOGLE_LOGIN_FILTER);
        OAuth2RestTemplate googleTemplate = new OAuth2RestTemplate(client.getClient(), oauth2ClientContext);
        googleFilter.setRestTemplate(googleTemplate);

        UserInfoTokenServices tokenServices = new UserInfoTokenServices(client.getResource().getUserInfoUri(), client.getClient().getClientId());
        tokenServices.setRestTemplate(googleTemplate);
        googleFilter.setTokenServices(tokenServices);

        return googleFilter;
    }

    @Bean
    public FilterRegistrationBean<OAuth2ClientContextFilter> oauth2ClientFilterRegistration(OAuth2ClientContextFilter filter) {
        FilterRegistrationBean<OAuth2ClientContextFilter> registration = new FilterRegistrationBean<OAuth2ClientContextFilter>();
        registration.setFilter(filter);
        registration.setOrder(-100);
        return registration;
    }

    /**
     * Specify the authorization criteria for request access.
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/**")
            .authorizeRequests()
            .anyRequest()
            .authenticated()
            .and()
            .exceptionHandling()
            .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/"))
            .and()
            .logout()
            .logoutSuccessUrl("/")
            .permitAll()
            .and()
            .addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class)
            .csrf()
            .disable();
    }

}

class ClientResources {
    @NestedConfigurationProperty
    private AuthorizationCodeResourceDetails client = new AuthorizationCodeResourceDetails();

    @NestedConfigurationProperty
    private ResourceServerProperties resource = new ResourceServerProperties();

    public AuthorizationCodeResourceDetails getClient() {
        return client;
    }

    public ResourceServerProperties getResource() {
        return resource;
    }
}

Тогда у меня есть отдельный класс для защиты пути "/ me":

@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/me")
            .authorizeRequests()
            .anyRequest()
            .authenticated();
    }

}

И мой application.yml для сервера аутентификации:

spring:
    mvc:
        view:
            prefix: /WEB-INF/jsp/
            suffix: .jsp

server:
    port: ${PORT:9999}
    error:
        whitelabel:
            enabled: false

security:
    oauth2:
        client:
            client-id: google client id
            client-secret: google client secret
            scope: read,write
            auto-approve-scopes: '.*'

google:
    client:
        clientId: google client id
        clientSecret: google client secret
        accessTokenUri: https://oauth2.googleapis.com/token
        userAuthorizationUri: https://accounts.google.com/o/oauth2/auth
        clientAuthenticationScheme: form
        scope:
            - openid
            - profile
            - email
    resource:
        userInfoUri: https://www.googleapis.com/oauth2/v3/userinfo
        preferTokenInfo: true

Контроллер для пути "/ me" тривиален, поэтому я не буду его здесь включать.И да, я использую один и тот же идентификатор клиента Google и секретный ключ для Google и самого сервера (пока).

Теперь на стороне моего клиента application.yml:

authorization-server-url: SERVER_URL

security:
    oauth2:
        client:
            clientId: google client id
            clientSecret: google client secret
            accessTokenUri: ${authorization-server-url}/oauth/token
            userAuthorizationUri: ${authorization-server-url}/oauth/authorize
        resource:
            userInfoUri: ${authorization-server-url}/me

И конфигурация безопасности на моей стороне клиента использует @Configurable, @EnableWebSecurity и @ EnableOAuth2SSO.Конфигурация безопасности предотвращает доступ неаутентифицированных пользователей, поэтому, как только я захожу на localhost: 8080, он перенаправляет меня на сервер аутентификации.

Сервер аутентификации, когда он используется сам по себе, успешно входит в Google.И если клиентское приложение на localhost: 8080 настроено для проверки подлинности с помощью Google OAuth напрямую, а не на настраиваемом сервере аутентификации, то это выполняется успешно.Проблема заключается в правильном перенаправлении после того, как сервер авторизации вошел в систему с Google.

Просто чтобы уточнить, я после потока localhost:8080 -> сервер аутентификации -> нажмите ссылку, которая приведет вас к SERVER_URL/login/google -> Войти через Google -> localhost:8080.Но я получаю localhost:8080 -> сервер авторизации -> ссылку для перехода на SERVER_URL/login/google -> Войти через Google -> SERVER_URL/login?code=the_code&state=the_s tate.

Заранее спасибо.

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

Вот моя конфигурация gradle:

buildscript {
    ext {
        springBootVersion = '2.0.5.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse-wtp'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'war'

group = this is a secret
version = '0.0.4-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

configurations {
    providedRuntime
}

ext {
    springCloudVersion = 'Finchley.SR1'
}

dependencies {
    implementation('org.springframework.boot:spring-boot-starter-security')
    implementation('org.springframework.boot:spring-boot-starter-web')
    implementation('org.springframework.cloud:spring-cloud-starter-oauth2')
    implementation('javax.servlet:jstl')
    implementation('org.apache.tomcat.embed:tomcat-embed-jasper')
    providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')
    testImplementation('org.springframework.boot:spring-boot-starter-test')
    testImplementation('org.springframework.security:spring-security-test')
}

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}

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

Страница ошибкиЯ получаю по адресу http://<SERVER_URL>/login?code=xgYiHr&state=Wp1SUW, где <SERVER_URL> - доменное имя сервера авторизации.И я получаю следующую страницу ошибки:

Error Page

И сетевой трафик для страницы ошибки.В соответствии с этим, http://<SERVER_URL>/oauth/authorize имеет правильный redirect_uri, который равен http://localhost:8080/login, но когда дело доходит до перенаправления на него, URL localhost:8080 заменяется на <SERVER_URL>:

enter image description here

Забавно, я только что попробовал запустить клиентское приложение через http://127.0.0.1:8080 вместо http://localhost:8080, и оно отлично работает!Не уверен, почему localhost:8080 заменяется на <SERVER_URL>.Я не уверен, что это проблема с AWS или Spring.

1 Ответ

0 голосов
/ 17 октября 2018

Кажется, я был прав, думая, что что-то не так с моей настройкой AWS.Я изменил среду в Elastic Beanstalk, чтобы использовать Nginx в качестве прокси-сервера, что решило мою проблему.Теперь я могу проверить мой клиент, используя localhost вместо 127.0.0.1.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...