2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

How session works with redis?

Last updated at Posted at 2019-05-09

Instead of Tomcat’s Embedded HttpSession stored in memory, Spring-Session reimplements HttpSesson with Redis to support multiple sessions with same browser.

Try it up with debugger

Let's first create a demo project, go to starter page and create a demo project with following plugin:

  • Redis
  • Web
  • Session

Add @EnableRedisHttpSession to BootApplication

@SpringBootApplication
+ @EnableRedisHttpSession
public class DemoApplication {
	...
}

And create a Hello Controller for debugging

@RestController
@RequestMapping("/")
public class Hello {

  @GetMapping("hello")
  public String hello(HttpServletRequest request, @RequestParam String value){
    // add debugger here
    request.getSession().setAttribute("key",value);
    return value;
  }
}

Add debugger with find usage for getter/setter

org.springframework.session.web.http.SessionRepositoryFilter#CURRENT_SESSION_ATTR

Cookies resolver

org.springframework.session.web.http.CookieHttpSessionIdResolver#resolveSessionIds

And these are the mapping between cookies and redis

org.springframework.session.web.http.DefaultCookieSerializer#readCookieValues
org.springframework.session.web.http.DefaultCookieSerializer#writeCookieValue

then start a local redis(localhost:6379) and run springboot in debug mode.

Let's try with a curl

 curl "http://localhost:8080/hello?value=1"

Finally, login to redis-cli, you will find sessions are already in Redis.

KEYS spring:session:sessions:*

How to reuse session-id?

By default, session ids are generated by UUID, they have no relation with browser or IP address.

org.springframework.session.MapSession#generateId

To reuse the session-id, every request from browser must have a valid seesion in the header(cookies or x-auth-token), I prefer header based session resolver (less payload and easier for non-browser clients).

@Bean
HttpSessionIdResolver headerResolver(){
	return new HeaderHttpSessionIdResolver("miao-token");
}

Recurl and your will get a miao-token header in response.

Content-Type: ...
Date: ...
miao-token: f15b28ea-15b6-4ce8-aad5-9ed0ab00d643

To keep the client's session up to date with server, just add the header in HttpInterceptor(eg: okhttp/ajax).

// angular HttpInterceptor, same as okhttp
export class AddHeaderInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const clonedRequest = req.clone({ 
    	headers: req.headers.set('miao-token', YOUR_GLOBAL_TOKEN) 
		});
    return next.handle(clonedRequest);
  }
}

In the end, here is the resuable process flow.

RESTful Request
	|
HttpSessionIdResolver
	|
(has token id)?
	|  
	|-------(yes): get seesion by id from redis and reuse.
	---------(no): jump to login page and create id by UUID

Appendix

What's cookie's scope?

See Scope of cookies, if you share two war with same session, you need to customize the DefaultCookieSerializer for wider scope.

CSRF protection

CSRF(Cross-Site Request Forgery) attacks may inject malicious code into webpages, see more at Spring-Securiy for server-side protection and Angular for client-side protection.

Alternatives

If you prefer a lower level redis store implementation, just try tomcat-redis-session-manager

com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve
2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?