http://nealma.com/2016/11/01/spring-boot-6-spring-session/
开发环境:
OS: Mac 10.11.6
IDE: IDEA
Build: 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中会话信息,待续...