Backbone.Sync Safari 问题
Backbone.Sync issue with Safari
我有一个 backbone 应用程序,我在其中使用 dualStorage 并为 Backbone 实现了我自己的同步。我实现了自己的同步,因为在我的 API 中它要求在每个请求的 header 中发送身份验证令牌。如果此身份验证令牌不存在或无效,则 API returns 出现 401 错误。
我的应用程序有两个选项卡,当您单击其中一个时,它会将路由从 /#guestlist 切换到 /#ticketlist,反之亦然。此问题仅在切换选项卡时发生,而在转到应用程序中的任何其他路由时不会发生。这就是这个问题让我感到非常奇怪的地方,只有这两个请求失败并且应该覆盖所有同步操作。
我遇到的问题似乎只存在于 Safari 中,而不存在于 Chrome 或 Firefox 中,但是由于这将 运行 主要出现在 iPad 上,我不能只忽略这个问题。
这是手头的问题
1.) 登录系统,一切正常 UI 由 API 数据填充
2.) 单击工单列表选项卡,系统将您注销。这是因为请求中不存在 API returns 作为身份验证令牌的 401(同样仅在 safari 中)
[Error] Failed to load resource: the server responded with a status of 401 (Unauthorized) (ticketlist, line 0)
下面是我的 Backbone.sync.
代码
/*
* Store a version of Backbone.sync to call from the
* modified version we create
*/
var _nativeSync = Backbone.sync;
Backbone.sync = function (method, model, options) {
/*
* The jQuery `ajax` method includes a 'headers' option
* which lets you set any headers you like
*/
if(CheckinApp.getSession().isAuthenticated() !== false) {
/*
* Set the 'Authorization' header and get the access
* token from the `auth` module
*/
options.headers = {
'Authorization': 'Token ' + CheckinApp.getSession().getAuthorizationToken()
}
}
/*
* Call the stored original Backbone.sync method with
* extra headers argument added
*/
_nativeSync(method, model, options);
};
我唯一担心的是,这可能与使用 dualStorage 产生冲突,因为我知道它也会覆盖 Backbone.sync 方法。为了让它工作,我必须在 dualStorage 之后包括我的同步,如下所示。
<script type="text/javascript" src="js/vendor/backbone.dualstorage.min.js"></script>
<script type="text/javascript" src="js/plugins/backbone.sync.js"></script>
我还在 API 端转储了请求的 headers 并且可以看到当从 Safari 发出但不在同一个请求时,此特定请求缺少授权令牌chrome 或 firefox 发出的请求。
[Tue Apr 07 14:49:08.677473 2015] [:error] [pid 16743] [client 71.181.125.154:64016] <pre>Array\n(\n
[Host] => jcrawford.heytix.com\n
[User-Agent] => Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.78.2 (KHTML, like Gecko) Version/6.1.6 Safari/537.78.2\n
[Accept] => application/json, text/javascript, */*; q=0.01\n [
Referer] => http://jcrawford.heytix.com/guestlist/\n
[X-Requested-With] => XMLHttpRequest\n
[Authorization] => Token 951ba59c833a80e4ddaf72ee6b3d9143\n
[Accept-Language] => en-us\n [Accept-Encoding] => gzip, deflate\n
[Cookie] => 'removed from output'
[Connection] => keep-alive\n)\n</pre>, referer: http://jcrawford.heytix.com/guestlist/
[Tue Apr 07 14:49:12.027279 2015] [:error] [pid 16743] [client 71.181.125.154:64016] <pre>Array\n(\n
[Host] => jcrawford.heytix.com\n
[User-Agent] => Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.78.2 (KHTML, like Gecko) Version/6.1.6 Safari/537.78.2\n
[Accept] => application/json, text/javascript, */*; q=0.01\n
[Referer] => http://jcrawford.heytix.com/guestlist/\n
[Accept-Encoding] => gzip, deflate\n
[X-Requested-With] => XMLHttpRequest\n
[Accept-Language] => en-us\n
[Cookie] => 'removed from output'
[Connection] => keep-alive\n)\n</pre>, referer: http://jcrawford.heytix.com/guestlist/
[Tue Apr 07 14:49:12.027565 2015] [:error] [pid 16743] [client 71.181.125.154:64016] HTTP 401 (GET /api/events/13044/guestlist), referer: http://jcrawford.heytix.com/guestlist/
这就是我使用 chrome 和/或 firefox 得到的结果。
[Tue Apr 07 14:57:38.686859 2015] [:error] [pid 17630] [client 71.181.125.154:65109] <pre>Array\n(
[Host] => jcrawford.heytix.com
[Connection] => keep-alive
[Cache-Control] => max-age=0
[Accept] => application/json, text/javascript, */*; q=0.01
[X-Requested-With] => XMLHttpRequest
[User-Agent] => Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.104 Safari/537.36
[Authorization] => Token 951ba59c833a80e4ddaf72ee6b3d9143
[Referer] => http://jcrawford.heytix.com/guestlist/
[Accept-Encoding] => gzip, deflate, sdch
[Accept-Language] => en-US,en;q=0.8
[Cookie] => 'removed from output'
)</pre>, referer: http://jcrawford.heytix.com/guestlist/
[Tue Apr 07 14:57:44.001465 2015] [:error] [pid 17492] [client 71.181.125.154:65106] <pre>Array\n(\n
[Host] => jcrawford.heytix.com\n
[Connection] => keep-alive\n
[Accept] => application/json, text/javascript, */*; q=0.01\n
[X-Requested-With] => XMLHttpRequest\n
[User-Agent] => Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.104 Safari/537.36\n
[Authorization] => Token 951ba59c833a80e4ddaf72ee6b3d9143\n
[Referer] => http://jcrawford.heytix.com/guestlist/\n
[Accept-Encoding] => gzip, deflate, sdch\n
[Accept-Language] => en-US,en;q=0.8\n
[Cookie] => 'removed from output'
)\n</pre>, referer: http://jcrawford.heytix.com/guestlist/
正如您从上面的日志中看到的,授权令牌是通过 Firefox/Chrome 传递的,但不是通过 Safari 传递的。我已将日志记录添加到同步方法,它在控制台中声明用户在查询 API 之前已通过身份验证,然后重定向到登录页面。
[Log] sync called, isAuthenticated: true (backbone.sync.js, line 12)
[Error] Failed to load resource: the server responded with a status of 401 (Unauthorized) (ticketlist, line 0)
我在 Safari 开发者 tools/console 中没有看到任何其他错误或任何内容。应用程序向 API 发出请求,得到 401(如预期的那样没有令牌)并且然后将用户从 Backbone 应用程序注销并重定向到登录页面。当没有令牌存在时,这种行为是预期的问题是为什么这不会为这些特定路由传递令牌?只有这些路线导致了问题,所有其他路线似乎在 UI.
中都可以正常工作
我还将提供我的路由器,以便您可以看到发生了什么,请记住,我大部分时间都在使用事件来进行实际路由,所以如果您需要查看任何其他代码,请让我知道。
CheckinApp.Routers.Default = Backbone.Router.extend({
view: null,
public_routes: ['login'],
routes:{
"":"eventlist",
"login": "login",
"guestlist": "guestlist",
"ticketlist":"ticketlist",
"managerslist":"managerslist",
"events": "eventlist",
"organize(/)(:action)": "displayOrganize",
"eventreport(/)(:event_id)": "eventreport",
"venuereport(/)(:venue_name)": "venuereport"
},
initialize:function (options) {
this.view = options.view;
Backbone.history.start();
},
guestlist:function () {
CheckinApp.getVent().trigger('main:renderListView', {title: 'Guest List', type: 'ticket', tab_hash: '#guestlist'});
},
ticketlist:function () {
CheckinApp.getVent().trigger('main:renderListView', {title: 'Ticket List', type: 'ticket', tab_hash: '#ticketlist'});
},
managerslist:function () {
CheckinApp.getVent().trigger('main:renderListView', {title: 'Managers List', type: 'ticket', tab_hash: '#managerslist'});
},
eventlist: function() {
var vent = CheckinApp.getVent();
vent.trigger('main:renderListView', {title: 'Todays Events', type: 'event'});
vent.trigger('tabs:remove');
},
eventreport: function() {
var collection = new CheckinApp.Collections.EventReport({"event_id": 13044});
var view = new CheckinApp.Views.EventReport({collection: collection});
view.render();
},
venuereport: function(venue_name) {
var collection = new CheckinApp.Collections.VenueReport([], {"venue_name": 'borgata'});
var view = new CheckinApp.Views.VenueReport({collection: collection});
var modal = new Backbone.BootstrapModal({
content: view,
title: ' ',
animate: true
});
modal.open();
//view.render();
},
login: function() {
var view = new CheckinApp.Views.Login({});
view.render();
},
before: function (route, params) {
if($.cookie('CheckinApp') && CheckinApp.getSession().isAuthenticated() == false) {
CheckinApp.setSessionFromCookie(JSON.parse($.cookie('CheckinApp')));
}
var hasAccess = CheckinApp.getSession().isAuthenticated(); // If cookie exists they are logged in..
if (!hasAccess) {
this.navigate('login', true);
} else {
if(route == 'login') {
this.navigate('', true);
return false;
}
}
if((_.contains(this.public_routes, route) === false)) {
return hasAccess; //return true if you want to proceed to routes else return false
}
},
after: function(route, params) {
if(route == 'logout') return false;
else {
CheckinApp.updateCookie();
return true;
}
}
});
最后是告诉 jQuery 侦听 401 并在发生时注销用户的代码。
$.ajaxSetup({
statusCode: {
401: function () {
CheckinApp.clearSession();
Backbone.history.navigate('#login', true);
}
}
});
我还更进一步,在之前的路由中添加了一堆 console.log 语句,并得出了这个结果。看起来可能正在对这些特定路由进行某些操作导致身份验证丢失?
[Log] sync : isAuthenticated = true (backbone.sync.js, line 12)
[Log] sync: url = http://jcrawford.heytix.com/guestlist/checkin/api/events/13044/guestlist/ (backbone.sync.js, line 13)
[Error] Failed to load resource: the server responded with a status of 401 (Unauthorized) (guestlist, line 0)
[Log] before : isAuthenticated: false (default.js, line 60)
[Log] cookie: undefined (default.js, line 61)
[Log] before : hasAccess = false (default.js, line 66)
[Log] before : hasAccess = false, going to login page (default.js, line 68)
[Log] before : going to route login (default.js, line 76)
如您所见,就在 AJAX 请求数据的那一行之前,它说已验证然后请求失败,它说未验证。
这次我的同步方法记录了一些日志
sync : isAuthenticated = true (backbone.sync.js, line 12)
sync: url = http://jcrawford.heytix.com/guestlist/checkin/api/events/13044/guestlist/ (backbone.sync.js, line 13)
User is Authenticated (backbone.sync.js, line 15)
options: {"parse":true,"headers":{"Authorization":"Token 951ba59c833a80e4ddaf72ee6b3d9143"}} (backbone.sync.js, line 24)
正如您在上面看到的,选项正在 header 上设置,但由于某些原因,当使用 Safari 时 Backbone 没有发送这些带有同步请求的 header。
根据一些建议(以及下面的建议),我尝试为 jQuery 修改我的 $.ajaxSetup,但我收到的结果与我目前遇到的完全相同。
$.ajaxSetup({
headers: function() {
var token = '';
if(CheckinApp) {
var session = CheckinApp.getSession();
if(session) {
token = CheckinApp.getSession().getAuthorizationToken();
}
}
return {
"Authorization": "Token " + token
};
},
statusCode: {
401: function () {
CheckinApp.clearSession();
Backbone.history.navigate('#login', true);
}
}
});
如有任何帮助,我们将不胜感激。
您是否尝试过直接将 $.ajaxSetup()
与令牌一起使用,看看是否可以在 safari 中重现同样的问题?对于您的示例,不确定如何在您的路由器中调用 before
和 after
函数,但看起来您可以在那里设置 ajax 设置,因为您已经在那里检查 hasAccess() 了。
示例:
$.ajaxSetup({
headers: { 'Authorization' : 'Token ' + howeverYouGetToken() }
});
发生此问题完全是因为我的票 Collection URL 包含尾随 /
在尾随 / 就位的情况下,Safari 会向带有尾随斜杠的 URL 发送 pre-flight 请求,并收到 302 Found。然后它会向没有尾部斜杠的 URI 发出请求,并收到 401 作为第二个请求,而不是授权令牌被传递给 API.
我不太确定这是 Backbone 还是 jQuery 的问题,但无论哪一个似乎都不喜欢尾部斜杠,因为删除它解决了 Safari 问题。
我有一个 backbone 应用程序,我在其中使用 dualStorage 并为 Backbone 实现了我自己的同步。我实现了自己的同步,因为在我的 API 中它要求在每个请求的 header 中发送身份验证令牌。如果此身份验证令牌不存在或无效,则 API returns 出现 401 错误。
我的应用程序有两个选项卡,当您单击其中一个时,它会将路由从 /#guestlist 切换到 /#ticketlist,反之亦然。此问题仅在切换选项卡时发生,而在转到应用程序中的任何其他路由时不会发生。这就是这个问题让我感到非常奇怪的地方,只有这两个请求失败并且应该覆盖所有同步操作。
我遇到的问题似乎只存在于 Safari 中,而不存在于 Chrome 或 Firefox 中,但是由于这将 运行 主要出现在 iPad 上,我不能只忽略这个问题。
这是手头的问题
1.) 登录系统,一切正常 UI 由 API 数据填充 2.) 单击工单列表选项卡,系统将您注销。这是因为请求中不存在 API returns 作为身份验证令牌的 401(同样仅在 safari 中)
[Error] Failed to load resource: the server responded with a status of 401 (Unauthorized) (ticketlist, line 0)
下面是我的 Backbone.sync.
代码/*
* Store a version of Backbone.sync to call from the
* modified version we create
*/
var _nativeSync = Backbone.sync;
Backbone.sync = function (method, model, options) {
/*
* The jQuery `ajax` method includes a 'headers' option
* which lets you set any headers you like
*/
if(CheckinApp.getSession().isAuthenticated() !== false) {
/*
* Set the 'Authorization' header and get the access
* token from the `auth` module
*/
options.headers = {
'Authorization': 'Token ' + CheckinApp.getSession().getAuthorizationToken()
}
}
/*
* Call the stored original Backbone.sync method with
* extra headers argument added
*/
_nativeSync(method, model, options);
};
我唯一担心的是,这可能与使用 dualStorage 产生冲突,因为我知道它也会覆盖 Backbone.sync 方法。为了让它工作,我必须在 dualStorage 之后包括我的同步,如下所示。
<script type="text/javascript" src="js/vendor/backbone.dualstorage.min.js"></script>
<script type="text/javascript" src="js/plugins/backbone.sync.js"></script>
我还在 API 端转储了请求的 headers 并且可以看到当从 Safari 发出但不在同一个请求时,此特定请求缺少授权令牌chrome 或 firefox 发出的请求。
[Tue Apr 07 14:49:08.677473 2015] [:error] [pid 16743] [client 71.181.125.154:64016] <pre>Array\n(\n
[Host] => jcrawford.heytix.com\n
[User-Agent] => Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.78.2 (KHTML, like Gecko) Version/6.1.6 Safari/537.78.2\n
[Accept] => application/json, text/javascript, */*; q=0.01\n [
Referer] => http://jcrawford.heytix.com/guestlist/\n
[X-Requested-With] => XMLHttpRequest\n
[Authorization] => Token 951ba59c833a80e4ddaf72ee6b3d9143\n
[Accept-Language] => en-us\n [Accept-Encoding] => gzip, deflate\n
[Cookie] => 'removed from output'
[Connection] => keep-alive\n)\n</pre>, referer: http://jcrawford.heytix.com/guestlist/
[Tue Apr 07 14:49:12.027279 2015] [:error] [pid 16743] [client 71.181.125.154:64016] <pre>Array\n(\n
[Host] => jcrawford.heytix.com\n
[User-Agent] => Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.78.2 (KHTML, like Gecko) Version/6.1.6 Safari/537.78.2\n
[Accept] => application/json, text/javascript, */*; q=0.01\n
[Referer] => http://jcrawford.heytix.com/guestlist/\n
[Accept-Encoding] => gzip, deflate\n
[X-Requested-With] => XMLHttpRequest\n
[Accept-Language] => en-us\n
[Cookie] => 'removed from output'
[Connection] => keep-alive\n)\n</pre>, referer: http://jcrawford.heytix.com/guestlist/
[Tue Apr 07 14:49:12.027565 2015] [:error] [pid 16743] [client 71.181.125.154:64016] HTTP 401 (GET /api/events/13044/guestlist), referer: http://jcrawford.heytix.com/guestlist/
这就是我使用 chrome 和/或 firefox 得到的结果。
[Tue Apr 07 14:57:38.686859 2015] [:error] [pid 17630] [client 71.181.125.154:65109] <pre>Array\n(
[Host] => jcrawford.heytix.com
[Connection] => keep-alive
[Cache-Control] => max-age=0
[Accept] => application/json, text/javascript, */*; q=0.01
[X-Requested-With] => XMLHttpRequest
[User-Agent] => Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.104 Safari/537.36
[Authorization] => Token 951ba59c833a80e4ddaf72ee6b3d9143
[Referer] => http://jcrawford.heytix.com/guestlist/
[Accept-Encoding] => gzip, deflate, sdch
[Accept-Language] => en-US,en;q=0.8
[Cookie] => 'removed from output'
)</pre>, referer: http://jcrawford.heytix.com/guestlist/
[Tue Apr 07 14:57:44.001465 2015] [:error] [pid 17492] [client 71.181.125.154:65106] <pre>Array\n(\n
[Host] => jcrawford.heytix.com\n
[Connection] => keep-alive\n
[Accept] => application/json, text/javascript, */*; q=0.01\n
[X-Requested-With] => XMLHttpRequest\n
[User-Agent] => Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.104 Safari/537.36\n
[Authorization] => Token 951ba59c833a80e4ddaf72ee6b3d9143\n
[Referer] => http://jcrawford.heytix.com/guestlist/\n
[Accept-Encoding] => gzip, deflate, sdch\n
[Accept-Language] => en-US,en;q=0.8\n
[Cookie] => 'removed from output'
)\n</pre>, referer: http://jcrawford.heytix.com/guestlist/
正如您从上面的日志中看到的,授权令牌是通过 Firefox/Chrome 传递的,但不是通过 Safari 传递的。我已将日志记录添加到同步方法,它在控制台中声明用户在查询 API 之前已通过身份验证,然后重定向到登录页面。
[Log] sync called, isAuthenticated: true (backbone.sync.js, line 12)
[Error] Failed to load resource: the server responded with a status of 401 (Unauthorized) (ticketlist, line 0)
我在 Safari 开发者 tools/console 中没有看到任何其他错误或任何内容。应用程序向 API 发出请求,得到 401(如预期的那样没有令牌)并且然后将用户从 Backbone 应用程序注销并重定向到登录页面。当没有令牌存在时,这种行为是预期的问题是为什么这不会为这些特定路由传递令牌?只有这些路线导致了问题,所有其他路线似乎在 UI.
中都可以正常工作我还将提供我的路由器,以便您可以看到发生了什么,请记住,我大部分时间都在使用事件来进行实际路由,所以如果您需要查看任何其他代码,请让我知道。
CheckinApp.Routers.Default = Backbone.Router.extend({
view: null,
public_routes: ['login'],
routes:{
"":"eventlist",
"login": "login",
"guestlist": "guestlist",
"ticketlist":"ticketlist",
"managerslist":"managerslist",
"events": "eventlist",
"organize(/)(:action)": "displayOrganize",
"eventreport(/)(:event_id)": "eventreport",
"venuereport(/)(:venue_name)": "venuereport"
},
initialize:function (options) {
this.view = options.view;
Backbone.history.start();
},
guestlist:function () {
CheckinApp.getVent().trigger('main:renderListView', {title: 'Guest List', type: 'ticket', tab_hash: '#guestlist'});
},
ticketlist:function () {
CheckinApp.getVent().trigger('main:renderListView', {title: 'Ticket List', type: 'ticket', tab_hash: '#ticketlist'});
},
managerslist:function () {
CheckinApp.getVent().trigger('main:renderListView', {title: 'Managers List', type: 'ticket', tab_hash: '#managerslist'});
},
eventlist: function() {
var vent = CheckinApp.getVent();
vent.trigger('main:renderListView', {title: 'Todays Events', type: 'event'});
vent.trigger('tabs:remove');
},
eventreport: function() {
var collection = new CheckinApp.Collections.EventReport({"event_id": 13044});
var view = new CheckinApp.Views.EventReport({collection: collection});
view.render();
},
venuereport: function(venue_name) {
var collection = new CheckinApp.Collections.VenueReport([], {"venue_name": 'borgata'});
var view = new CheckinApp.Views.VenueReport({collection: collection});
var modal = new Backbone.BootstrapModal({
content: view,
title: ' ',
animate: true
});
modal.open();
//view.render();
},
login: function() {
var view = new CheckinApp.Views.Login({});
view.render();
},
before: function (route, params) {
if($.cookie('CheckinApp') && CheckinApp.getSession().isAuthenticated() == false) {
CheckinApp.setSessionFromCookie(JSON.parse($.cookie('CheckinApp')));
}
var hasAccess = CheckinApp.getSession().isAuthenticated(); // If cookie exists they are logged in..
if (!hasAccess) {
this.navigate('login', true);
} else {
if(route == 'login') {
this.navigate('', true);
return false;
}
}
if((_.contains(this.public_routes, route) === false)) {
return hasAccess; //return true if you want to proceed to routes else return false
}
},
after: function(route, params) {
if(route == 'logout') return false;
else {
CheckinApp.updateCookie();
return true;
}
}
});
最后是告诉 jQuery 侦听 401 并在发生时注销用户的代码。
$.ajaxSetup({
statusCode: {
401: function () {
CheckinApp.clearSession();
Backbone.history.navigate('#login', true);
}
}
});
我还更进一步,在之前的路由中添加了一堆 console.log 语句,并得出了这个结果。看起来可能正在对这些特定路由进行某些操作导致身份验证丢失?
[Log] sync : isAuthenticated = true (backbone.sync.js, line 12)
[Log] sync: url = http://jcrawford.heytix.com/guestlist/checkin/api/events/13044/guestlist/ (backbone.sync.js, line 13)
[Error] Failed to load resource: the server responded with a status of 401 (Unauthorized) (guestlist, line 0)
[Log] before : isAuthenticated: false (default.js, line 60)
[Log] cookie: undefined (default.js, line 61)
[Log] before : hasAccess = false (default.js, line 66)
[Log] before : hasAccess = false, going to login page (default.js, line 68)
[Log] before : going to route login (default.js, line 76)
如您所见,就在 AJAX 请求数据的那一行之前,它说已验证然后请求失败,它说未验证。
这次我的同步方法记录了一些日志
sync : isAuthenticated = true (backbone.sync.js, line 12)
sync: url = http://jcrawford.heytix.com/guestlist/checkin/api/events/13044/guestlist/ (backbone.sync.js, line 13)
User is Authenticated (backbone.sync.js, line 15)
options: {"parse":true,"headers":{"Authorization":"Token 951ba59c833a80e4ddaf72ee6b3d9143"}} (backbone.sync.js, line 24)
正如您在上面看到的,选项正在 header 上设置,但由于某些原因,当使用 Safari 时 Backbone 没有发送这些带有同步请求的 header。
根据一些建议(以及下面的建议),我尝试为 jQuery 修改我的 $.ajaxSetup,但我收到的结果与我目前遇到的完全相同。
$.ajaxSetup({
headers: function() {
var token = '';
if(CheckinApp) {
var session = CheckinApp.getSession();
if(session) {
token = CheckinApp.getSession().getAuthorizationToken();
}
}
return {
"Authorization": "Token " + token
};
},
statusCode: {
401: function () {
CheckinApp.clearSession();
Backbone.history.navigate('#login', true);
}
}
});
如有任何帮助,我们将不胜感激。
您是否尝试过直接将 $.ajaxSetup()
与令牌一起使用,看看是否可以在 safari 中重现同样的问题?对于您的示例,不确定如何在您的路由器中调用 before
和 after
函数,但看起来您可以在那里设置 ajax 设置,因为您已经在那里检查 hasAccess() 了。
示例:
$.ajaxSetup({
headers: { 'Authorization' : 'Token ' + howeverYouGetToken() }
});
发生此问题完全是因为我的票 Collection URL 包含尾随 /
在尾随 / 就位的情况下,Safari 会向带有尾随斜杠的 URL 发送 pre-flight 请求,并收到 302 Found。然后它会向没有尾部斜杠的 URI 发出请求,并收到 401 作为第二个请求,而不是授权令牌被传递给 API.
我不太确定这是 Backbone 还是 jQuery 的问题,但无论哪一个似乎都不喜欢尾部斜杠,因为删除它解决了 Safari 问题。