基本 HTTP 身份验证在标头中不包含 JSON? (Backbone.js 到 Rails 服务器)

发布于 2024-10-08 03:31:33 字数 1931 浏览 3 评论 0原文

我正在使用 Backbone.js 使用 JSON api 为我的 Rails 应用程序创建纯 JS 前端。

backbone.js 模型 URL 如下所示:

window.MedicationCollection = Backbone.Collection.extend({
  model: Medication,
    url: 'http://localhost:3000/medication_options'
});

CRUD 可以很好地使用它。它使用“application/JSON”内容类型向我的服务器发送请求。

但我需要为 API 添加身份验证,并且我的 Rails 应用程序正在使用 Authlogic,因此我添加了以下内容:

  before_filter :require_user

     def require_http_auth_user
        return true if current_user
        authenticate_or_request_with_http_basic do |email, password|
          email = email.gsub("_at_", "@") if email.include?("_at_")
          if @current_user = User.find_by_email(email)
            @current_user.valid_password?(password)
          else
            false
          end
        end
      end

Rails 中典型的 CRUD 方法如下所示:

  def update
    @medication_option = MedicationOption.find(params[:id])
    if @medication_option.update_attributes(params[:medication_option])
      flash[:notice] = "Successfully updated medication."
    end
    respond_with @medication_option
  end

因此,在我的 Backbone.js 模型中,我向 url 添加了“用户名:密码”:

window.MedicationCollection = Backbone.Collection.extend({
  model: Medication,
    url: 'http://username:password@localhost:3000/medication_options'
});

使用适当的凭据,身份验证可以正常工作,但由于某种原因,Rails 服务器将所有 Backbone.js 请求解释为 HTML 而不是 JSON。

由于某种原因,在基本 HTTP 身份验证过程中,JSON 标头会在混合中丢失。

因此,如果我像这样显式地将“.json”添加到 URL 末尾:

window.MedicationCollection = Backbone.Collection.extend({
  model: Medication,
    url: 'http://username:password@localhost:3000/medication_options.json'
});

我可以获得基本的 GET 请求。

但是当我执行 CRUD 时,它不起作用,因为它将 ID 附加到 URL 的末尾,所以它会出错:

ActionController::RoutingError (No route matches "/medication_options.json/41516")

所以我不确定从这里去哪里。

I'm using Backbone.js to create a pure JS front-end for my rails app using a JSON api.

The backbone.js model URL looks like this:

window.MedicationCollection = Backbone.Collection.extend({
  model: Medication,
    url: 'http://localhost:3000/medication_options'
});

CRUD works fine with this. It's sending requests to my server with an "application/JSON" content type.

But I needed to add authentication for the API and my rails app is using Authlogic so I added this:

  before_filter :require_user

     def require_http_auth_user
        return true if current_user
        authenticate_or_request_with_http_basic do |email, password|
          email = email.gsub("_at_", "@") if email.include?("_at_")
          if @current_user = User.find_by_email(email)
            @current_user.valid_password?(password)
          else
            false
          end
        end
      end

And a typical CRUD method in rails looks like this:

  def update
    @medication_option = MedicationOption.find(params[:id])
    if @medication_option.update_attributes(params[:medication_option])
      flash[:notice] = "Successfully updated medication."
    end
    respond_with @medication_option
  end

So in my Backbone.js model I added "username:password" to the url:

window.MedicationCollection = Backbone.Collection.extend({
  model: Medication,
    url: 'http://username:password@localhost:3000/medication_options'
});

The authentication works fine with the appropriate credentials, but for some reason all of the Backbone.js requests are interpreted by the Rails server as HTML instead of JSON.

For some reason during an Basic HTTP authentication, the JSON header gets lost in the mix.

So if I explicitly add ".json" to the end of the URL like this:

window.MedicationCollection = Backbone.Collection.extend({
  model: Medication,
    url: 'http://username:password@localhost:3000/medication_options.json'
});

I can get basic GET requests to work.

But when I do CRUD it doesn't work because it appends the ID to the end of the URL, so it errors:

ActionController::RoutingError (No route matches "/medication_options.json/41516")

So I'm not sure where to go from here.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

懵少女 2024-10-15 03:31:33

您的 .json 应始终位于 url 的末尾以被解释为 json:

/medication_options/41516.json

如果需要将 json 放在正确的位置,您可以编辑模型 url 以及集合 URL。

根本问题是为什么它首先没有被处理为 json。如果您使用的是rails 3,您是否有:

respond_to :js 

respond_to :json

匹配您的respond_with并确保您的控制器接受这种格式(否则rails默认会返回406错误)?

Your .json should always be at the end of the url to be interpreted as json:

/medication_options/41516.json

You can edit the Model url as well as the collection URL if needed to put the json at the right place.

The root problem is why it doesn't get processed as json in the first place. If you are using rails 3 do you have:

respond_to :js 

or

respond_to :json

to match your respond_with and make sure your controller accepts this kind of format (otherwise rails would return 406 error by default)?

墨落成白 2024-10-15 03:31:33

我从未使用过 Document.js,但在查看文档时,您似乎可以覆盖 url 并返回函数的结果,而不是为其提供文字字符串值。您可以通过这种方式将 .json 添加到 url 字符串的末尾吗?

I've never used Document.js, but in looking through the docs it seems you can override url and return the result of a function instead of giving it a literal string value. Could you add the .json to the end of the url string that way?

ˇ宁静的妩媚 2024-10-15 03:31:33

尝试这样的事情:

 _.extend(Medication, 
    {extension:'.json',
     url:function() {
          var base = getUrl(this.collection);
          if (this.isNew()) return base + this.extension;
          return (base + (base.charAt(base.length - 1) == '/' ? '' : '/')
                  + this.id + this.extension);
        }
    });

Try something like this:

 _.extend(Medication, 
    {extension:'.json',
     url:function() {
          var base = getUrl(this.collection);
          if (this.isNew()) return base + this.extension;
          return (base + (base.charAt(base.length - 1) == '/' ? '' : '/')
                  + this.id + this.extension);
        }
    });
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文