Skip to content
Greg Turnquist edited this page Mar 2, 2018 · 26 revisions

Welcome to Learning Spring Boot 2nd Edition’s wiki!

We broke new ground by releasing Learning Spring Boot 2.0 2nd Edition on November 3rd, 2017. This was the first book to hit the market that:

You get to dig into building a reactive web app using reactive data access, state of the art developer tools, multiple testing strategies, asynchronous AMQP messaging, distributed microservices, WebSockets, and security. And then you get to deploy it to the cloud.

If you STAR and WATCH this github repository, you can be alerted to changes in the code and this wiki page the moment they happen.


Upgrade to Spring Boot 2.0.0.RELEASE

This book’s code was upgraded to 2.0.0.RELEASE on March 2nd, 2018, just two days are upgrading to RC2. For the changes to make to your own applications, check out the following sections.

Corresponding Spring portfolio upgrades

  • Spring Cloud - Finchley.M8

  • Spring Cloud Stream - Elmhurt.RC2

Key build changes

None

Code changes

None


Upgrade to Spring Boot 2.0.0.RC2

This book’s code was upgraded to 2.0.0.RC2 on February 28th, 2018, just seven days are upgrading to RC1. For the changes to make to your own applications, check out the following sections.

Corresponding Spring portfolio upgrades

  • Spring Cloud - Finchley.M7

  • Spring Cloud Stream - Elmhurt.RC1

Key build changes

None

Code changes

  • Spring Boot 2.0.0.RC2 bumps things up to Spring Security 5.0.2.RELEASE. That combined with tweaks to Boot’s security policies has caused CSRF (Cross Site Request Forgery) protected to enabled by default. CSRF is already disabled between the microservices. But the fact that Eureka is secured triggers breakage. The solution requires plugging in an alternative security policy in Eureka.

    @Configuration
    protected static class SecurityPolicy extends WebSecurityConfigurerAdapter {
    
    	@Override
    	protected void configure(HttpSecurity http) throws Exception {
    		http
    			.authorizeRequests()
    				.anyRequest().authenticated()
    				.and()
    			.httpBasic()
    				.and()
    			.csrf().disable();
    	}
    }

    This class, tucked inside of LearningSpringBootEurekaServerApplication replaces the default security policy provided by Spring Boot, declaring that all authenticated users are also authorized, that HTTP BASIC is enabled, and that CSRF is disabled.

  • There were some bugs found in Chapter 10 that shouldn’t have been there. Stuff that was fixed in Chapter 9’s code but never copied over to Chapter 10 (nothing in print) caused stuff to break. That was fixed and verified to work correctly.


Upgrade to Spring Boot 2.0.0.RC1

The code base was initial published against Spring Boot 2.0.0.M5. It was upgraded to 2.0.0.RC1 on February 21st, 2018. For the changes to make to your own applications, check out the following sections.

Corresponding Spring portfolio upgrades

  • Spring Cloud - Finchley.M6

  • Spring Cloud Stream - Elmhurt.M4

Key build changes

  • org.springframework.boot:spring-boot-starter-security-reactiveorg.springframework.boot:spring-boot-starter-security

Code changes

  • In Chapter 10, Take Your App To Production with Spring Boot, Spring Cloud Gateway is introduced. As a lingering side effect of Spring Session being lazy in saving session updates, I wrote a custom Spring Cloud Gateway filter to force the current WebSession (holder of security context) to get saved to MongoDB before making a remote call. The recipient of the remote call uses the SESSION id to then fetch these security context. Since publication, that bit of code was added to Spring Cloud Gateway, making it unnecessary in the book.

  • HttpSecurity is renamed as ServerHttpSecurity.

  • The frontend microservice’s security policy is changed to:

    @EnableWebFluxSecurity
    public class SecurityConfiguration {
    
    	@Bean
    	SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) {
    		return http
    			.authorizeExchange()
    				.pathMatchers("/**").authenticated()
    				.and()
    			.httpBasic()
    				.securityContextRepository(new WebSessionServerSecurityContextRepository()) // (1)
    				.and()
    			.csrf().disable() // (2)
    			.build();
    	}
    }
    1. You can now specify that all security details are stored in the HTTP session using httpBasic().securityContextRepository(new WebSessionServerSecurityContextRepository()). This also creates new session, replacing the security.session=always attribute.

    2. CSRF, which wasn’t operational at the time of writing, now is, and is on by default. So for now, it’s disabled explicitly via csrf().disable().

  • The backend microservice security policies are configured like this:

    @EnableWebFluxSecurity
    @EnableReactiveMethodSecurity
    public class SecurityConfiguration {
    
    	@Bean
    	SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) {
    		return http
    			.securityContextRepository(new WebSessionServerSecurityContextRepository()) // (1)
    			.authorizeExchange()
    				.anyExchange().authenticated()
    				.and()
    			.csrf().disable() // (2)
    			.build();
    	}
    }
    1. Setting the securityContextRepository at the top configures is to read from the WebSession, which is fetched from Spring Session MongoDB. This constrains the services to not create a new session, replacing the security.session=never attribute.

    2. This disables CSRF on the backend, since we’re not using in the book.

  • SpringDataUserDetailsRepository, which used to implement UserDetailsRepository now implements ReactiveUserDetailsService.

  • Spring Security now supports multiple password encoders/decoders. Passwords themselves are able to carry a tag (like {sha1}aj320gjr to signal the password was encoded using SHA-1. Faux users are now created like this:

    User.withDefaultPasswordEncoder() // (1)
        .username(user.getUsername()) // (2)
        .password(user.getPassword()) // (3)
        .authorities(user.getRoles()) // (4)
        .build()
    1. Creates a DelegatingPasswordEncoder, which in turn can support a multitude of encoders, including a NoOpPasswordEncoder that doesn’t encrypt the password at all.

    2. Fluent API to set username

    3. Fluent API to set password

    4. Fluent API to set list of GrantedAuthority using an array of string-based roles (replacing the need for AuthorityUtils.createAuthorityList(…​)).

  • Thymeleaf still doesn’t have built in support for Spring Security 5’s Reactive support. However, the location of security context details seems to have moved.

    public boolean expr(String accessExpression) {
    	Map<String, Object> sessionVars = (Map<String, Object>) this.context.getVariable("session"); // (1)
    	SecurityContext securityContext = (SecurityContext) sessionVars.get("SPRING_SECURITY_CONTEXT"); // (2)
    	Authentication authentication = securityContext.getAuthentication(); // (3)
            ....
    1. Look in the current Thymeleaf WebFlux context for the session variable. This will retrieve the map of variables stored in the HTTP session.

    2. Inside the HTTP session, look up the SPRING_SECURITY_CONTEXT variable, which contains current security context details.

    3. From the SecurityContext, extract the Authentication object.

  • Spring Framework slightly altered one API to yield a FileUrlResource instead of a bare UrlResource. This is indicative of a URL-based resource that is located on the local file system.

  • A couple sections of the manuscript’s code depended upon Spring WebFlux being brought in transitively through Spring Cloud Stream. This changed so org.springframework.boot:spring-boot-starter-webflux has been added explicitly in a couple places.

With Spring Security having the biggest API changes, this has all been tested out, verifying Learning Spring Boot works perfectly with Spring Boot 2.0.0.RC1.