BAEL-315 Adding spring session as mechanism for sharing authentication tokens created by the edge service.
This commit is contained in:
parent
a310184efa
commit
2a7b598cf0
|
@ -6,3 +6,6 @@ eureka.instance.hostname=localhost
|
|||
eureka.client.serviceUrl.defaultZone=http://discUser:discPassword@localhost:8082/eureka/
|
||||
eureka.client.register-with-eureka=false
|
||||
eureka.client.fetch-registry=false
|
||||
|
||||
spring.redis.host=localhost
|
||||
spring.redis.port=6379
|
||||
|
|
|
@ -5,5 +5,9 @@ eureka.client.region = default
|
|||
eureka.client.registryFetchIntervalSeconds = 5
|
||||
|
||||
zuul.routes.resource.path=/resource/**
|
||||
zuul.routes.resource.sensitiveHeaders=Set-Cookie,Authorization,Cookie
|
||||
hystrix.command.resource.execution.isolation.thread.timeoutInMilliseconds: 5000
|
||||
|
||||
spring.redis.host=localhost
|
||||
spring.redis.port=6379
|
||||
|
||||
|
|
|
@ -2,6 +2,11 @@ spring.application.name=resource
|
|||
server.port=8083
|
||||
|
||||
resource.returnString=hello cloud
|
||||
resource.user.returnString=hello cloud user
|
||||
resource.admin.returnString=hello cloud admin
|
||||
|
||||
eureka.client.region = default
|
||||
eureka.client.registryFetchIntervalSeconds = 5
|
||||
|
||||
spring.redis.host=localhost
|
||||
spring.redis.port=6379
|
||||
|
|
|
@ -52,6 +52,15 @@
|
|||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.3</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
|
|
@ -32,6 +32,16 @@
|
|||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.session</groupId>
|
||||
<artifactId>spring-session</artifactId>
|
||||
<version>1.2.1.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<dependencyManagement>
|
||||
|
@ -52,6 +62,15 @@
|
|||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.3</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -17,11 +17,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||
auth.inMemoryAuthentication()
|
||||
.withUser("discUser")
|
||||
.password("discPassword")
|
||||
.roles("SYSTEM")
|
||||
.and()
|
||||
.withUser("admin")
|
||||
.password("password")
|
||||
.roles("ADMIN");
|
||||
.roles("SYSTEM");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package com.baeldung.spring.cloud.bootstrap.discovery;
|
||||
|
||||
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
|
||||
import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;
|
||||
|
||||
@EnableRedisHttpSession
|
||||
public class SessionConfig extends AbstractHttpSessionApplicationInitializer {
|
||||
}
|
|
@ -27,6 +27,21 @@
|
|||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-zuul</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.session</groupId>
|
||||
<artifactId>spring-session</artifactId>
|
||||
<version>1.2.1.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
|
@ -52,6 +67,15 @@
|
|||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.3</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,54 @@
|
|||
package com.baeldung.spring.cloud.bootstrap.gateway;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.WebAttributes;
|
||||
import org.springframework.security.web.authentication.AbstractAuthenticationTargetUrlRequestHandler;
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.io.IOException;
|
||||
|
||||
public class CustomAuthenticationHandler extends AbstractAuthenticationTargetUrlRequestHandler implements AuthenticationSuccessHandler{
|
||||
|
||||
public CustomAuthenticationHandler() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor which sets the <tt>defaultTargetUrl</tt> property of the base class.
|
||||
* @param defaultTargetUrl the URL to which the user should be redirected on
|
||||
* successful authentication.
|
||||
*/
|
||||
public CustomAuthenticationHandler(String defaultTargetUrl) {
|
||||
setDefaultTargetUrl(defaultTargetUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the parent class {@code handle()} method to forward or redirect to the target
|
||||
* URL, and then calls {@code clearAuthenticationAttributes()} to remove any leftover
|
||||
* session data.
|
||||
*/
|
||||
public void onAuthenticationSuccess(HttpServletRequest request,
|
||||
HttpServletResponse response, Authentication authentication)
|
||||
throws IOException, ServletException {
|
||||
response.setStatus(303);
|
||||
handle(request, response, authentication);
|
||||
clearAuthenticationAttributes(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes temporary authentication-related data which may have been stored in the
|
||||
* session during the authentication process.
|
||||
*/
|
||||
protected final void clearAuthenticationAttributes(HttpServletRequest request) {
|
||||
HttpSession session = request.getSession(false);
|
||||
|
||||
if (session == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
|
||||
}
|
||||
}
|
|
@ -1,9 +1,18 @@
|
|||
package com.baeldung.spring.cloud.bootstrap.gateway;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
|
||||
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
|
||||
import org.springframework.cloud.netflix.ribbon.RibbonClientSpecification;
|
||||
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
||||
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableZuulProxy
|
||||
|
@ -12,4 +21,20 @@ public class GatewayApplication {
|
|||
public static void main(String[] args) {
|
||||
SpringApplication.run(GatewayApplication.class, args);
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<RibbonClientSpecification> configurations = new ArrayList<>();
|
||||
|
||||
@Bean
|
||||
@LoadBalanced RestTemplate restTemplate(){
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public SpringClientFactory springClientFactory() {
|
||||
SpringClientFactory factory = new SpringClientFactory();
|
||||
factory.setConfigurations(this.configurations);
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package com.baeldung.spring.cloud.bootstrap.gateway;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER")
|
||||
.and()
|
||||
.withUser("admin").password("admin").roles("ADMIN");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests()
|
||||
.antMatchers("/resource/hello/cloud").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.formLogin()
|
||||
.successHandler(new CustomAuthenticationHandler("/resource/hello/user"))
|
||||
.and()
|
||||
.logout().permitAll()
|
||||
.logoutSuccessUrl("/resource/hello/cloud").permitAll()
|
||||
.and()
|
||||
.csrf().disable();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.baeldung.spring.cloud.bootstrap.gateway;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.session.data.redis.RedisFlushMode;
|
||||
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
|
||||
import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;
|
||||
|
||||
@Configuration
|
||||
@EnableRedisHttpSession(redisFlushMode = RedisFlushMode.IMMEDIATE)
|
||||
public class SessionConfig extends AbstractHttpSessionApplicationInitializer {
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package com.baeldung.spring.cloud.bootstrap.gateway;
|
||||
|
||||
import com.netflix.zuul.ZuulFilter;
|
||||
import com.netflix.zuul.context.RequestContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.SessionRepository;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
@Component
|
||||
public class SessionSavingZuulPreFilter extends ZuulFilter {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Autowired
|
||||
private SessionRepository repository;
|
||||
|
||||
@Override public boolean shouldFilter() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object run() {
|
||||
RequestContext context = RequestContext.getCurrentContext();
|
||||
|
||||
HttpSession httpSession = context.getRequest().getSession();
|
||||
Session session = repository.getSession(httpSession.getId());
|
||||
|
||||
context.addZuulRequestHeader("Cookie", "SESSION=" + httpSession.getId());
|
||||
|
||||
log.info("ZuulPreFilter session proxy: {}", session.getId());
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override public String filterType() {
|
||||
return "pre";
|
||||
}
|
||||
|
||||
@Override public int filterOrder() {
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -4,4 +4,15 @@ spring.cloud.config.discovery.enabled=true
|
|||
spring.cloud.config.username=configUser
|
||||
spring.cloud.config.password=configPassword
|
||||
|
||||
eureka.client.serviceUrl.defaultZone=http://discUser:discPassword@localhost:8082/eureka/
|
||||
eureka.client.serviceUrl.defaultZone=http://discUser:discPassword@localhost:8082/eureka/
|
||||
|
||||
management.security.sessions=always
|
||||
|
||||
zuul.routes.resource.path=/resource/**
|
||||
zuul.routes.resource.sensitive-headers=Set-Cookie,Authorization
|
||||
zuul.routes.resource.retryable=true
|
||||
hystrix.command.resource.execution.isolation.thread.timeoutInMilliseconds=600000
|
||||
|
||||
logging.level.org.springframework.web.=debug
|
||||
logging.level.org.springframework.security=debug
|
||||
logging.level.org.springframework.cloud.netflix.zuul=debug
|
|
@ -27,6 +27,21 @@
|
|||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.session</groupId>
|
||||
<artifactId>spring-session</artifactId>
|
||||
<version>1.2.1.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
|
@ -52,6 +67,15 @@
|
|||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.3</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -18,8 +18,24 @@ public class ResourceApplication {
|
|||
@Value("${resource.returnString}")
|
||||
private String returnString;
|
||||
|
||||
@Value("${resource.user.returnString}")
|
||||
private String userReturnString;
|
||||
|
||||
@Value("${resource.admin.returnString}")
|
||||
private String adminReturnString;
|
||||
|
||||
@RequestMapping("/hello/cloud")
|
||||
public String getString() {
|
||||
return returnString;
|
||||
}
|
||||
|
||||
@RequestMapping("/hello/user")
|
||||
public String getUserString() {
|
||||
return userReturnString;
|
||||
}
|
||||
|
||||
@RequestMapping("/hello/admin")
|
||||
public String getAdminString() {
|
||||
return adminReturnString;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package com.baeldung.spring.cloud.bootstrap.resource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal1(AuthenticationManagerBuilder auth) throws Exception {
|
||||
//try in memory auth with no users to support the case that this will allow for users that are logged in to go anywhere
|
||||
auth.inMemoryAuthentication();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.httpBasic()
|
||||
.disable()
|
||||
.authorizeRequests()
|
||||
.antMatchers("/hello/cloud").permitAll()
|
||||
.antMatchers("/hello/user").hasAnyRole("USER", "ADMIN")
|
||||
.antMatchers("/hello/admin").hasAnyRole("ADMIN")
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.csrf().disable();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public BCryptPasswordEncoder encoder() {
|
||||
return new BCryptPasswordEncoder(11);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.baeldung.spring.cloud.bootstrap.resource;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
|
||||
import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;
|
||||
|
||||
@Configuration
|
||||
@EnableRedisHttpSession
|
||||
public class SessionConfig extends AbstractHttpSessionApplicationInitializer {
|
||||
}
|
|
@ -4,4 +4,9 @@ spring.cloud.config.discovery.enabled=true
|
|||
spring.cloud.config.username=configUser
|
||||
spring.cloud.config.password=configPassword
|
||||
|
||||
eureka.client.serviceUrl.defaultZone=http://discUser:discPassword@localhost:8082/eureka/
|
||||
eureka.client.serviceUrl.defaultZone=http://discUser:discPassword@localhost:8082/eureka/
|
||||
|
||||
management.security.sessions=never
|
||||
|
||||
logging.level.org.springframework.web.=debug
|
||||
logging.level.org.springframework.security=debug
|
Loading…
Reference in New Issue