Add SSO features
This commit is contained in:
25
pom.xml
25
pom.xml
@@ -14,7 +14,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>1.1.5.BUILD-SNAPSHOT</version>
|
||||
<version>1.1.5.RELEASE</version>
|
||||
<relativePath /> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.platform</groupId>
|
||||
<artifactId>spring-platform-netflix-core</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@@ -44,10 +45,27 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.cloudfoundry</groupId>
|
||||
<artifactId>spring-boot-cf-service-broker</artifactId>
|
||||
<version>2.3.1</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security.oauth</groupId>
|
||||
<artifactId>spring-security-oauth2</artifactId>
|
||||
<version>2.0.3.BUILD-SNAPSHOT</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.eureka</groupId>
|
||||
@@ -59,6 +77,11 @@
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.ant</groupId>
|
||||
<artifactId>ant-launcher</artifactId>
|
||||
<version>1.9.3</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.platform.cloudfoundry.broker;
|
||||
package org.springframework.platform.cloudfoundry.broker.configuration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -25,7 +25,7 @@ import org.cloudfoundry.community.servicebroker.model.Catalog;
|
||||
import org.cloudfoundry.community.servicebroker.model.ServiceDefinition;
|
||||
import org.cloudfoundry.community.servicebroker.service.BeanCatalogService;
|
||||
import org.cloudfoundry.community.servicebroker.service.CatalogService;
|
||||
import org.springframework.platform.netflix.eureka.advice.LeaseManagerLite;
|
||||
import org.springframework.platform.cloudfoundry.broker.FreeServiceDefinitionFactory;
|
||||
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import com.netflix.appinfo.InstanceInfo.ActionType;
|
||||
@@ -35,15 +35,14 @@ import com.netflix.eureka.lease.LeaseManager;
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class CatalogLeaseManager implements LeaseManager<InstanceInfo>, LeaseManagerLite,
|
||||
CatalogService {
|
||||
public class CatalogLeaseManager implements LeaseManager<InstanceInfo>, CatalogService {
|
||||
|
||||
private Map<String, ServiceDefinition> definitions = new HashMap<String, ServiceDefinition>();
|
||||
|
||||
private List<ServiceDefinition> values = new ArrayList<ServiceDefinition>();
|
||||
|
||||
public CatalogLeaseManager(InstanceInfo config) {
|
||||
register(config, false);
|
||||
register(config, 0, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -56,11 +55,6 @@ public class CatalogLeaseManager implements LeaseManager<InstanceInfo>, LeaseMan
|
||||
return new BeanCatalogService(getCatalog()).getServiceDefinition(serviceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(InstanceInfo info, boolean isReplication) {
|
||||
register(info, 0, isReplication);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(InstanceInfo info, int leaseDuration, boolean isReplication) {
|
||||
if (!definitions.containsKey(info.getAppName())) {
|
||||
@@ -102,7 +96,8 @@ public class CatalogLeaseManager implements LeaseManager<InstanceInfo>, LeaseMan
|
||||
|
||||
private ServiceDefinition getServiceDefinition(InstanceInfo info) {
|
||||
String name = info.getAppName().toLowerCase();
|
||||
ServiceDefinition definition = new FreeServiceDefinitionFactory("eureka-").create(name, "Eureka-brokered service");
|
||||
ServiceDefinition definition = new FreeServiceDefinitionFactory("eureka-")
|
||||
.create(name, "Eureka-brokered service");
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("info", (Object) info);
|
||||
map.put("uri", info.getHomePageUrl());
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.platform.cloudfoundry.broker;
|
||||
package org.springframework.platform.cloudfoundry.broker.configuration;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
@@ -41,9 +41,15 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.platform.netflix.eureka.EurekaRegistryAvailableEvent;
|
||||
import org.springframework.platform.netflix.eureka.advice.LeaseManagerLite;
|
||||
import org.springframework.platform.cloudfoundry.broker.FreeServiceDefinitionFactory;
|
||||
import org.springframework.platform.cloudfoundry.broker.ServiceInstanceBindingRepository;
|
||||
import org.springframework.platform.cloudfoundry.broker.ServiceInstanceRepository;
|
||||
import org.springframework.platform.cloudfoundry.broker.simple.SimpleServiceInstanceBindingRepository;
|
||||
import org.springframework.platform.cloudfoundry.broker.simple.SimpleServiceInstanceBindingService;
|
||||
import org.springframework.platform.cloudfoundry.broker.simple.SimpleServiceInstanceRepository;
|
||||
import org.springframework.platform.cloudfoundry.broker.simple.SimpleServiceInstanceService;
|
||||
import org.springframework.platform.netflix.eureka.advice.PiggybackMethodInterceptor;
|
||||
import org.springframework.platform.netflix.eureka.event.EurekaRegistryAvailableEvent;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
@@ -69,21 +75,21 @@ import com.netflix.eureka.lease.LeaseManager;
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@ComponentScan(basePackages = { "demo", "org.cloudfoundry.community.servicebroker" }, excludeFilters = {
|
||||
@ComponentScan(basePackages = { "org.cloudfoundry.community.servicebroker" }, excludeFilters = {
|
||||
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = BrokerApiVersionConfig.class),
|
||||
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = BeanCatalogService.class) })
|
||||
@ConditionalOnClass(ServiceInstanceRepository.class)
|
||||
@ConditionalOnClass({ServiceInstanceRepository.class, BrokerApiVersionConfig.class })
|
||||
@ConditionalOnWebApplication
|
||||
public class ServiceBrokerAutoConfiguration {
|
||||
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingClass(name="com.netflix.eureka.PeerAwareInstanceRegistry")
|
||||
@ConditionalOnMissingClass(name = "com.netflix.eureka.PeerAwareInstanceRegistry")
|
||||
@ConditionalOnMissingBean(CatalogService.class)
|
||||
protected static class CatalogConfiguration {
|
||||
|
||||
|
||||
@Autowired
|
||||
private BrokerProperties broker;
|
||||
|
||||
|
||||
@Bean
|
||||
public BeanCatalogService catalogService() {
|
||||
return new BeanCatalogService(catalog());
|
||||
@@ -97,10 +103,10 @@ public class ServiceBrokerAutoConfiguration {
|
||||
@Bean
|
||||
@ConfigurationProperties("cloudfoundry.service.definition")
|
||||
public ServiceDefinition serviceDefinition() {
|
||||
return new FreeServiceDefinitionFactory(broker.getPrefix()).create(broker.getName(),
|
||||
broker.getDescription());
|
||||
return new FreeServiceDefinitionFactory(broker.getPrefix()).create(
|
||||
broker.getName(), broker.getDescription());
|
||||
}
|
||||
|
||||
|
||||
@Component
|
||||
@ConfigurationProperties("cloudfoundry.server.broker")
|
||||
public static class BrokerProperties {
|
||||
@@ -108,21 +114,27 @@ public class ServiceBrokerAutoConfiguration {
|
||||
@Value("${spring.application.name:application}")
|
||||
private String name;
|
||||
private String description;
|
||||
|
||||
public String getPrefix() {
|
||||
return prefix==null ? name + "-" : prefix;
|
||||
return prefix == null ? name + "-" : prefix;
|
||||
}
|
||||
|
||||
public void setPrefix(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description == null ? "Singleton service app" : description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
@@ -158,7 +170,7 @@ public class ServiceBrokerAutoConfiguration {
|
||||
ProxyFactory factory = new ProxyFactory(
|
||||
PeerAwareInstanceRegistry.getInstance());
|
||||
factory.addAdvice(new PiggybackMethodInterceptor(leaseManager,
|
||||
LeaseManager.class, LeaseManagerLite.class));
|
||||
LeaseManager.class));
|
||||
factory.setProxyTargetClass(true);
|
||||
Field field = ReflectionUtils.findField(PeerAwareInstanceRegistry.class,
|
||||
"instance");
|
||||
@@ -13,9 +13,10 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.platform.cloudfoundry.broker;
|
||||
package org.springframework.platform.cloudfoundry.broker.simple;
|
||||
|
||||
import org.cloudfoundry.community.servicebroker.model.ServiceInstanceBinding;
|
||||
import org.springframework.platform.cloudfoundry.broker.ServiceInstanceBindingRepository;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.platform.cloudfoundry.broker;
|
||||
package org.springframework.platform.cloudfoundry.broker.simple;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -27,6 +27,7 @@ import org.cloudfoundry.community.servicebroker.service.CatalogService;
|
||||
import org.cloudfoundry.community.servicebroker.service.ServiceInstanceBindingService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.platform.cloudfoundry.broker.ServiceInstanceBindingRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
@@ -13,12 +13,13 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.platform.cloudfoundry.broker;
|
||||
package org.springframework.platform.cloudfoundry.broker.simple;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.cloudfoundry.community.servicebroker.model.ServiceInstance;
|
||||
import org.springframework.platform.cloudfoundry.broker.ServiceInstanceRepository;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.platform.cloudfoundry.broker;
|
||||
package org.springframework.platform.cloudfoundry.broker.simple;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.cloudfoundry.community.servicebroker.model.ServiceDefinition;
|
||||
import org.cloudfoundry.community.servicebroker.model.ServiceInstance;
|
||||
import org.cloudfoundry.community.servicebroker.service.ServiceInstanceService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.platform.cloudfoundry.broker.ServiceInstanceRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.platform.cloudfoundry.sso;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.actuate.autoconfigure.ManagementServerProperties;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
||||
import org.springframework.boot.context.embedded.FilterRegistrationBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.context.annotation.ScopedProxyMode;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext;
|
||||
import org.springframework.security.oauth2.client.OAuth2RestOperations;
|
||||
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
|
||||
import org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter;
|
||||
import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter;
|
||||
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
|
||||
import org.springframework.security.oauth2.client.token.AccessTokenRequest;
|
||||
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
|
||||
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
|
||||
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
|
||||
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.logout.LogoutHandler;
|
||||
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnExpression("'${cloudfoundry.sso.tokenUri:${vcap.services.sso.credentials.tokenUri:}}'!=''")
|
||||
@ConditionalOnClass({ EnableOAuth2Client.class, SecurityProperties.class })
|
||||
@ConditionalOnWebApplication
|
||||
@EnableOAuth2Client
|
||||
@EnableConfigurationProperties(CloudfoundrySsoProperties.class)
|
||||
public class CloudfoundrySsoConfiguration {
|
||||
|
||||
@Autowired
|
||||
private CloudfoundrySsoProperties sso;
|
||||
|
||||
@Resource
|
||||
@Qualifier("accessTokenRequest")
|
||||
private AccessTokenRequest accessTokenRequest;
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean oauth2ClientFilterRegistration(
|
||||
OAuth2ClientContextFilter filter) {
|
||||
FilterRegistrationBean registration = new FilterRegistrationBean();
|
||||
registration.setFilter(filter);
|
||||
registration.setOrder(0);
|
||||
return registration;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public OAuth2ProtectedResourceDetails remote() {
|
||||
AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
|
||||
// set up resource details, OAuth2 URLs etc.
|
||||
details.setClientId(sso.getClientId());
|
||||
details.setClientSecret(sso.getClientSecret());
|
||||
details.setAccessTokenUri(sso.getTokenUri());
|
||||
details.setUserAuthorizationUri(sso.getAuthorizationUri());
|
||||
return details;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
|
||||
public OAuth2RestOperations restTemplate() {
|
||||
return new OAuth2RestTemplate(remote(), new DefaultOAuth2ClientContext(
|
||||
accessTokenRequest));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
protected static class SsoSecurityConfigurer extends WebSecurityConfigurerAdapter
|
||||
implements Ordered {
|
||||
|
||||
@Autowired
|
||||
private OAuth2ProtectedResourceDetails remote;
|
||||
|
||||
@Autowired
|
||||
private CloudfoundrySsoProperties sso;
|
||||
|
||||
@Autowired
|
||||
private OAuth2RestOperations restTemplate;
|
||||
|
||||
private List<CloudfoundrySsoConfigurer> configurers = Collections.emptyList();
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
if (ClassUtils
|
||||
.isPresent(
|
||||
"org.springframework.boot.actuate.autoconfigure.ManagementServerProperties",
|
||||
null)) {
|
||||
return ManagementServerProperties.ACCESS_OVERRIDE_ORDER;
|
||||
}
|
||||
return SecurityProperties.ACCESS_OVERRIDE_ORDER;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param configurers the configurers to set
|
||||
*/
|
||||
@Autowired(required = false)
|
||||
public void setConfigurers(List<CloudfoundrySsoConfigurer> configurers) {
|
||||
this.configurers = configurers;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
|
||||
http.addFilterAfter(cloudfoundrySsoFilter(),
|
||||
AbstractPreAuthenticatedProcessingFilter.class);
|
||||
|
||||
for (CloudfoundrySsoConfigurer configurer : configurers) {
|
||||
// Delegates can add authorizeRequests() here
|
||||
configurer.configure(http);
|
||||
}
|
||||
if (configurers.isEmpty()) {
|
||||
// Add anyRequest() last as a fall back. Spring Security would replace an
|
||||
// existing anyRequest() matcher with this one, so to avoid that we only
|
||||
// add it if the user hasn't configured anything.
|
||||
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry requests = http
|
||||
.antMatcher("/**").authorizeRequests();
|
||||
if (!sso.getHome().isSecure()) {
|
||||
requests.antMatchers(sso.getHome().getPath()).permitAll();
|
||||
}
|
||||
requests.anyRequest().authenticated();
|
||||
}
|
||||
|
||||
http.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
|
||||
.addLogoutHandler(logoutHandler());
|
||||
http.exceptionHandling().authenticationEntryPoint(
|
||||
new LoginUrlAuthenticationEntryPoint("/login"));
|
||||
|
||||
}
|
||||
|
||||
protected OAuth2ClientAuthenticationProcessingFilter cloudfoundrySsoFilter() {
|
||||
OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter(
|
||||
"/login");
|
||||
filter.setRestTemplate(restTemplate);
|
||||
filter.setTokenServices(tokenServices());
|
||||
return filter;
|
||||
}
|
||||
|
||||
private ResourceServerTokenServices tokenServices() {
|
||||
RemoteTokenServices services = new RemoteTokenServices();
|
||||
services.setCheckTokenEndpointUrl(sso.getTokenInfoUri());
|
||||
services.setClientId(sso.getClientId());
|
||||
services.setClientSecret(sso.getClientSecret());
|
||||
return services;
|
||||
}
|
||||
|
||||
private LogoutHandler logoutHandler() {
|
||||
LogoutHandler handler = new LogoutHandler() {
|
||||
@Override
|
||||
public void logout(HttpServletRequest request,
|
||||
HttpServletResponse response, Authentication authentication) {
|
||||
restTemplate.getOAuth2ClientContext().setAccessToken(null);
|
||||
String redirect = request.getRequestURL().toString()
|
||||
.replace("/logout", sso.getHome().getPath());
|
||||
try {
|
||||
response.sendRedirect(sso.getLogoutUri(redirect));
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalStateException("Cannot logout", e);
|
||||
}
|
||||
}
|
||||
};
|
||||
return handler;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.platform.cloudfoundry.sso;
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public interface CloudfoundrySsoConfigurer {
|
||||
|
||||
void configure(HttpSecurity http);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.platform.cloudfoundry.sso;
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class CloudfoundrySsoConfigurerAdapter implements CloudfoundrySsoConfigurer {
|
||||
|
||||
@Override
|
||||
public void configure(HttpSecurity http) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.platform.cloudfoundry.sso;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.validation.Validator;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@ConfigurationProperties("cloudfoundry.sso")
|
||||
@Data
|
||||
public class CloudfoundrySsoProperties implements Validator {
|
||||
|
||||
@Value("${vcap.services.sso.credentials.tokenUri:}")
|
||||
private String tokenUri;
|
||||
|
||||
@Value("${vcap.services.sso.credentials.authorizationUri:}")
|
||||
private String authorizationUri;
|
||||
|
||||
@Value("${vcap.services.sso.credentials.clientId:}")
|
||||
private String clientId;
|
||||
|
||||
@Value("${vcap.services.sso.credentials.clientSecret:}")
|
||||
private String clientSecret;
|
||||
|
||||
private Home home = new Home();
|
||||
|
||||
@Data
|
||||
public static class Home {
|
||||
private String path = "/";
|
||||
private boolean secure = true;
|
||||
}
|
||||
|
||||
public String getTokenInfoUri() {
|
||||
return tokenUri.replace("/oauth/token", "/check_token");
|
||||
}
|
||||
|
||||
public String getUserInfoUri() {
|
||||
return tokenUri.replace("/oauth/token", "/user_info");
|
||||
}
|
||||
|
||||
public String getLogoutUri(String redirectUrl) {
|
||||
return tokenUri.replace("/oauth/token", "/logout.do?redirect="+redirectUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> clazz) {
|
||||
return CloudfoundrySsoProperties.class.isAssignableFrom(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(Object target, Errors errors) {
|
||||
CloudfoundrySsoProperties sso = (CloudfoundrySsoProperties) target;
|
||||
if (StringUtils.hasText(sso.getTokenUri())) {
|
||||
if (!StringUtils.hasText(sso.getAuthorizationUri())) {
|
||||
errors.rejectValue("authorizeUri", "missing.authorizeUri", "Missing authorizeUri");
|
||||
}
|
||||
if (!StringUtils.hasText(sso.getClientId())) {
|
||||
errors.rejectValue("clientId", "missing.clientId", "Missing clientId");
|
||||
}
|
||||
if (!StringUtils.hasText(sso.getClientSecret())) {
|
||||
errors.rejectValue("clientSecret", "missing.clientSecret", "Missing clientSecret");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.platform.cloudfoundry.sso;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Import(CloudfoundrySsoConfiguration.class)
|
||||
public @interface EnableCloudfoundrySso {
|
||||
|
||||
}
|
||||
@@ -1,2 +1,2 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
org.springframework.platform.cloudfoundry.broker.ServiceBrokerAutoConfiguration
|
||||
org.springframework.platform.cloudfoundry.broker.configuration.ServiceBrokerAutoConfiguration
|
||||
@@ -18,9 +18,11 @@ package org.springframework.platform.cloudfoundry.broker.sample;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.platform.cloudfoundry.sso.EnableCloudfoundrySso;
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@EnableCloudfoundrySso
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
@@ -1,15 +1,27 @@
|
||||
debug: true
|
||||
server:
|
||||
port: 8787
|
||||
spring:
|
||||
application:
|
||||
name: eureka
|
||||
management:
|
||||
context-path: /admin
|
||||
cloudfoundry:
|
||||
sso:
|
||||
tokenUri: http://localhost:8080/uaa/oauth/token
|
||||
authorizationUri: http://localhost:8080/uaa/oauth/authorize
|
||||
clientId: app
|
||||
clientSecret: appclientsecret
|
||||
logging:
|
||||
level:
|
||||
com.netflix.discovery: 'OFF'
|
||||
org.springframework.security: DEBUG
|
||||
eureka:
|
||||
server:
|
||||
waitTimeInMsWhenSyncEmpty: 1000
|
||||
client:
|
||||
serviceUrl:
|
||||
defaultZone: http://localhost:8080/v2/
|
||||
default.defaultZone: http://localhost:8080/v2/
|
||||
defaultZone: http://localhost:8787/v2/
|
||||
default.defaultZone: http://localhost:8787/v2/
|
||||
registerWithEureka: false
|
||||
fetchRegistry: false
|
||||
Reference in New Issue
Block a user