首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

spring-cloud oauth2与前端跨域问题解决始末

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来抛出异常的,那我这么改造一下:

再次访问,完美解决。。。。。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190108G01LBK00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券