diff --git a/spring-cloud.html b/spring-cloud.html index cc83db8..02577bc 100644 --- a/spring-cloud.html +++ b/spring-cloud.html @@ -478,9 +478,15 @@ body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-b
Spring Cloud focuses on providing good out of box experience for typical use cases and extensibility mechanism to cover others.
+Spring Cloud focuses on providing good out of box experience for typical use cases +and extensibility mechanism to cover others.
Example script to deploy and regis#ter a broker:
+Here’s a Spring Cloud "Hello World" app with HTTP Basic +authentication and a single user account:
+@Grab('spring-boot-starter-security')
+@Controller
+class Application {
+
+ @RequestMapping('/'
+ String home() {
+ 'Hello World'
+ }
+
+}
+You can run it with spring run app.groovy and watch the logs for the password (username is "user"). So far this is just the default for a Spring Boot app.
Here’s a Spring Cloud app with OAuth2 SSO:
+@Grab('spring-cloud-starter-security')
+@Controller
+@EnableOAuth2Sso
+class Application {
+
+ @RequestMapping('/'
+ String home() {
+ 'Hello World'
+ }
+
+}
+Spot the difference? This app will actually behave exactly the same as +the previous one, because it doesn’t know it’s OAuth2 credentals +yet.
+You can register an app in github quite easily, so try that if you +want a production app on your own domain. If you are happy to test on +localhost:8080, then set up these properties in your application +configuration:
+oauth2:
+ client:
+ clientId: bd1c0a783ccdd1c9b9e4
+ clientSecret: 1a9030fbca47a5b2c28e92f19050bb77824b5ad1
+ tokenUri: https://github.com/login/oauth/access_token
+ authorizationUri: https://github.com/login/oauth/authorize
+ authenticationScheme: form
+ resource:
+ userInfoUri: https://api.github.com/user
+ preferTokenInfo: false
+run the app above and it will redirect to github for authorization. If +you are already signed into github you won’t even notice that it has +authenticated. These credentials will only work if your app is +running on port 8080.
+If you now drop the app into Cloud Foundry:
DOMAIN=mydomain.net
-cf push app -p target/*.jar --no-start
-cf env app | grep SPRING_PROFILES_ACTIVE || cf set-env app SPRING_PROFILES_ACTIVE cloud
-cf env app | grep APPLICATION_DOMAIN || cf set-env app APPLICATION_DOMAIN ${DOMAIN}
-
-cf services | grep configserver && cf bind app configserver
-
-cf restart app
-cf create-service-broker app user secure http://app.${DOMAIN}
-
-for f in `cf curl /v2/service_plans | grep '\"guid' | sed -e 's/.*: "//' -e 's/".*//'`; do
- cf curl v2/service_plans/$f -X PUT -d '{"public":true}'
-done
-
-cf create-service app free appi
+$ spring jar app.jar app.groovy +$ cf push -p app.jar
At which point you have a service called "app" and a service instance called "appi":
+and bind it to a service called "sso" with the following properties +(e.g. created as a +user-provided +service):
$ cf marketplace
-OK
+$ cf create-user-provided-service sso -p '{clientId:"<my-client>",clientSecret:"<my-secret>",userInfoUri:"https://uaa.run.pivotal.io/userinfo",tokenUri: "https://login.run.pivotal.io/oauth/token",authorizationUri:"https://login.run.pivotal.io/oauth/authorize"}
+$ cf push app -p app.jar
+and then visit it in a browser, then it will redirect to the Cloud
+Foundry (PWS) login server instead of challenging for Basic
+authentication credentials. The clientId and clientSecret are
+credentials of a registered client in Cloud Foundry. It’s quite hard
+to get a Cloud Foundry client registration for testing (but please ask
+at support@run.pivotal.io if you want one on PWS).
You want to protect an API resource with an OAuth2 token? Here’s a +simple example (paired with the client above):
+@Grab('spring-cloud-starter-security')
+@RestController
+@EnableOAuth2Resource
+class Application {
-service plans description
-app free Singleton service app
-$ cf services
-Getting services in org default / space development as admin...
-OK
+ @RequestMapping('/'
+ def home() {
+ [message: 'Hello World']
+ }
-name service plan bound apps
-appi app free
+}
Your application can define a configuration property
-application.domain (defaults to "cfapps.io") which will be used to
-construct the credentials for any app that binds to your service. Or
-it can define the URI directly using
-cloudfoundry.service.definition.metadata.uri.
and
+oauth2:
+ resource:
+ userInfoUri: https://api.github.com/user
+ preferTokenInfo: false
+If your app has a
+Spring
+Cloud Zuul embedded reverse proxy (using @EnableZuulProxy) then you
+can ask it to forward OAuth2 access tokens downstream to the services
+it is proxying. Thus the SSO app above can be enhanced simply like this:
@Controller
+@EnableOAuth2Sso
+@EnableZuulProxy
+class Application {
+
+ @RequestMapping('/'
+ String home() {
+ 'Hello World'
+ }
+
+}
+You can change some other basic metadata by setting config properties:
-cloudfoundry.service.definition.* is bound to a
-ServiceDefinition (defined in spring-boot-cf-service-broker) which
-has optional setters for plans and metadata.
cloudfoundry.service.broker.* is bound to an internal bean. It has
-optional setters for "name" (the service name), "description" (user
-friendly description) and "prefix" (used to create a unique id from
-the name).
and it will (in addition to loggin the user in and grabbing a token)
+pass the authentication token downstream to the /proxy/*
+services. If those services are implemented with
+@EnableOAuth2Resource then they will get a valid token in the
+correct header.
An app which binds to your service will get credentials that contain a
-"uri" property linking to your service. A Spring Boot app can bind to
-that through the vcap.services.[service].credentials.uri environment
-property.
How does it work? The @EnableOAuth2Sso annotation pulls in
+spring-cloud-starter-security (which you could do manually in a
+traditional app), and that has some autoconfiguration for a
+ZuulFilter, which itself is activated because Zuul is on the
+classpath (via @EnableZuulProxy). The
+filter
+just extracts an access token from the currently authenticated user,
+and puts it in a request header for the downstream requests.
If your service also has a -Eureka core dependency, and you -can expose it as a Eureka service, then any service which registers -with Eureka will also become a Cloud Foundry service.