I have a scenario that I have some microservices, cloud gateway and eureka server. All microservices and cloud gateway registered on the eureka server. Cloud gateway will securing all the downstream services. When any user want to access the service first it will fill out the username and password for authentication on the cloud gateway. If the user will be authentic then it will access the service by the gateway route that is already set in application.properties file but I want when the user will authentic and access the service then I can also get user authentic credential in downstream services or microservices that are behind the cloud gateway. In other word I want to getting principle values that is set on the gateway in downstream service. So, After searching many days I got a Global Filter Implementation link but this filter code in Kotlin and I am not familiar with Kotlin, So unable to understand of this. I want to implement this in Java. Basically this filter for adding username and user roles to headers of downstream services request. How can I convert this filter into java.
Here is the Workflow
Here is the cloud gateway configuration
@Configuration @EnableWebFluxSecurity public class GatewaySecurityConfig{ @Bean public MapReactiveUserDetailsService userDetailsService() { UserDetails user = User.builder() .username("user") .password(passwordEncoder().encode("password")) .roles("USER") .build(); UserDetails admin = User.builder() .username("admin") .password(passwordEncoder().encode("password")) .roles("USER","ADMIN") .build(); return new MapReactiveUserDetailsService(user, admin); } @Bean public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { http .authorizeExchange() .anyExchange().authenticated() .and() .httpBasic(withDefaults()) .formLogin(); return http.build(); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(8); } }
Global Filter Implementation in Kotlin and I want code of this in Java8
@Component class AddCredentialsGlobalFilter : GlobalFilter { private val usernameHeader = "logged-in-user" private val rolesHeader = "logged-in-user-roles" override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain) = exchange.getPrincipal<Principal>() .flatMap { p -> val request = exchange.request.mutate() .header(usernameHeader, p.name) .header(rolesHeader, (p as Authentication).authorities?.joinToString(";") ?: "") .build() chain.filter(exchange.mutate().request(request).build()) } }
Application.properties Configuration
server: port: 8080 eureka: client: serviceUrl: defaultZone: http://localhost:8083/eureka spring: main: allow-bean-definition-overriding: true application: name: gateway cloud: gateway: routes: - id: userModule uri: lb://user predicates: - Path=/user/**
Advertisement
Answer
I believe it’s something like following
@Component public class AddCredentialsGlobalFilter implements GlobalFilter { private final String usernameHeader = "logged-in-user"; private final String rolesHeader = "logged-in-user-roles"; @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { return exchange.getPrincipal().flatMap(p -> { List<GrantedAuthority> authorities = (List<GrantedAuthority>) ((Authentication)p).getAuthorities(); String rolesString = authorities != null ? authorities.stream().map(Object::toString).collect(Collectors.joining(";")) : ""; ServerHttpRequest request = exchange.getRequest().mutate() .header(usernameHeader, p.getName()) .header(rolesHeader, rolesString) .build(); return chain.filter(exchange.mutate().request(request).build()); }); } }