填坑:H5 APP 使用 JSESSIONID 保持会话登录 时间: 2018-02-25 01:12 分类: JAVA Web,服务器,修仙日记 ####前言 这段时间给电影网站加了收费在线观看的权限,由于之前的 APP 没有添加登录模块,所以现在必须得添加上了。APP 基于 H5 MUI 开发,在实现的过程中真的是碰得焦头烂额的。 ####过程 H5 开发 APP 无非就是利用 WebView 操作 html 代码,写个登录页面简直就是顺手拈来,但是!写完登录,发现登录成功后再次发起其他的 ajax 请求,依旧是未登录状态,即 ajax 登录后服务器 response 的 `Set-Cookie` 在 WebView 中不起作用。 既然如此,那么就在登陆后保存服务器返回的 `JSESSIONID`,后面的 ajax 请求添加上 cookie,无奈 mui.ajax headers 添加 cookie 不能成功! 到 DCloud 社区搜索相关问答,官方说 `plus.navigator.setCookie()` 可以设置 WebView 的 Cookie,于是去尝试一下,发现没点作用,几经折腾,发现是离线打包的原因,在 Hbuilder 中用基座调试是没问题的,没办法由于播放器部分必须用 Android 原生代码开发,所以必须离线打包,MUI 的这个 H5 开发 APP 就是一坑,不想多说了,这个问题根本无从下手去找解决方法。 此时,代码没问题,是离线打包 SDK 的问题,头都大了,心中一万匹草泥马奔腾起来,发誓再也不用 MUI 开发 APP 了。 ####解决方案 针对这种情况,解决办法当然还是有的,只不过繁琐一些罢了。 方案一: 将 H5 中的 ajax 交由 Android 原生代码去做,这样一来设置 Http 请求的 Cookie 就不可能会有问题了,实现需做的事情:编写插件接口用 Java 代码实现带 cookie 的 http 请求,在 js 代码中调用此接口。如果 SDK 离线打包没问题的话,原本 `plus.navigator.setCookie()` 一句代码就能解决的事变得这么繁琐,不采用! 方案二: 对 Tomcat 服务器不熟悉的打破脑袋估计也想不到此方案。有点 Http 协议常识的人都知道,浏览器与服务器保持会话登录状态通常是利用 session 来实现的,当然了 cookie 也能,但是不安全。 实际上 session 的实现方案也可能需要借助 cookie(不是必需的),对于 Java Web,浏览器访问服务器,都会产生一个 JSESSIONID,大多数情况下我们看到的是存在于 Cookie 中,对于早期的一些网站都是暴露在 URL 地址中的,正因如此,可能很多人就想不到此方案。 既然 WebView 中 ajax 设置 Cookie 不成功,那么能够将 JSESSIONID 作为 http 请求参数传给服务器后台吗? 最初我的想法就是这样的: 1. ajax 登录,SpringMVC Controller 中 `session.getId()` 获取到 `JSESSIONID` 返回给客户端。 2. 接收登录返回结果,将 `JSESSIONID` 通过 `plus.storage.setItem()` 存到本地。 3. 进行需要权限的 ajax 请求时从本地获取 `JSESSIONID` 并拼接到 url 中。 上面做法有个难点就是,后端获取到 `JSESSIONID` 后如何通过 `JSESSIONID` 取得对应的 `HttpSession` 对象,经过一方搜索,几乎没有什么好的方案,唯一可行的就是通过实现 `HttpSessionListener` 接口,自己将所有的 session 都用一个 Map 保存起来,这样一来就可以通过这个 Map 来根据 `JSESSIONID` 获取对应的 session 对象了,但是,此方案不够优雅,Tomcat 本身就存储了所有的 session,这样做显得有点多此一举,并且,session 的时效性又该如何控制? 到这里,内心是崩溃的。 不到黄河心不死,关键点在于 `JSESSIONID`,于是搜索 `JSESSIONID`,很多文章都是说如何去掉 url 中的 `JSESSIONID`,看到这里,虽然不是我要找的答案,但是正好相反,我要做的是如何把这个 `JSESSIONID` 不通过 cookie 传给服务器,而是通过 url 传给后台。 于是终于找到答案: 前面也说了一下,session 实现方案是可以借助 cookie 来传递 `JSESSIONID` 或者在 url 中来传递 `JSESSIONID` 的,只是我没有想到,url 传递 `JSESSIONID` 不需要我们手动在后端来根据 `JSESSIONID`来获取对应的 session 对象,服务器都给我们做好了的。 之所以会有 url 传递`JSESSIONID`这种方案,是因为当客户端禁止了 cookie 后,为了能够客户端与服务器保持会话而做的。 到此,对于服务器的 session 又有了一个新的认识。 最终解决方案就是: http 请求地址中是用如下方式携带`JSESSIONID`的: > http://xxx.com/action;jsessionid=xxxxxxxxxxxx 和普通的 http 参数不同,它是以分号开始追加到地址后面的(参数是以问号追加)。 这样一来,服务器会自动地获取 session_id,并找到对应的 HttpSession 对象,并不需要我们手动地去获取(手动获取在前面也分析过了,没有什么好的实现方法)。所以,没错,就是这么简单,WebView cookie 设置不成功有什么大不了,直接利用 url 传递 session_id 简直方便快捷。 但是,由于之前 web.xml 配置出了点差错,那是因为服务器 session 错乱,找不到问题所在,就把 url 传递 session_id 给禁止了,也就是前面所说的很多文章关于去掉 url 中的 `jsessionid` 的,在 `web.xml`中加了下面配置: ``` COOKIE ``` 这简直是坑爹,如此设置虽然能去掉 url 中的 jsessionid,是为了好看吗?一旦客户端禁止 cookie,需要登录的会话操作就全部用不了了,现在想想,当时真的是病急乱投医。 最后老老实实去掉该段配置,就能够通过 url 的方式来传递 jsessionid 来保持登录会话状态了,问题得以解决。 标签: 无
帮我的大忙了|´・ω・)ノ