我使用Spring Boot 1.5.13以及Spring Security 4.2.6和Spring Security oAuth2 2.0.15。
我想为我们的Spring Boot应用程序找到最佳实践设置,这些应用程序提供一组混合内容:一个REST API,以及一些提供便利性和着陆页面的网页。对于有一些链接的开发人员,加上基于Swagger的API文档,这也是Web内容。
我有一个允许我使用适当的授权代码流运行应用程序的配置,因此我可以通过浏览器访问所有Web内容并通过配置的IdP(在我的情况下为PingFederate)进行身份验证,此外我可以从在浏览器中,即直接或与REST客户端,例如使用RESTClient。
这是我的安全配置:
@Slf4j
@Configuration
@EnableWebSecurity
@EnableOAuth2Sso // this annotation must stay here!
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login**", "/webjars/**", "/css/**").permitAll()
.antMatchers("/cfhealth").permitAll()
.antMatchers("/").permitAll()
.antMatchers("/protected", "/api/**").authenticated();
}
@Bean
public RequestContextListener requestContextListener() {
return new RequestContextListener();
}
}
和oAuth2配置:
@Configuration
@Slf4j
public class OAuth2Config extends ResourceServerConfigurerAdapter {
@Value("${pingfederate.pk-uri}")
String pingFederatePublicKeyUri;
@Autowired
PingFederateKeyUtils pingFederateKeyUtils;
@Override
public void configure(ResourceServerSecurityConfigurer config) {
config.tokenServices(tokenServices());
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
String certificate = pingFederateKeyUtils.getKeyFromServer(pingFederatePublicKeyUri);
String publicKey = pingFederateKeyUtils.extractPublicKey(certificate);
converter.setVerifier(pingFederateKeyUtils.createSignatureVerifier(publicKey));
return converter;
}
@Bean
@Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
return defaultTokenServices;
}
}
但是,当我想以编程方式/在浏览器外部使用标头中的承载令牌调用REST API时,例如使用curl,授权代码流启动并重定向到本地登录端点。我想要的是API调用接受承载令牌进行身份验证,而不创建会话,并且浏览器中的所有Web内容/ mvc调用都会建立会话。
curl -i -H "Accept: application/json" -H "Authorization: Bearer $TOKEN" -X GET http://localhost:8080/authdemo/api/hello
将@EnableResourceServer注释添加到上面的SecurityConfig类中(并在应用程序属性文件中添加security.oauth2.resource.filter-order = 3,我可以使curl命令工作,但随后授权代码流被破坏,我在浏览器中为我的应用程序中的所有URL获得以下输出:
<oauth>
<error_description>
Full authentication is required to access this resource
</error_description>
<error>unauthorized</error>
</oauth>
现在有办法让这个szenario很好地工作吗?如果是的话,那会是什么样子?或者仅在Spring Boot + Security + oAuth2的更高版本中支持它?
Spring Boot with Security OAuth2 - how to use resource server with web login form?的问题非常相似
答案 0 :(得分:1)
我找到了解决方案:它需要多个HttpSecurity配置。我通过阅读Matt Raible在https://developer.okta.com/blog/2018/02/13/secure-spring-microservices-with-oauth写的伟大文章找到了他,他向我介绍了requestMatchers(。)的概念。这就是我最终实现它的方式:
compileSdkVersion 28
defaultConfig {
applicationId "com.austurn.keikonew.keiko"
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
通过这种方式,我可以使用浏览器访问该服务,从而获得授权代码流。但访问API(或实际上是服务的任何部分)会导致验证提供的承载令牌。
为了说明在这种情况下如何将某些端点排除/公开的方式,这里是我如何配置执行器端点以及我自己添加的一个非常简单的“ping”端点:
@Configuration
@EnableResourceServer
@EnableWebSecurity(debug = true)
@EnableOAuth2Sso
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Bean
public RequestContextListener requestContextListener() {
return new RequestContextListener();
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.requestMatcher(new RequestHeaderRequestMatcher("Authorization"))
.authorizeRequests().anyRequest().fullyAuthenticated();
}
}
我的/ cfhealth端点的实现:
@Configuration
@Order(1)
public class ActuatorSecurity extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatcher(new OrRequestMatcher(EndpointRequest.to("health", "info"),
new AntPathRequestMatcher("/cfhealth"))).authorizeRequests().anyRequest().permitAll();
}
}
我很高兴向其他人学习,如果这是Spring Security配置的最佳实践方式,或者有更好的方法可以做到这一点。在过去的几周里,我花了很多时间研究这个主题,并且需要花费一些精力来掌握基本的Spring Security概念。