因此,我已经按照指南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>
是授权服务器的域名。我得到以下错误页面:
错误页面的网络流量。据此,http://<SERVER_URL>/oauth/authorize
具有正确的redirect_uri
,即http://localhost:8080/login
,但是当涉及到重定向时,localhost:8080
url被替换为<SERVER_URL>
:< / p>
有趣的是,我只是尝试通过http://127.0.0.1:8080
而不是http://localhost:8080
来运行客户端应用程序,它运行良好!不知道为什么localhost:8080
被<SERVER_URL>
取代。我不确定是AWS还是Spring问题。
答案 0 :(得分:0)
似乎我认为我的AWS设置有问题是正确的。我将Elastic Beanstalk中的环境更改为使用Nginx作为代理服务器,从而解决了我的问题。现在,我可以使用localhost
而不是127.0.0.1
来测试客户端了。