一、背景
最近在做一个机关单位的项目,他们的项目基本都是部署在内部网络中,并且都做了单点登录验证,即就是该网站上挂载了许多的系统和应用,访问其中的某一个系统和应用的时候,都会被单点登录拦截在登录页面,必须登录该网站,才能访问其中的系统及应用
二、问题描述
该项目中使用了第三方插件,即在线 Office 插件,在线 Office 插件的原理无外乎也就是和浏览器兼容一个插件,在浏览器中通过该插件调取本地的 Office 软件,例如 WPS 等。代码如下:
// 初始化插件 var Application; Application = init("yozo", "100%", $(window).height()); Application.ActionEnabledWithYozoID(4, false); Application.openDocumentRemote(serverBaseUrl + '/file/getFileStream.action?id=${id}', false); Application.enableProtect(true); Application.setToolbarAllVisible(false);
以上是在 JSP 页面中打开在线 Office 插件的部分代码。我们可以看出,我们唯一给到这个插件的东西就是文件流的地址,我们的文档都是以二进制的方式保存在数据库的
当插件调取本地 Office 软件的时候,会将这个地址传给本地 Office 软件,那么传给它的仅仅是 API 地址而已,并没有 Cookies 信息,当调取这个 API 地址时,就会被前面我们说到的单点登录给拦截到,导致获取不到数据,打不开文档
可以看出,我们在页面正常访问项目的时候,每个请求都会自动携带一个 Cookies 信息,里面放入了 JSESSIONID,这是我们通过单点登录的唯一凭证
三、解决方案
既然本地 Office 软件在发起请求的时候没有带上 Cookies 信息,那么就只有我们手动给它传输 Cookies 信息了
- 1、获取 JSESSIONID
<%String sessionId = request.getSession().getId();%>
- 2、手动传输 Cookies 信息
Application.openDocumentRemote(serverBaseUrl + '/file/getFileStream.action;jsessionid=<%=sessionId%>?id=${id}', false);
这里尤为注意,不能将 jsessionid 跟在参数后面,这样服务器会把 jsessionid 作为参数处理,也是无法传输 Cookies 信息的
这样,我们就在请求地址中手动传入了 Cookies 信息,可以通过登录验证了