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


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

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

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

一些帖子供参考

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. @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
  • @RequestMapping(value="/admin/v1")
  • publicclassQuickRun{
  • @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;
  • }
  • @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进行负载均衡,敬请期待。

  • 总结

    以上是DEVMAX为你收集整理的ajax 跨域 session 及 spring boot分布式session全部内容。

    如果觉得DEVMAX网站内容还不错,欢迎将DEVMAX网站推荐给好友。

    ajax 跨域 session 及 spring boot分布式session的更多相关文章

    1. HTML5 Web缓存和运用程序缓存(cookie,session)

      这篇文章主要介绍了HTML5 Web缓存和运用程序缓存(cookie,session),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    2. 关于h5中的fetch方法解读(小结)

      这篇文章主要介绍了关于h5中的fetch方法解读(小结),fetch身为H5中的一个新对象,他的诞生,是为了取代ajax的存在而出现,有兴趣的可以了解一下

    3. iOS Swift上弃用后Twitter.sharedInstance().session()?. userName的替代方案

      解决方法如果您仍在寻找解决方案,请参阅以下内容:

    4. 使用Fabric SDK iOS访问Twitter用户时间线

      我试图在这个问题上挣扎两天.我正在使用FabricSDK和Rest工具包,试图为Twitter使用不同的RestAPIWeb服务.我可以使用具有authTokenSecret,authToken和其他值的会话对象的TWTRLogInButton成功登录.当我尝试获取用户时间线时,我总是得到失败的响应,作为:{“errors”:[{“code”:215,“message”:“BadAuthentic

    5. ios – 如何在Swift中手动为UIWebView设置Cookie

      我需要在swift中为webview设置一个cookie.我找到了一个解决方案,但它是针对objective-c的.如何在Swift中做到这一点?

    6. ios – 如何从Apple Watch调用iPhone上定义的方法

      有没有办法从Watchkit扩展中调用iPhone上的类中定义的方法?根据我的理解,目前在Watchkit和iPhone之间进行本地通信的方法之一是使用NSUserDefaults,但还有其他方法吗?

    7. 通过在iOS中处理cookie来维护会话信息

      我是iOS开发的新手.我正在使用NSURLSession来管理会话信息.下面是我用来调用任何服务器API的示例代码,我的申请流程是,如果没有登录–>登录(呼叫登录api)Else转到主屏幕并调用其他API.我的问题是,一旦从内存中删除应用程序,会话信息就不会被维护,我不得不再次调用Login.我的要求就像Facebook一样,用户只需登录一次,并且在下次应用程序启动时保持会话.编辑:我想我必须通过

    8. 如何使用iOS SDK保存LinkedIn访问令牌?

      我在我的iOS应用程序中使用LinkedIn.我想保存访问令牌以供将来使用.令牌属于非属性类型,无法直接保存在NSUserDefaults中.我尝试使用NSKeyedArchiver,但我得到了输出:令牌中的文本即将到来,但值将为空.代码段1:我也尝试像这样保存,但结果是一样的:代码段2:我的编码或访问令牌有什么问题需要一些特殊技术来保存吗?请建议.解决方法这就是我拯救的方式.它对我有用.希望它有所帮助以这种方式使用保存的responseBody我希望这次我很清楚

    9. ios – 以http无效的自定义URL方案开头

      我在应用程序中使用了自定义URL方案.我成功地从safari重定向到我的应用程序.就像我已经制作了URL方案“appname”.请检查http://prntscr.com/2cjx0p.我需要使用像iosurlredirectfrommailtoapp这样的解决方案,但我不确定如何设置cookie.我发现我必须首先在我的应用程序中为服务器“http://myappname.com”设置一个cook

    10. ios – 如何将视频从AVAssetExportSession保存到相机胶卷?

      在此先感谢您的帮助.解决方法只需使用session.outputURL=…

    随机推荐

    1. xe-ajax-mock 前端虚拟服务

      最新版本见Github,点击查看历史版本基于XEAjax扩展的Mock虚拟服务插件;对于前后端分离的开发模式,ajax+mock使前端不再依赖后端接口开发效率更高。CDN使用script方式安装,XEAjaxMock会定义为全局变量生产环境请使用xe-ajax-mock.min.js,更小的压缩版本,可以带来更快的速度体验。

    2. vue 使用 xe-ajax

      安装完成后自动挂载在vue实例this.$ajaxCDN安装使用script方式安装,VXEAjax会定义为全局变量生产环境请使用vxe-ajax.min.js,更小的压缩版本,可以带来更快的速度体验。cdnjs获取最新版本点击浏览已发布的所有npm包源码unpkg获取最新版本点击浏览已发布的所有npm包源码AMD安装require.js安装示例ES6Module安装通过Vue.use()来全局安装示例./Home.vue

    3. AJAX POST数据中文乱码解决

      前端使用encodeURI进行编码后台java.net.URLDecoder进行解码编解码工具

    4. Koa2框架利用CORS完成跨域ajax请求

      实现跨域ajax请求的方式有很多,其中一个是利用CORS,而这个方法关键是在服务器端进行配置。本文仅对能够完成正常跨域ajax响应的,最基本的配置进行说明。这样OPTIONS请求就能够通过了。至此为止,相当于仅仅完成了预检,还没发送真正的请求呢。

    5. form提交时,ajax上传文件并更新到&lt;input&gt;中的value字段

    6. ajax的cache作用

      filePath="+escape;},error:{alert;}});解决方案:1.加cache:false2.url加随机数正常代码:网上高人解读:cache的作用就是第一次请求完毕之后,如果再次去请求,可以直接从缓存里面读取而不是再到服务器端读取。

    7. 浅谈ajax上传文件属性contentType = false

      默认值为contentType="application/x-www-form-urlencoded".在默认情况下,内容编码类型满足大多数情况。在这里,我们主要谈谈contentType=false.在使用ajax上传文件时:在其中先封装了一个formData对象,然后使用post方法将文件传给服务器。说到这,我们发现在JQueryajax()方法中我们使contentType=false,这不是冲突了吗?这就是因为当我们在form标签中设置了enctype=“multipart/form-data”,

    8. 909422229_ajaxFileUpload上传文件

      ajaxFileUpload.js很多同名的,因为做出来一个很容易。我上github搜AjaxFileUpload出来很多类似js。ajaxFileUpload是一个异步上传文件的jQuery插件传一个不知道什么版本的上来,以后不用到处找了。语法:$.ajaxFileUploadoptions参数说明:1、url上传处理程序地址。2,fileElementId需要上传的文件域的ID,即的ID。3,secureuri是否启用安全提交,默认为false。4,dataType服务器返回的数据类型。6,error

    9. AJAX-Cache:一款好用的Ajax缓存插件

      原文链接AJAX-Cache是什么Ajax是前端开发必不可少的数据获取手段,在频繁的异步请求业务中,我们往往需要利用“缓存”提升界面响应速度,减少网络资源占用。AJAX-Cache是一款jQuery缓存插件,可以为$.ajax()方法扩展缓存功能。

    10. jsf – Ajax update/render在已渲染属性的组件上不起作用

      我试图ajax更新一个有条件渲染的组件。我可以确保#{user}实际上是可用的。这是怎么引起的,我该如何解决呢?必须始终在ajax可以重新呈现之前呈现组件。Ajax正在使用JavaScriptdocument.getElementById()来查找需要更新的组件。但是如果JSF没有将组件放在第一位,那么JavaScript找不到要更新的内容。解决方案是简单地引用总是渲染的父组件。

    返回
    顶部