将身份验证凭据/ cookie注入预定义的ExtJS ajax代理

时间:2017-07-27 18:26:09

标签: ajax rest authentication cookies extjs

将ExtJS 6.20与一堆具有固定网址的模型一起使用到API,如下所示:

Ext.define('Admin.model.Patient', {
    extend: 'Ext.data.Model',

    requires: [
        'Ext.data.proxy.Rest',
        'Ext.data.schema.Association'
    ],

    fields: [
        { name: 'id', type: 'string' },
        { name: 'mrn', type: 'string' },
        { name: 'birth_date', type: 'date', format: 'Y-m-d' },
        { name: 'sex', type: 'string' },
        { name: 'first_name', type: 'string' },
        { name: 'last_name', type: 'string' }
    ],

    proxy: {
        type: 'ajax',
        url: 'http://localhost/patientview/api/read',
        reader: {
            type: 'json',
            rootProperty: ''
        }
    }

});

问题是,在成功登录之前,需要从API获取身份验证会话cookie,然后才能连接到API的受保护资源。我很容易从HTTP响应中获取会话cookie(并计划将其存储在会话存储中),但我不确定如何将其作为有效负载(如extraParams?)传递给代理,特别是因为它是已启动应用程序时已绑定到我的数据模型。

FWIW,为了使用经过身份验证的Cookie测试API,我使用curl中的cookie参数,如curl -v --cookie "session=XXX" http://0.0.0.0:5000/patientview/api/read中所示,其中XXX是会话Cookie的值。

由于Set-Cookie标题是“禁止”对象,因此withCredentials: true标题通常不可用(例如,参见how to get a cookie from an AJAX response)。

看起来有一种方法可以使用onLoginButton: function() { var formPanel = this.lookupReference('loginForm'), form = formPanel.getForm(), url = 'http://localhost/login_api/'; if (form.isValid()) { values = form.getValues(true); console.log(values); Ext.Ajax.request({ method: 'POST', cors: true, withCredentials: true, useDefaultXhrHeader: false, url: url, params: values, //username and password headers: { 'Accept': 'application/json' }, disableCaching: false, success: function (response) { json = Ext.decode(response.responseText); test = response.getAllResponseHeaders(); console.log('json'); console.log(json); console.log(test); console.log(response); if (response.status === 201) { console.log(json.items); } else { Ext.MessageBox.alert('Error', response.message); } } }); } }, 通过后续请求提供这些凭据 关键字(请参阅getting extjs to work with cors and cookies on chrome)。

我按照以下方式将我的登录修改为API:

responseHeaders

但是,即使这样,它也没有按预期工作。我假设,因为withCredentials中没有第三方Cookie,并且因为它们应该通过Patient关键字注入,所以还需要做其他事情。

FWIW,我的ExtJS应用程序的路径为http://localhost/test/,而Flask / API可在http://localhost/下访问...(为了消除任何跨域问题,我在本地运行这些一个nginx / uwsgi web / app服务器,通过端口80提供服务。我顺利登录,顺便说一句。我只是不确定如何将凭据传递给我的其他API调用(例如,上面的success: function (response) { if (response.status === 201) { console.log(json.items); Ext.Ajax.request({ url: 'http://localhost/patientview/api/read', method: 'GET', cors: true, useDefaultXhrHeader: false, withCredentials: true, success: function(response) { var result = Ext.decode(response.responseText); console.log(result); } }); } } 模型)。

注意:如果我在我的第一个Ext.request.Ajax调用成功回调中将另一个AJAX调用(根据上面的博客文章)嵌套到http://localhost/patientview/api/read,它可以工作,按照

cors

但是,虽然这是概念证明这是可行的,但它并没有解决如何将凭证注入我的预定义模型的问题。

修改

我删除了withCredentialsExt.request.Ajax选项,因为网络应用和api位于同一个域等。它确实可以正常工作。另外,我测试了另一个我调用Ext.define('Admin.view.main.MainModel', { extend: 'Ext.app.ViewModel', alias: 'viewmodel.main', stores: { patients: { model: 'Admin.model.Patient', autoLoad: true } } }); 的函数,并且通过从浏览器自动获取凭据来实现这一功能。

它仍然无法使用模型代理(它们都定义类似于上面的代码;相同的协议,相同的域,相同的端口等)

值得注意的是,如果我刷新浏览器,那么数据可供所有使用ajax代理绑定到模型的不同商店使用(这是有道理的)。我想知道在登陆成功后是否有办法重新加载绑定到模型的商店?

我的商店按照以下方式绑定到模型视图:

bind: {
    store: '{patients}'
},

然后,例如,通过数据绑定,它通过绑定命令被送到下拉组合框:

    <div ng-app="productController" ng-controller="productCtrl" class="row-fluid">
        <div class="col-md-12">
            <div class="form-group">
                <div class="input-group mb-2 mr-sm-2 mb-sm-0">
                    <div class="input-group-addon">
                        <i class="fa fa-pencil"></i>
                    </div>
                    <input ng-disabled="product.disabled" type="text" ng-model="description[0]" name="description" class="form-control" placeholder="Description..." required>
                    <div class="input-group-addon">
                        <a ng-click="addfield()" class="add-field">
                            <i class="fa fa-plus"></i>
                        </a>                           
                    </div>
                </div>
                <div ng-repeat="item in inputs track by $index">
                    <div class="input-group mb-2 mr-sm-2 mb-sm-0 repeat-input">
                        <div class="input-group-addon">
                            <i class="fa fa-pencil"></i>
                        </div>
                        <input ng-disabled="product.disabled" type="text" name="description" ng-model="description[$index+1]" class="form-control" placeholder="Description..." required>
                    </div>
                </div>
            </div>
        </div>
        {{description}}
    </div>

如果我要重新加载商店,这究竟会在哪里?我对ExtJS中的数据绑定有点新意。

2 个答案:

答案 0 :(得分:0)

要全局设置授权Cookie,您可以尝试使用

Ext.util.Cookies.set('session', token);

但是,如果资源位于不同的端点上,则会失败,因为cookie是为index.html所在的端点保存的,并且不会提交给其他端点。在这种情况下,您必须检查远程API如何获取令牌。

由于存在这些跨域问题,如果您使用的是OAuth等标准化身份验证方法,则该令牌通常会被视为承载令牌,这意味着您可以在全局范围内为所有Ajax调用设置一次,像这样:

Ext.Ajax.setDefaultHeaders({
    'Authorization': 'Bearer ' + token,
    'Accept': 'application/json'
});

答案 1 :(得分:0)

我最终终于使用了这个的修改版本:ExtJS login app ...它比基于用户会话管理路由行为更容易实现。现在,所有带有ajax代理的模型都不会加载,直到创建主视图,这只发生在我的AJAX身份验证请求中成功回调之后。