向每个骨干网同步请求发送令牌

我的PHP API需要提交用户令牌,以及来自我的前端Backbone应用程序的每个请求,以确保用户...

  • 活跃
  • 有权限访问资源
  • 在Backbone中设置这个最简单的方法是什么? 我猜测唯一的办法是覆盖Backbone.sync,但代码是什么样子? CoffeeScript首选。

    编辑

    还有两件事
    1.如果我得到403: Access Forbidden Error我想将用户重定向到/login
    2.当应用程序启动时,我从localStorage中提取包含令牌的用户模型
    3.我有一个baseModel和baseCollection,所有模型/集合都来自它


    你可以这样做:

    var _sync = Backbone.sync;
    Backbone.sync = function(method, model, options) {
    
        if( model && (method === 'create' || method === 'update' || method === 'patch') ) {
            options.contentType = 'application/json';
            options.data = JSON.stringify(options.attrs || model.toJSON());
        }
    
        _.extend( options.data, {
            "access_token": "some-token"
        });
    
        return _sync.call( this, method, model, options );
    }
    

    只要听取fetch / save方法的失败事件,就可以将用户重定向到/login

    model.fetch().fail( /* redirect */ )
    

    Backbone使用jQuery的$ .ajax,因此您可以使用$ .ajaxSetup“为将来的Ajax请求设置默认值”:

    $.ajaxSetup({
       headers: {
         "accept": "application/json",
         "token": YOUR_TOKEN
       }
    });
    

    更新:对此想法的改进(感谢@Glen)是使用$ .ajaxSend在每次将请求标头设置为标记之前检查是否存在标记:

    $(document).ajaxSend(function(event, request) {
       var token = App.getAuthToken();
       if (token) {
          request.setRequestHeader("token", token);
       }
    });
    

    App.getAuthToken()是您的Backbone应用程序中的一项功能。


    身份验证是应用程序的责任。

    对于Backbone应用程序,auth逻辑应该在Backbone代码中,并且应该不惜一切代价来避免更改全局jQuery的ajax行为。

    ajaxSetupajaxSend缺点

    ajaxSetup上的jQuery文档:

    注意:此处指定的设置将影响所有对$.ajax或基于Ajax衍生工具(如$.get()调用。 这可能会导致不良行为,因为其他呼叫者(例如插件)可能正在期待正常的默认设置。 出于这个原因,我们强烈建议不要使用这个API。 相反,请在调用中明确设置选项,或者定义一个简单的插件来执行此操作。

    ajaxSend具有与上述相同的问题。 它比ajaxSetup的唯一优点是每次都调用一个函数,给予您比传递给ajaxSetup基于对象的选项更大的灵活性。

    最安全的方式是AuthModelAuthCollection

    将认证逻辑放入基础模型和集合中。 这是最有范围的解决方案。

    在这里,您可以使用已经存在的BaseModel ,但我仍然倾向于将BaseModelAuthModel分离出来,因为您可能想要创建一个使用基本模型的自定义模型,但也使用不同的外部API。

    由于模型和集合的新sync函数是相似的,但都可能有不同的父实现,所以我做了一个简单的函数发生器。

    /**
     * Generates a new sync function which adds the token to the request header 
     * and handles a redirect on error.
     * @param  {Function} syncFn the parent `sync` function to call.
     * @return {Function}  a new version of sync which implements the auth logic.
     */
    var authSyncFunction = function(syncFn) {
        return function(method, model, options) {
            options = options || {};
    
            var beforeSend = options.beforeSend,
                error = options.error;
    
            _.extend(options, {
                // Add auth headers
                beforeSend: function(xhr) {
                    xhr.setRequestHeader('Authorization', "Bearer " + yourTokenHere);
                    if (beforeSend) return beforeSend.apply(this, arguments);
                },
    
                // handle unauthorized error (401)
                error: function(xhr, textStatus, errorThrown) {
                    if (error) error.call(options.context, xhr, textStatus, errorThrown);
                    if (xhr.status === 401) {
                        Backbone.history.navigate('login');
                    }
                }
            });
    
            return syncFn.call(this, method, model, options);
        };
    };
    

    在模型和集合上使用生成器。

    var AuthModel = BaseModel.extend({
        sync: authSyncFunction(BaseModel.prototype.sync)
    });
    
    var AuthCollection = BaseCollection.extend({
        sync: authSyncFunction(BaseCollection.prototype.sync)
    });
    

    然后,您就可以在模型和集合上使用这些,您确定需要验证。 由于您已经在使用基础模型和集合,因此只需将BaseModel.extend更改为AuthModel.extend

    虽然我知道你要求在403 Forbidden响应中重定向,但我认为它应该在401 Unauthorized 。 请参阅403禁止与401未经授权的HTTP响应

    覆盖主干的sync

    如果您现在不想改变所有模型和集合,但仍想遵循良好的实践并避免更改全局ajax设置,则重写Backbone.sync函数是一种简单的选择。

    使用我们以前定义的sync发生器

    Backbone.sync = authSyncFunction(Backbone.sync);
    

    管理本地存储和身份验证

    要管理本地存储中的数据,请检查Backbone-session。

    这是一个很好的Backbone模型实现,它与本地存储器同步,而不是REST API。 它还提供了一个很好的界面来管理认证。

    // Extend from Session to implement your API's behaviour
    var Account = Session.extend({
      signIn: function () {},
      signOut: function () {},
      getAuthStatus: function () {}
    });
    
    // Using the custom Account implementation
    var session = new Account();
    session.fetch()
      .then(session.getAuthStatus)
      .then(function () {
        console.log('Logged in as %s', session.get('name'));
      })
      .fail(function () {
        console.log('Not yet logged in!');
      });
    
    链接地址: http://www.djcxy.com/p/71815.html

    上一篇: Send token with every backbone sync request

    下一篇: java.io.IOException : No authentication challenges found