Spring-cloud-gateway: WebSession always save to spring session on redis?

Created on 6 Aug 2018  路  9Comments  路  Source: spring-cloud/spring-cloud-gateway

This is my globalFilter, I want to get some attributes in session,when user logined success ,but get nothing! And I put some attributes to session ,but always a new session save to spring session on redis.

@Component("LoginFilter")
public class LoginFilter implements GlobalFilter, Ordered {

    private static final Logger logger = LoggerFactory.getLogger(LoginFilter.class);


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        Map<String, Object> attrs = exchange.getSession().cache().block().getAttributes();
        attrs.put("abc", "ddddd");
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }
}

This is my Logincontroller on backend service .

    @PostMapping("/pb/login")
    public Response<Void> login(@RequestParam("loginName") String username, String password,
        HttpServletRequest request, HttpServletResponse resp) {
        ......
        AdminDTO adminDTO = new AdminDTO();

        HttpSession session = request.getSession();
        logger.debug("session id is {}",session.getId());
        // save to session
    request.getSession().setAttribute(GlobalConstant.SESSION_KEY, adminDTO);
    ......
        return response;
    }

bootstrap.yml

server:
    port: 7040
spring:
    application:
        name: web-gateway
    cloud:
        gateway:
            locator:
                enabled: true
            routes:
            -   id: user-service
                uri: lb://user-service
                order: 8000
                predicates:
                - Path=/api/user/**
                filters:
                - SaveSession
                - StripPrefix=2
            -   id: admin-service
                uri: lb://admin-service
                order: 8000
                predicates:
                - Path=/api/admin/**
                filters:
                - StripPrefix=2

admin service Application

@EnableDiscoveryClient
@SpringBootApplication
@EnableCircuitBreaker
@EnableRedisHttpSession(redisNamespace = "lvji")
public class AdminApplication {

    private static final Logger logger = LoggerFactory.getLogger(AdminApplication.class);

    public static void main(String[] args) {
        SpringApplication.run(AdminApplication.class, args);
    }

}

````
gateway Application

@EnableFeignClients
@SpringBootApplication
@EnableRedisWebSession(redisNamespace = "gt")
@Slf4j
public class WebGatewayApplication {

private static final Logger logger = LoggerFactory.getLogger(WebGatewayApplication.class);

public static void main(String[] args) {
    logger.info("Starting WebGatewayApplication ---------------------------------------");
    SpringApplication.run(WebGatewayApplication.class, args);
    logger.info("WebGatewayApplication started successed ------------------------------");
}

}


gateway gradle.build

dependencies {
compile(
'org.springframework.session:spring-session-data-redis:2.0.5.RELEASE',
'org.springframework.boot:spring-boot-starter-data-redis:2.0.4.RELEASE',
)
compile("io.lettuce:lettuce-core:5.0.3.RELEASE")
compile "org.apache.commons:commons-pool2:2.6.0"
compile('com.alibaba:fastjson:1.2.31')
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.boot:spring-boot-starter-webflux')
compile('org.springframework.cloud:spring-cloud-starter-gateway')
compile('org.springframework.cloud:spring-cloud-starter-netflix-ribbon')
compile('org.springframework.cloud:spring-cloud-starter-consul-all')
compile('org.springframework.cloud:spring-cloud-starter-netflix-hystrix')
compile('org.springframework.cloud:spring-cloud-starter-openfeign')
compile('org.projectlombok:lombok')
}
````

redis info
192.168.32.66:6380> keys lvji* 1) "lvji:sessions:expires:cdab3607-dbe4-45df-89ec-38de8d739165" 2) "lvji:expirations:1533579060000" 3) "lvji:sessions:cdab3607-dbe4-45df-89ec-38de8d739165" 192.168.32.66:6380> keys gt* 1) "gt:sessions:e62b9623-7bcc-44b9-a017-cdb12768a9dc" 2) "gt:sessions:9f42be8c-3d21-4676-bf42-d96934e86643" 3) "gt:sessions:db72cd1c-a67f-4316-bac0-219a20fc8561" 4) "gt:sessions:d830536c-b77b-4d4d-aaa7-409ff0638196" 5) "gt:sessions:6f0e359f-2087-4299-a3d6-0ec966e9a01f" 6) "gt:sessions:53f88f8d-a104-45ea-9fb8-cff0560e72e6" 7) "gt:sessions:9f7a2a87-7db6-498c-924d-44a875751c5b" 8) "gt:sessions:55da8712-3745-48da-8cdc-f93d0a494179" 9) "gt:sessions:ae70a5a5-9e83-4c11-9cf0-ef093a610675" 10) "gt:sessions:6d1e2913-20c7-4f51-bceb-1f47b16c2e26" 11) "gt:sessions:80e359df-dbd9-4362-ae28-e8b395ac6c2f" 12) "gt:sessions:88684b4e-5209-40c4-bb48-eefe1a1d6eb7" 13) "gt:sessions:d9eabd61-21c2-4aad-bc27-7f83f27539b8" 14) "gt:sessions:fa0c68a6-0643-4985-8f21-54aed996fffb" 15) "gt:sessions:559668e3-a864-4aa9-b784-597908bf0e0f"

question

Most helpful comment

@others
I search the topic when I use spring cloud gateway.
Spring cloud gateway use WebSession(redis) with WebFlux.
Other serivce behind gateway use HttpSession(redis) with SpringMvc.
The reason gateway can not get session is:
HttpSession encode the sessionid(base64) but WebSession not (base on SpringSession-2.1.7)
Here is a triky solution:

```
@Configuration
@EnableRedisHttpSession
public class SpringSessionConfig {
@Autowired
private DefaultCookieSerializer defaultCookieSerializer;

@PostConstruct
public void init(){
    this.defaultCookieSerializer.setUseBase64Encoding(false);
}

}
````

All 9 comments

Not sure I understand what you are asking. Gateway has nothing to do with spring session redis and I have never used it before.

BTW, anytime you use block() in gateway (or any Webflux application) is an error.

@spencergibb
I used the spring session redis at the gateway level. When I access the url through the gateway, there will be a spring session redis save every time I visit. But the backend service layer has only one session saved in redis

I remembered there is a SaveSessionGatewayFilterFactory. @gregturn might be able to offer more help here than me.

SaveSessionGatewayFilterFactory is designed in case you need to _ensure_ the session is saved before making an outbound call from the gateway. For example, if you establish a session at the gateway and wish to "share it" with other microservices. Use the filter and be sure to pass along the session id to other microservices.

Some Spring Session implementations are lazy (for example Spring Session MongoDB), meaning they don't actually make a save until you trigger one. Not sure about Redis. @vpavic may know about that one in particular.

@spencergibb @gregturn
Thank you for your reply, I solved the problem. By implementing my own WebSessionIdResolver, I understand some, but it is not very clear, I have to look at the source code again.

@9923 do you mind sharing?

@spencergibb
It will be my pleasure.Maybe after I finish it.

Hello, I have the same problem, do you mind sharing your code? @vezhou

@others
I search the topic when I use spring cloud gateway.
Spring cloud gateway use WebSession(redis) with WebFlux.
Other serivce behind gateway use HttpSession(redis) with SpringMvc.
The reason gateway can not get session is:
HttpSession encode the sessionid(base64) but WebSession not (base on SpringSession-2.1.7)
Here is a triky solution:

```
@Configuration
@EnableRedisHttpSession
public class SpringSessionConfig {
@Autowired
private DefaultCookieSerializer defaultCookieSerializer;

@PostConstruct
public void init(){
    this.defaultCookieSerializer.setUseBase64Encoding(false);
}

}
````

Was this page helpful?
0 / 5 - 0 ratings

Related issues

gaoyf picture gaoyf  路  3Comments

chsi13 picture chsi13  路  6Comments

bijukunjummen picture bijukunjummen  路  3Comments

samtonyclarke picture samtonyclarke  路  3Comments

thirunar picture thirunar  路  6Comments