我的shiro之旅: 十七 跨域session共享的一种解决方法
来源:互联网 发布:c语言If else例题 编辑:程序博客网 时间:2024/06/03 12:43
在文章七里面有介绍session共享,不过只是在一个域名及其他子域间共享。有时候,我们需要在多个一级域名共享登录的session。当然,用shiro-cas是一个很不错的解决方法,应该也是大部分人使用的方法。不过因为种种原因,并没有选择shiro-cas的方式,就使用了其他方式代替,思路也来自shiro-cas。比如有www.a.com,www.b.com两个域名需要共享session,并且www.b.com域名下的session是主,登录在www.b.com域名下,www.a.com域名下的session需要取www.b.com域名下的session。大概画一个图:
在www.a.com中加一个filter,用于重定向到www.b.com,取得b域名下的sessionId。代码贴出来:
import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import org.apache.commons.lang.StringUtils;import org.apache.shiro.web.servlet.AdviceFilter;import org.apache.shiro.web.util.WebUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import com.concom.security.infrastructure.helper.HttpHelper;import com.concom.security.infrastructure.helper.ShiroSecurityHelper;/**用于跨域共享session,那个应用需要与登录应用共享session,就开放此filter,并且应该是拦截所有请求,至少是拦截所有需要保护的资源 * @author Dylan * @mail pickear@gmail.com * @time 2014年4月14日 */public class CasFilter extends AdviceFilter {private final static Logger log = LoggerFactory.getLogger(CasFilter.class);private String casServerURL; //重定向的目标地址,该地址用于获取sessionId,如www.b.com/tokenprivate String domain; //filter应用的域名,如www.a.com@Overrideprotected boolean preHandle(ServletRequest request, ServletResponse response)throws Exception {boolean hasSyn = (null == ShiroSecurityHelper.getSession().getAttribute("hasSyn") ? false : (Boolean) ShiroSecurityHelper.getSession().getAttribute("hasSyn"));if(ShiroSecurityHelper.hasAuthenticated() || hasSyn){//当用户已经登录或者从session中取得的hasSyn为true,说明已经同步session,不需要再重定向return true;}String jsid = WebUtils.getCleanParam(request, "jsid");HttpServletRequest httpRequest = WebUtils.toHttp(request);String url = httpRequest.getRequestURL().toString();url = StringUtils.remove(url, httpRequest.getContextPath());if(StringUtils.isNotBlank(jsid)){//如果jsid不为空,说明是通过www.b.com重定向回来的,将从b域名拿到的sessionId写回到自己域名下。 //以下两句作用是将jsid,rememberMe写到domain域名下的cookie中,读者可以自己实现。HttpHelper.setCookie(WebUtils.toHttp(httpRequest),WebUtils.toHttp(response), "jsid", jsid,domain,"/");HttpHelper.setCookie(WebUtils.toHttp(httpRequest),WebUtils.toHttp(response), "rememberMe", WebUtils.getCleanParam(request, "rememberMe"),domain,"/");WebUtils.issueRedirect(request, response, url);log.info("redirect : " + url);return false;}String uri = casServerURL + "?service=" + url; //重写向到www.b.com/token下WebUtils.issueRedirect(request, response, uri);log.info("redirect : " + uri);return false;}@Overrideprotected void postHandle(ServletRequest request, ServletResponse response)throws Exception {super.postHandle(request, response);}public void setCasServerURL(String casServerURL) {this.casServerURL = casServerURL;}public void setDomain(String domain) {this.domain = domain;}}
www.b.com/token请求的代码应该是如下的:
/**用于跨域共享session,该方法应该在登录的应用开放。如登录页面在xxx.aa.com域名下,要和***.bb.com共享session * 那么,在***.bb.com应该有个filter,用来重写向到xxx.aa.com域名下的token请求,并带上回调地址,在token方法中 * 会拿到xxx.aa.com下的sesison,以参数的形式再重定向回***.bb.com。在bb域名的filter中拿到该jsid,应该保存 * 到自己域名下的cookie里,以确保bb的cookie里jsid值和xxx.aa.com相同。filter的实现为casFilter。 * @param request * @param response * @return */ @RequestMapping(value="/token",method = RequestMethod.GET)public void token(HttpServletRequest request, HttpServletResponse response) {String service = WebUtils.getCleanParam(request, "service");String rememberMe = HttpHelper.getCookieValue(request, "rememberMe");Session session = ShiroSecurityHelper.getSession();session.setAttribute("hasSyn", true); //将hasSyn为true设置到session中,CasFilter会从Session中取该值try {WebUtils.issueRedirect(request, response, service+"?jsid="+session.getId()+"&rememberMe="+rememberMe);} catch (IOException e) {e.printStackTrace();}}
然后,将CasFilter交由spring 管理
<bean id="casFilter" class="com.xxx.security.interfaces.filter.CasFilter"> <property name="casServerURL" value="http://www.b.com/token"/> <property name="domain" value="www.a.com"/></bean>
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><property name="securityManager" ref="securityManager" /><property name="loginUrl" value="/security/login.html" /><property name="successUrl" value="/home.html" /><property name="unauthorizedUrl" value="/security/unauthorized.html" /><property name="filters"><map><entry key="cas" value-ref="casFilter" /></map></property><property name="filterChainDefinitions"><value>/** = cas,anon</value></property></bean>
整个过程,目的只有一个,就是让www.a.com,www.b.com两个域名的cookie共享。当然,cookie跨域共享方式很多,网上也有很多资料,包括通过iframe,js等方式。本文的这种方法,只是借仿shiro-cas的重定向方式,不过也有所不同。本文分享到这里,希望读者有更好的方式分享。
0 0
- 我的shiro之旅: 十七 跨域session共享的一种解决方法
- 我的shiro之旅: 七 shiro session 共享
- 我的shiro之旅-session共享-redis
- 我的shiro之旅: 八 shiro session 共享的进一步
- 集群session共享方案(有shiro共享session的方案)
- ifame共享session的解决方法
- 我的shiro之旅: 三 浅谈shiro的filter
- 我的shiro之旅: 六 自定义shiro的sessionId
- 我的shiro之旅: 十 自定义shiro的SessionIdCookie
- 我的shiro之旅: 十一 shiro的权限设计
- 我的shiro之旅: 一 shiro简介
- 我的shiro之旅: 十四 shiro 自动登录
- 我的shiro之旅: 十四 shiro 自动登录
- 我的shiro之旅:自定义filter
- 我的shiro之旅-realm
- 我的tomcat+redis实现session共享配置之路
- 使用redis进行基于shiro的session集群共享
- 使用redis进行基于shiro的session集群共享
- LeetCode Wildcard Matching
- python 图 遍历-深度优先和广度优先 II
- Linux 多线程应用中如何编写安全的信号处理函数
- NSNumber Compare的崩溃
- 我的android开发之路
- 我的shiro之旅: 十七 跨域session共享的一种解决方法
- 不用循环,计算一串数字里面有多少个1
- weblogic的BEA-000438错误解决
- java,C#插入数据到oracle11g数据库并返回其id
- java中callback
- 静态链表的实现与操作(C语言实现)
- C语言中关键字auto、static、register、const、volatile、extern的作用
- 记录最近的几个bug
- jQuery模仿的QQ投票效果代码