ajax 跨域 session 及 spring boot分布式session

前端之家收集整理的这篇文章主要介绍了ajax 跨域 session 及 spring boot分布式session前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。



(一)背景:http://blog.csdn.net/u010989191/article/details/53400624


未跨域Ajax异步请求时,session保持不变

未跨域时Ajax请求不同的action时,session保持不变

跨域Ajax异步请求时,每次请求都是一个新的session

@H_301_29@ 一些帖子供参考

http://www.cnblogs.com/interdrp/p/4056525.html
http://blog.csdn.net/qq_29845761/article/details/51897705

同一个容器内的请求不会出现session失效,异步跨域访问则需要考虑session共享问题


(二)参考http://www.cnblogs.com/gdlin/p/6846638.html

情景:公司的一个网站有一个模块(测试模块)需要单独用另外的一个域名(www.xyz.com)去访问,即网站需要用两个不同的域名去访问,如首页(www.abc.com)和测试模块(www.xyz.com)

这时候就涉及到session跨域问题,因为域名不是父子关系,所以必须要实现完全跨域,想到了以下三个解决办法:

1.URL传参:测试模块访问的时候,地址www.xyz.com后把主域名的session通过参数的形式传递过去,如:www.xyz.com;jsessionid=7D4DED1F2DB5BC53961EFED18BCE7E30

2.SSO单点登录

3.利用jsonp的跨域特性,通过ajax进行session传递

第一种方案考虑URL传参数不美观以及URL需要分享给别人的时候就没法获取到session,所以放弃

第二种SSO单点登录方案应该在三种方案中最优的,因为系统架构问题,所以也放弃

我的项目中采用第1种方案,直接成功。

在本例中,对方的前提是 服务器相同,域名不同,且非父子域名cookie无法共享

(三)周边情况

http://blog.csdn.net/ahhsxy/article/details/7356128

这篇文章前提是 服务器相同,域名不同,父子域名,文章详细分析了sesseion本质及解决方

文章首先:要在不同的二级域名共享session,只需要把JESSIONID写进共享Cookie就行了。

然后发现session后者才是我手工创建的,而前者是tomcat创建的。很遗憾,我手工创建的不生效,因为tomcat在绑定session时,采取严格匹配更加优先的原则,blog.vinceruan.info比.vinceruan.info更加匹配。

所以:在所有sesseion的地方:

public Session getSession(HttpServletRequest request,HttpServletResponse response){
HttpSession session = request.getSession(false);
if (session==null){
session = request.getSession(true);
String session_id = session.getId();
Cookie c = new Cookie("JSESSIONID",session_id);
c.setDomain(".vinceruan.info");
c.setPath("/");
response.addCookie();
}
}


取得session,重置cokkie的domain为父域名

作者也表示不想使用单点登录,所以最终采用修改tomcat配置搞定


(四)基于redis的单点登录

http://blog.csdn.net/Angry_Mills/article/details/73866332

先简单说一下单点登录

登录的部分单独拿出来作为一个项目,专门用来登录

当我想访问某个子项目或者模块的时候,会先请求登录的部分,如果登录过了,就不需要再登录了。

这个和单独项目时,把userId放到session中道理是一样的

因为多个子项目在不同的tomcat无法实现session共享,这时我们可以利用cookie


多说几句关于cookie和session的区别

cookie是针对于浏览器的,session是针对服务器的。

cookie的产生会有JSessionId,也就是session的唯一凭证。

cookie是当前浏览器对该父域名用作数据共享和记录的。

session是在服务器上开辟了一块内存,用于当前session(同一JSessionId)用户数据共享

关于cookie和session的区别只是个人理解,有不同的看法可以提,多交流。

说一下流程:

用户在一个模块登录,会进到登录系统,先验证你的用户名和密码是否正确,如果正确。

会产生一个唯一票据,我们这里叫他token,把这个token放到redis中,存放方式是这样的。

redis.put(token,userId);//存储一条对应用户信息的token

redis,put("your setting",token);//再存储一条对应userId的唯一标识,your setting可以写成loginSys+userId

为什么要这么存,正常的思路是只存上面一条就行了,稍后解答。

我们把token返回,response.addCookie(new Cookie("my cookie",token));//这里的my cookie可以写成loingSysCookie

流程实现是这样的,需要设置过期时间等等参数,这里就不写了。

这时候只要是同一浏览器,就会带着这个cookie,访问该项目下的子项目(父级域名下的子级域名,比如www.baidu.com和mp3.baidu.com的关系),

进入登录系统,拿到token,进到redis中比对,是否有用户就可以了,如果有,就不需要再登录了。

下面说一下上面的疑问:

当我再一次登录系统的时候,先去找redis中的redis,get("your setting")是否为空,已经在别处登录过的用户,可以取到他的token,

redis.del(token),这样就实现了单点登录,同步登出。

之后再设置redis和cookie,方法同上。

很多没有redis中放第二条,就无法实现单点登录同步登出,虽然设置了过期时间,但用户体验和安全性还是差一点。



该法没有用session,仅用了cokkie,所以不存在tomcat的cokkie和自己生成的session cookie冲突问题

但仍有两个弊端:

1.如果不是父子域名就没办法了

2. 客户端禁用cookie

总结:

1.如果请求域名不同,存在父子关系

只能放弃session+cookie方式,因为一次登录要给父域名注册cookie,且还要考虑tomcat自动生成的二级域名cookie与手动注册的一级域名cookie冲突,每次覆盖sesseion(无谓的开销)以及spring等框架对session的封装;

可采用cokkie(或localstrage)+token(jsessionID),在请求时一起带上

2.如果请求域名不同,不存在父子关系

可采用localstrage+token(jsessionID),在请求时一起带上


3.ajax请求不会写入cokkie,也不会带上cokkie,所以只能在请求时捎带 jsessionid 或者token机制

4.如果请求域名相同,服务器不同

则直接在服务器端集成分布式session;

spring boot 分布式session(利用redis)方法参考:

http://www.cnblogs.com/mengmeng89012/p/5519698.html

这次带来的是spring boot + redis 实现session共享的教程。

在spring boot的文档中,告诉我们添加@EnableRedisHttpSession来开启spring session支持,配置如下:

Java代码
  1. @Configuration
  2. @H_819_301@@EnableRedisHttpSession
  3. publicclassRedisSessionConfig{
  4. }

而@EnableRedisHttpSession这个注解是由spring-session-data-redis提供的,所以在pom.xml文件添加

<dependency>
  • <groupId>org.springframework.boot</groupId>
  • <artifactId>spring-boot-starter-redis</artifactId>
  • </dependency>
  • <groupId>org.springframework.session</groupId>
  • <artifactId>spring-session-data-redis</artifactId>
  • </dependency>
  • 接下来,则需要在application.properties中配置redis服务器的位置了,在这里,我们就用本机:

    spring.redis.host=localhost
  • spring.redis.port=6379
  • 这样以来,最简单的spring boot + redis实现session共享就完成了,下面进行下测试。

    首先我们开启两个tomcat服务,端口分别为8080和9090,在application.properties中进行设置【下载地址】

    server.port=8080

    接下来定义一个Controller:

    @RestController @H_819_301@@RequestMapping(value="/admin/v1")
  • publicclassQuickRun{
  • @H_819_301@@RequestMapping(value="/first",method=RequestMethod.GET)
  • publicMap<String,Object>firstResp(HttpServletRequestrequest){
  • Map<String,Object>map=newHashMap<>();
  • request.getSession().setAttribute("requestUrl",request.getRequestURL());
  • map.put("requestUrl",153); background-color:inherit; font-weight:bold">returnmap;
  • }
  • @H_819_301@@RequestMapping(value="/sessions",153); background-color:inherit; font-weight:bold">publicObjectsessions(HttpServletRequestrequest){
  • map.put("sessionId",request.getSession().getId());
  • map.put("message",request.getSession().getAttribute("map"));
  • 启动之后进行访问测试,首先访问8080端口的tomcat,返回获取【下载地址】

    {"requestUrl":"http://localhost:8080/admin/v1/first"}
  • 接着,我们访问8080端口的sessions,返回:

    {"sessionId":"efcc85c0-9ad2-49a6-a38f-9004403776b5","message":"http://localhost:8080/admin/v1/first"}

    最后,再访问9090端口的sessions,返回:

    可见,8080与9090两个服务器返回结果一样,实现了session的共享

    如果此时再访问9090端口的first的话,首先返回:

    {"requestUrl":"http://localhost:9090/admin/v1/first"}

    而两个服务器的sessions都是返回:

    Highlighter" style="padding:0px; font-family:Consolas,"message":"http://localhost:9090/admin/v1/first"}

    通过spring boot + redis来实现session的共享非常简单,而且用处也极大,配合Nginx进行负载均衡,便能实现分布式的应用了。

    本次的redis并没有进行主从、读写分离等等配置(_(:з」∠)_其实是博主懒,还没尝试过.......)

    而且,Nginx的单点故障也是我们应用的障碍......以后可能会有对此次博客的改进版本,比如使用zookeeper进行负载均衡,敬请期待。

    原文链接:https://www.f2er.com/ajax/160718.html

    猜你在找的Ajax相关文章