由于项目的需要,别的平台需要单点登录到当前系统,单点登录的时候会推送一个token值过来,通过解析token值获取相关信息,由于推送过来的token只包含账号信息,是不包含密码信息的,所以就想到了绕过密码登录的方案,因为我们的项目使用了shiro安全框架,会话都交给了shiro去管理。所以就从网上搜索到了下面这样一个实现:
在某些应用场景下我们或许需要直接登录,而不需要用户输入密码,例如用户用手机直接登录的场景。
在Shiro中我们通过在线程变量中绑定一个已通过验证的Subject对象即可实现。
- PrincipalCollection principals = new SimplePrincipalCollection(
- user.getId(), "MobileRealm");
- Builder builder = new WebSubject.Builder(
- ServletActionContext.getRequest(),
- ServletActionContext.getResponse());
- builder.principals(principals);
- builder.authenticated(true);
- WebSubject subject = builder.buildWebSubject();
- ThreadContext.bind(subject);
以上是用于Web Application的代码,所以用的是WebSubject,应根据自己的应用选择需要创建的Subject类。
通过以上的方式发现有一个问题,就是发送请求构建subject的时候该请求的响应总是发送c了两个jsessionid,如下图:
c
导致放到session中的值使用的会话标志是第一个sid,而第二个sid会覆盖第一个,这样就会出现session丢失的情况。
问题原因:
使用WebSubject.Builder构建subject的时候会产生一个sessionId,而代码中HttpSession.setAttribute()这个方法也会产生一个sessionId.因此会导致产生两个sessionId导致会话丢失的问题。
解决方法:
设置WebSubject.Builder的sessionid为HttpSession的Id即可,如下代码:
builder.sessionId(session.getId());