spring-cloud oauth2与前端跨域问题
By sam
发表于 2019-01-07
文章目录
1.问题描述
1.1.1.readyState 状态 状态说明
1.1.关于readystate五个状态总结
2.系统架构
问题描述
架构是前后端分离的,也就是说前端可能是在不同的服务器,甚至在不同域名下的。
那这样的话,势必有跨域问题,而正常的跨域问题,springboot都已经提供了解决方案,即在BackGatewayApplication启动类上添加如下filter:
或者还有更方便的:
目前遇到的问题是,前端通过ajax请求,如果传了一个失效的token,则前端会直接报错,显示的是这样的:
看着像是说跨域问题。
但是,我们之前遇到的跨域大部分是浏览器的行为,将请求拦截了,但是这个不同的是他的请求发出去了,服务端也接收到了请求,并返回了,返回的失效token的提示,通过postman或者curl工具能正常返回,并且还有状态码:
paste image
但是通过ajax请求浏览器访问,却总是出现error,以下是用jquery的ajax请求:
调用ajax请求后,总是直接调用了error的回调方法,并在控制台打印:
paste image
打印的xhr是:
关于readystate五个状态总结
readyState 状态 状态说明
(0)未初始化
此阶段确认XMLHttpRequest对象是否创建,并为调用open()方法进行未初始化作好准备。值为0表示对象已经存在,否则浏览器会报错--对象不存在。
(1)载入
此阶段对XMLHttpRequest对象进行初始化,即调用open()方法,根据参数(method,url,true)完成对象状态的设置。并调用send()方法开始向服务端发送请求。值为1表示正在向服务端发送请求。
(2)载入完成
此阶段接收服务器端的响应数据。但获得的还只是服务端响应的原始数据,并不能直接在客户端使用。值为2表示已经接收完全部响应数据。并为下一阶段对数据解析作好准备。
(3)交互
此阶段解析接收到的服务器端响应数据。即根据服务器端响应头部返回的MIME类型把数据转换成能通过responseBody、responseText或responseXML属性存取的格式,为在客户端调用作好准备。状态3表示正在解析数据。
(4)完成
此阶段确认全部数据都已经解析为客户端可用的格式,解析已经完成。值为4表示数据解析完毕,可以通过XMLHttpRequest对象的相应属性取得数据。
概而括之,整个XMLHttpRequest对象的生命周期应该包含如下阶段:
创建-初始化请求-发送请求-接收数据-解析数据-完成
readyState为0,了解了一下,出现这种情况,xhr中readyState为0的几种情况:
引用官方对XMLHttpRequest的说明:
http://www.w3.org/TR/XMLHttpRequest/
The status attribute must return the result of running these steps:
status的值一定会返回运行这些步骤的结果。
1、If the state is UNSENT or OPENED, return 0.(如果状态是UNSENT或者OPENED,返回0)
2、If the error flag is set, return 0.(如果错误标签被设置,返回0)
3、Return the HTTP status code.(返回HTTP状态码)
而根据我得到的error错误,第一反应是跨域访问,被浏览器拒绝了,但是,关键是我服务端收到了请求。
还有一种情况,也是会导致state的状态为0的,就是:
If the cross-origin request status is network error
虽然去访问了,应该是浏览器跨域的返回头没有被允许,所以浏览器阻止返回的响应,Access-Control-Allow-Origin 浏览器没有发现这个属性的设置,所以就报跨域,也就是服务器在响应头里也要设置跨域处理,不然也会出现这种情况。
那么,我就在response的header设置一下:
再次访问,就得到了状态码:
paste image
![paste image]
而这次是在complete方法里取得了xhr:
得到的状态值是4,status值是403。
在这里还没完,因为我用的是security+oauth2,在gateway处理所有资源请求的权限认证的,而在oauth2这里,确有个头疼的问题,在token失效的时候,我就拿不到readyState,也一直是0,说这个问题的之前,先来说下我的架构。
系统架构
目前我的服务请求流程大致是这样:
paste image
所有的资源请求都经过gateway转发并在gateway认证(在oauth2里把gateway作为一个总的资源服务器配置来校验各资源服务器的权限),调用认证服务器去校验token的正确性。
而oauth2的工作流程大致是:
OAuth2AuthenticationProcessingFilter:
然后是OAuth2AuthenticationManager:
再UserInfoTokenServices:
这段很关键,
有这个key就会抛出InvalidTokenException异常。
然后当中的this.getMap(…)这个方法很重要,我们看看:
这个方法是调用认证服务器获取用户信息的接口,也就是我写在认证服务器的一个接口:
很显然,如果我传的token是过期的token,那这个返回的user肯定是null,通过调试,果然如此,但是,按理说应该会被catch掉,但是,因为返回的是null,却没走这里,不知道为什么,可能是被其它的filter或者监听器给捕获了,那么,我只能让它不返回null,但又不能破坏oauth2原有的规则,既然是通过返回的map里面的key来判断是否有error来抛出异常的,那我这么改造一下:
再次访问,完美解决。。。。。
领取专属 10元无门槛券
私享最新 技术干货