### 前言 使用Spring Security的时候,觉得省了好多的事情但是它使用的是内存来存储CurrentUser的信息 和登录凭证,一旦单机不能承受大用户量,就需要水平扩展,就会涉及到session的问题。
怎么才能实现 平滑扩展呢?还好有Sping Session,怎么用呢?开发环境:OS: Mac 10.11.6IDE: IDEABuild: Maven### Spring Session 是什么 其实也不是什么新鲜的事儿?我们在实现用户登录,授权的时候,最初是web场景,我们只需要在Cookies中
操作即可,现在我们面临移动端、open API等多种场景,单纯的Cookies已经不满足或者不能优雅的体现Restful 风格,此时需要在Header上动手脚,也就是把原来存放在Cookies中的信息移到了Header中,换汤不换药
### 在Web中使用CookieHttpSessionStrategy```java @Bean public HttpSessionStrategy httpSessionStrategy() { return new CookieHttpSessionStrategy();
}```### 在Header中使用HeaderHttpSessionStrategy```java @Bean public HttpSessionStrategy httpSessionStrategy() {
return new HeaderHttpSessionStrategy(); }```### Session 外部存储单纯的把Session信息存在JVM内容已经不适合现在的技术架构,再加上外部存储的开源产品足够成熟(Redis等),
于是Sping Session对HttpSession进行了重新包装,使其很容易结合Redis等开源产品,节省了我们的开发时间只需要在你自己实现的WebSecurityConfigurerAdapter中加上如下注解:。
```@EnableRedisHttpSession```### Cookies和Header混合支持但是在使用的过程中遇到一个问题,需要Cookie和Header都支持,这下麻烦了,还需要自己去实现,
怎么才能都支持呢?那就是在自己实现的AllHttpSessionStrategy中,对Request进行判断,如果是html,就使用CookieHttpSessionStrategy,如果是API就用HeaderHttpSessionStrategy,具体如下:
``` @Bean public HttpSessionStrategy httpSessionStrategy() { return new MyHttpSessionStrategy(new HeaderContentNegotiationStrategy());
}```这里的MyHttpSessionStrategy是要自己实现的```public class MyHttpSessionStrategy implements HttpSessionStrategy {
private HttpSessionStrategy browser; private HttpSessionStrategy api; private RequestMatcher browserMatcher;
@Autowired public MyHttpSessionStrategy(ContentNegotiationStrategy contentNegotiationStrategy) { this(new CookieHttpSessionStrategy(), new HeaderHttpSessionStrategy());
MediaTypeRequestMatcher matcher = new MediaTypeRequestMatcher(contentNegotiationStrategy, Arrays.asList(MediaType.TEXT_HTML));
matcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL)); RequestHeaderRequestMatcher javascript = new RequestHeaderRequestMatcher("X-Requested-With");
this.browserMatcher = new OrRequestMatcher(Arrays.asList(matcher, javascript)); } public MyHttpSessionStrategy(HttpSessionStrategy browser, HttpSessionStrategy api) {
this.browser = browser; this.api = api; } @Override public String getRequestedSessionId(HttpServletRequest request) {
return getStrategy(request).getRequestedSessionId(request); } @Override public void onNewSession(Session session, HttpServletRequest request, HttpServletResponse response) {
getStrategy(request).onNewSession(session, request, response); } @Override public void onInvalidateSession(HttpServletRequest request, HttpServletResponse response) {
getStrategy(request).onInvalidateSession(request, response); } private HttpSessionStrategy getStrategy(HttpServletRequest request) {
return this.browserMatcher.matches(request) ? this.browser : this.api; }}```### 结束 这样无论是网页端还是RESTFull API,都可以正常支持了。
网页端通过cookie来传递session,API使用的是x-auth-token。 这里有个问题就是还不知道怎么去更新Redis中会话信息,待续...
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。