托管授权服务器不会重定向到本地主机客户端

时间:2018-10-13 06:48:26

标签: java spring amazon-web-services spring-boot spring-security

因此,我已经按照指南here来实现Spring Authorization Server。我设法使客户端和服务器都准备好进行测试。我需要和授权服务器的原因是,我需要能够认证可一起使用的多个微服务。

我已经在我的机器上同时运行了服务器和客户端。授权服务器位于localhost:9999,客户端位于localhost:8080/client(将客户端应用上下文路径设置为/ client)。在这种情况下,客户端的身份验证可以正常工作。为了简化此过程,我决定使用Elastic Beanstalk在AWS上托管授权服务器。为了保密起见,我将使用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

我已经研究了几天,但似乎找不到解决此问题的方法。我需要能够使用托管服务器在localhost上测试多个微服务。

我的授权服务器主应用程序类是默认的(我没有添加任何东西)。这是我的安全配置:

@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客户端ID和密码(暂时)。

现在在我的客户端,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:

我得到的错误页面位于URL http://<SERVER_URL>/login?code=xgYiHr&state=Wp1SUW,其中<SERVER_URL>是授权服务器的域名。我得到以下错误页面:

Error Page

错误页面的网络流量。据此,http://<SERVER_URL>/oauth/authorize具有正确的redirect_uri,即http://localhost:8080/login,但是当涉及到重定向时,localhost:8080 url被替换为<SERVER_URL>:< / p>

enter image description here

有趣的是,我只是尝试通过http://127.0.0.1:8080而不是http://localhost:8080来运行客户端应用程序,它运行良好!不知道为什么localhost:8080<SERVER_URL>取代。我不确定是AWS还是Spring问题。

1 个答案:

答案 0 :(得分:0)

似乎我认为我的AWS设置有问题是正确的。我将Elastic Beanstalk中的环境更改为使用Nginx作为代理服务器,从而解决了我的问题。现在,我可以使用localhost而不是127.0.0.1来测试客户端了。