拒绝从 '*' 执行脚本,因为它的 MIME 类型 ('application/json') 不可执行,并且启用了严格的 MIME 类型检查

Posted

技术标签:

【中文标题】拒绝从 \'*\' 执行脚本,因为它的 MIME 类型 (\'application/json\') 不可执行,并且启用了严格的 MIME 类型检查【英文标题】:Refused to execute script from '*' because its MIME type ('application/json') is not executable, and strict MIME type checking is enabled拒绝从 '*' 执行脚本,因为它的 MIME 类型 ('application/json') 不可执行,并且启用了严格的 MIME 类型检查 【发布时间】:2014-09-28 04:31:03 【问题描述】:

我是 AngularJS 的新手。我正在使用 rails 应用程序以 json 格式公开数据。数据将由 Angular 应用程序使用。 angular repo 和 rails repo 是完全不同的。不同存储库的原因是因为我希望我的 Rails 存储库只是使用我可以在 Angular 应用程序中使用的 API 公开数据。

我的rails控制器如下

class Api::V1::PhonesController < ApplicationController
  def index
    render json: Phone.all
  end

  def show
    render json: Phone.find(params[:id])
  end
  ...
end

现在,当我访问“localhost:3000/api/v1/phones”时,它会返回所有手机的 json 数据。当我访问 'localhost:3000/api/v1/phones/1' 时,它返回 id 为 1 的手机的 json 数据。我使用http://jsonlint.com/ 验证了 json 数据格式。到这里为止一切正常。

我的 angularjs 路由文件如下:

$routeProvider.
   when('/phones', 
     templateUrl: 'list.html',
     controller: 'PhoneListController' 
   ).
   when('/phones/:id', 
     templateUrl: 'show.html',
     controller: 'PhoneShowController'
   ).
   otherwise(
     redirectTo: '/phones'
   );
]);

我在 Angular 存储库中的 index.html 中嵌入了 list.html 模板。

<html ng-app='phoneCatApp'>
  ...
</html>
<script type="text/ng-template" id="list.html">
  This is the list template.
</script>

services.js 的代码如下:

var appServices = angular.module('appServices', []);

phoneCatApp.factory('appServices', ['$http', '$q', function($http, $q)
  var url = "http://localhost:3000/api/v1/";

  //get all phones
  this.getPhones = function()
    var defered = $q.defer();
    var listApi = url + "phones";

    $http.jsonp(listApi).then(function(results)
      defered.resolve(results);
    , function(error)
      defered.reject(error);
    );
    return defered.promise;
    
  return this;
]);

当我访问“#/phones”时,脚本模板中的文本也会显示出来。问题是 1)在chrome中,当我检查页面时显示以下错误。

Refused to execute script from 'http://localhost:3000/api/v1/phones' because its MIME type ('application/json') is not executable, and strict MIME type checking is enabled.

2) 在 Firefox 中,显示以下错误。

SyntaxError: missing ; before statement

感谢您的帮助。

【问题讨论】:

【参考方案1】:

嘿,所以我相信您的问题是您的 Rails 控制器返回的是 JSON 而不是 JSONP。您的控制器必须明确指定一个回调函数,该函数可以由请求参数指定。

有关从 rails 控制器返回 JSONP 的示例,请参阅 Handling jsonp in rails 3 controller

所以你的rails代码看起来像(啊,我的rails非常生锈......):

class Api::V1::PhonesController < ApplicationController
  def index
    if params[:callback]
      format.js  render :json => :phones => Phone.all.to_json, :callback => params[:callback] 
    else
      format.json  render json: :phones => Phone.all.to_json
    end
end

那么对于角度方面,这个答案应该可以帮助你: parsing JSONP $http.jsonp() response in angular.js

我认为你的角度看起来像:

var appServices = angular.module('appServices', []);

phoneCatApp.factory('appServices', ['$http', '$q', function($http, $q)
  var url = "http://localhost:3000/api/v1/";

  //get all phones
  this.getPhones = function()
    var defered = $q.defer();
    var listApi = url + "phones?callback=JSON_CALLBACK";

    $http.jsonp(listApi).then(function(results)
      defered.resolve(results);
    , function(error)
      defered.reject(error);
    );
    return defered.promise;
    
  return this;
]);

【讨论】:

出现错误:“ActionController::InvalidCrossOriginRequest(安全警告:另一个站点上的嵌入式 假设有一个服务将 json 数据导出到很多应用程序。在这里,我无法修改服务器代码以考虑回调。将要使用 json 数据的应用程序需要处理它。那怎么办? 所以这可能作为一个单独的问题更好,甚至可能在 securityexchange 上,但文档在这里:edgeapi.rubyonrails.org/classes/ActionController/…guides.rubyonrails.org/…(一个好的 Rails 安全指南)......基本上,实现好的 csrf想要提供 JSONP 端点时的保护有点棘手,需要仔细考虑。应用程序/消费者是否将位于与 REST 服务器不同的域中?一个好的开始:***.com/questions/613962/is-jsonp-safe-to-use 应用程序/消费者将是不同的应用程序。我的 Angular 应用程序主题基于官方 angularjs 教程(手机目录)应用程序。唯一的区别是教程使用存储在应用程序中的 json 文件来检索数据,而我使用的是 rails 应用程序来使用 API 公开数据。 老实说,如果您有兴趣拥有一个安全的应用程序,我会使用 CORS(跨域请求共享)而不是 JSONP。这样,您的 REST 服务器实际上可以选择特定域来允许跨域请求。另外 - 您可以使用 Angular 的 CSRF 保护和标头中的令牌,您可以在 Rails 端检查这些令牌。

以上是关于拒绝从 '*' 执行脚本,因为它的 MIME 类型 ('application/json') 不可执行,并且启用了严格的 MIME 类型检查的主要内容,如果未能解决你的问题,请参考以下文章

拒绝从 URL 执行脚本,因为它的 MIME 类型 ('application/json') 不可执行,并且启用了严格的 MIME 类型检查

拒绝从 'url' 执行脚本,因为它的 MIME 类型('application/json')不可执行

拒绝从 'URL' 执行脚本,因为它的 MIME 类型 ('text/html') 不可执行,并且启用了严格的 MIME 类型检查

拒绝从 'file_name.php' 执行脚本,因为它的 MIME 类型 ('text/html') 不可执行,并且启用了严格的 MIME 类型检查

拒绝执行脚本,因为它的 MIME 类型 ('text/html') 不可执行,并且启用了严格的 MIME 类型检查

拒绝执行脚本,因为它的 MIME 类型 ('text/html') 不可执行并且启用了严格的 MIME 类型检查