Spring-Boot(六) Spring Session 分布式会话管理

本文介绍如何使用 Spring Session 支持 Cookies 和 Header,实现统一的会话管理方案,包括使用 CookieHttpSessionStrategy 和 HeaderHttpSessionStrategy 的方法,并展示了如何结合 Redis 进行 Session 外部存储。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

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中会话信息,待续...

转载于:https://my.oschina.net/nealma/blog/859067

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值