领先一步
VMware 提供培训和认证,助您加速进步。
了解更多Spring Boot 1.3 中有一些关于 Spring Boot OAuth2 客户端和服务器以及 Spring Security OAuth2 的新功能。其中一些功能从 Spring Cloud Security 移植到了 Spring Boot,因此存在于 Spring Cloud 的 Angel release train 中,但不在 Brixton release train 中。本文帮助您了解这些更改并更新任何现有应用程序以使用新功能。
如果您不使用 Spring Cloud,则应该能够直接更改 Spring Boot 依赖项的版本号。由于一些 OAuth2 功能已从 Spring Cloud Security 迁移到 Spring Boot 1.3,因此事情可能比这稍微复杂一些。一篇单独的文章介绍了如何将 Spring Cloud 应用从 Spring Boot 1.2 升级到 1.3。如果您正在使用 Spring Cloud Angel 版本系列,则应参考该文章以了解如何管理依赖项(与任何特定功能无关)。
OAuth2 授权服务器最主要的功能是颁发访问令牌。为此,它必须能够对客户端应用和(可选)用户进行身份验证。
通过约定和 Spring Boot 1.3 中的一些配置属性,可以实现一个非常简单的 OAuth2 授权服务器,它只有一个客户端。因此,像 spring.io 的Angular JS Spring Securrity Tutorial 中那样简单的身份验证服务器可以大大简化。在 Spring Boot 1.2 中,我们有
@SpringBootApplication
@RestController
@EnableResourceServer
public class AuthserverApplication {
@Configuration
@EnableAuthorizationServer
protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Excep
endpoints.authenticationManager(authenticationManager);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("acme")
.secret("acmesecret")
.authorizedGrantTypes("authorization_code", "refresh_token",
"password")
.scopes("openid").autoApprove(true);
}
}
...
}
在 Spring Boot 1.3 中,我们只有
@SpringBootApplication
@RestController
@EnableResourceServer
@EnableAuthorizationServer
public class AuthserverApplication {
...
}
并在 application.properties 中
security.oauth2.client.clientId: acme
security.oauth2.client.clientSecret: acmesecret
security.oauth2.client.authorized-grant-types: authorization_code,refresh_token,password
security.oauth2.client.scope: openid
这是一个通用的授权服务器,非常适合演示,但在实践中不太现实,因为它只有一个客户端(“acme”)。尽管如此,作为快速开始使用 OAuth2 的方法,能够用很少的精力做这么多事情是很不错的。
要扩展基本示例并控制授权服务器功能,您只需要回到旧的 Spring Boot 1.2 版本(任何拥有自己的 AuthorizationServerConfigurer 的应用都会关闭自动配置的功能)。
资源服务器通过要求有效的访问令牌(由授权服务器创建)来保护其端点。
与授权服务器类似,资源服务器可以通过约定和 Spring Boot 1.3 中的一些配置属性来实现,也可以通过 Spring Boot 1.2 与 Spring Cloud Security 结合来实现。例如,可以参考 spring.io 的Angular JS Spring Security Tutorial中的简单资源服务器。
使用 Spring Boot 1.2 时,我们必须使用 Spring Cloud Security 来进行 @EnableOAuth2Resource 注解
@SpringBootApplication
@RestController
@EnableOAuth2Resource
class ResourceApplication {
...
}
并在 application.properties 中进行一些配置以帮助解码访问令牌
spring.oauth2.resource.userInfoUri: https://:9999/uaa/user
使用 Spring Boot 1.3 时,可以移除 Spring Cloud 依赖项,并将注解替换为 Spring Security OAuth2 中原生的 @EnableResourceServer 注解
@SpringBootApplication
@RestController
@EnableResourceServer
class ResourceApplication {
...
}
要完成应用,需要进行略有不同的配置(请注意,键前缀已从 spring.oauth2 更改为 security.oauth2)
security.oauth2.resource.userInfoUri: https://:9999/uaa/user
在 OAuth2 中,客户端是一个代理(通常是应用程序),它获取一个令牌,通常代表用户。可以通过拥有一个单一的授权服务器和支持的身份验证应用(即 OAuth2 客户端)来实现单点登录。
在 Spring Boot 1.3 中,客户端可以实现单点登录模式,只需一个注解和一些配置属性。如果您同时使用 Spring Cloud Security,则可以使用 Spring Boot 1.2 实现相同的功能。
使用 Spring Boot 1.2 和 Spring Cloud Angel 的一个非常通用的示例将使用一个单一的 @EnableOAuth2Sso 注解
@SpringBootApplication
@EnableOAuth2Sso
public class SsoApplication {
...
}
并在 application.yml(或等效的 application.properties)中为客户端进行一些配置。这是一个用于在 localhost:8080 上运行的应用,通过 Facebook 进行身份验证的示例
spring:
oauth2:
client:
clientId: 233668646673605
clientSecret: 33b17e044ee6a4fa383f46ec6e28ea1d
accessTokenUri: https://graph.facebook.com/oauth/access_token
userAuthorizationUri: https://#/dialog/oauth
tokenName: oauth_token
authenticationScheme: query
clientAuthenticationScheme: form
resource:
userInfoUri: https://graph.facebook.com/me
在 Spring Boot 1.3 中,同一个应用看起来几乎相同,但不再需要 Spring Cloud Security。此外,注解已移至不同的包,配置前缀也已更改。因此,移除 Cloud 依赖项,更改注解的导入,并将 application.yml 中的前缀从 spring 切换到 security 是迁移此应用所需的所有操作。
在 Spring Cloud Security 1.0(来自 Angel 版本系列)中,用户可以通过结合使用特殊的 **OAuth2ClientConfigurer** 回调和 spring.oauth2.sso.* 中的一些配置属性来定制请求匹配和访问规则。因此,例如,spring.io 的Angular JS Spring Security Tutorial中的原生客户端应用在 Spring Boot 1.2 中具有这种通用的实现模式
@SpringBootApplication
@EnableOAuth2Sso
public class UiApplication {
@Configuration
protected static class SecurityConfiguration extends OAuth2SsoConfigurerAdapter {
@Override
public void match(RequestMatchers matchers) {
matchers.anyRequest();
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/index.html", "/home.html", "/").permitAll()
.anyRequest().authenticated()
.and().csrf()
.csrfTokenRepository(csrfTokenRepository())
.and()
.addFilterAfter(csrfHeaderFilter(), CsrfFilter.class);
}
}
...
}
以及一个与原生示例类似的 application.yml
spring:
oauth2:
sso:
home:
secure: false
path: /,/**/*.html
client:
accessTokenUri: https://:9999/uaa/oauth/token
userAuthorizationUri: https://:9999/uaa/oauth/authorize
resource:
userInfoUri: https://:9999/uaa/user
在 Spring Boot 1.3 中,不再需要 Spring Cloud Security,并且自定义配置不需要过时的 OAuth2SsoConfigurerAdapter。相反,它们只需要与 @EnableOAuth2Sso 注解一起的常规 WebSecurityConfigurerAdapter 中的所有相同代码,再加上一个请求匹配器。
@SpringBootApplication
@EnableZuulProxy
@EnableOAuth2Sso
public class UiApplication extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**")
.authorizeRequests()
.antMatchers("/index.html", "/home.html", "/").permitAll()
.anyRequest().authenticated()
.and().csrf()
.csrfTokenRepository(csrfTokenRepository())
.and()
.addFilterAfter(csrfHeaderFilter(), CsrfFilter.class);
}
...
}
更新版本中的配置属性大多相同:前缀从 spring.oauth2 更改为 security.oauth2,并且不再需要 *.oauth2.sso.* 属性,因为它们由用户在 WebSecurityConfigurerAdapter 中显式配置。
spring.io 的Angular JS Spring Security Tutorial中的实际客户端应用与上面自定义的应用类似,但它也是一个 Zuul 代理,负责将来自浏览器客户端的请求转发到后端服务。在 Spring Boot 1.3 中,此应用仍然需要 Spring Cloud Security 来进行令牌中继(它希望将用于身份验证的访问令牌发送到后端资源),但不需要它进行基本的 SSO 功能,因此其实现与上一个示例相同,只是添加了一个 @EnableZuulProxy 注解。
注意:在撰写本文时,Spring Boot 1.3.0 中的一个 bug 导致了Angular JS Spring Security Tutorial中客户端应用的当前实现需要一个解决方法。该解决方法仅在使用 Spring Cloud Security 时才需要,并且在 Spring Boot 1.3.1 中将不再需要。
@Component @Order(Ordered.HIGHEST_PRECEDENCE) class WorkaroundRestTemplateCustomizer implements UserInfoRestTemplateCustomizer { public void customize(OAuth2RestTemplate template) { template.setInterceptors(new ArrayList<>(template.getInterceptors())); } }
在 Spring Boot 1.2 和 Angel 版本系列的 Spring Cloud Security 中,如果绑定到具有正确凭据的服务,应用可以自我配置为 OAuth2 SSO。例如,您可以创建如下的用户提供服务:
cf create-user-provided-service sso -p '{"userInfoUri":"https://uaa.run.pivotal.io/userinfo", "tokenUri":"login.run.pivotal.io/oauth/token", "authorizationUri":"login.run.pivotal.io/oauth/authorize", "clientId":"[client]", "clientSecret":"[secret]"}'
然后,与服务绑定的带有 @EnableOAuth2Sso 的应用将绑定 SSO 所需的配置,而无需用户更改任何配置。
Spring Boot 1.3 和 Spring Cloud Brixton 也提供了相同的功能,但不是使用 Spring Cloud Security,而是需要使用新的 spring-cloud-cloudfoundry-web 库来获取 SSO 配置绑定行为。您也可以使用 Cloud Foundry 内置的 SSO 服务而不是用户提供服务(在 Pivotal Web Services 中可用于选定的帐户,或在 Pivotal Cloud Foundry 中可用)。
如果您正在使用 Spring Boot,并且可能还使用 Spring Cloud 和 OAuth2,希望您现在能够顺利地从 Spring Boot 1.2 升级到 1.3,或者至少当您遇到障碍时,有一些工具可以帮助您思考发生了什么。Spring Boot 1.3 几乎拥有 Spring Cloud Security 1.0 的所有功能,因此您需要考虑的主要问题是依赖项。此外,Spring Boot 还提供了一些新功能,例如自动配置授权服务器。一如既往,您可以(也应该)使用默认行为,直到您需要更改它为止,届时应该没有障碍。
Spring Guides 中的示例应用现在都已更新到 Spring Boot 1.3,即使这意味着它们依赖于 Spring Cloud 的某个里程碑版本(这仅适用于 Zuul 代理示例)。许多应用不再需要 Spring Cloud。如果您需要 Spring Cloud 的 GA 版本,目前需要坚持使用 Spring Boot 1.2。该组合的示例可以从 Git 历史记录中提取。