【问题标题】:How to debug "No 'Access-Control-Allow-Origin' header is present on the requested resource"如何调试“请求的资源上不存在‘Access-Control-Allow-Origin’标头”
【发布时间】:2016-01-11 03:49:50
【问题描述】:

我在浏览器控制台上显示此错误:

XMLHttpRequest 无法加载 http://localhost:8080/api/login。请求的资源上不存在“Access-Control-Allow-Origin”标头。 Origin 'http://localhost:9009' 因此不允许访问。

我使用的环境是:

  • 后端- Spring Boot
  • 前端- Angularjs
  • Web 服务器- 咕哝

在服务器上,我已经将请求和响应中的标头定义为:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        httpResponse.setHeader("Access-Control-Allow-Origin", "*");
        httpResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE,PUT");
        httpResponse.setHeader("Access-Control-Max-Age", "3600");
        httpResponse.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization, Content-Type");

        if (httpRequest.getMethod().equals("OPTIONS")) {
            httpResponse.setStatus(HttpServletResponse.SC_ACCEPTED);
            return;
        }
}

我已经在此链接No 'Access-Control-Allow-Origin' header is present on the requested resource 上找到了这个问题,但找不到合适的解决方案。

这是浏览器网络图片:

【问题讨论】:

  • 不是您问题的直接答案,但是:1)当您将其移至生产环境时,请注意“*”,2)请向我们展示您拨打此电话时通过线路的标头(在浏览器中按 F12,然后网络将显示它们)
  • 我已经上传了图片
  • 这令人困惑。你不是在响应中设置标题吗?您的跟踪在请求中显示它们

标签: angularjs spring-security spring-boot angular-ui-router cors


【解决方案1】:

您需要在您的网络服务器上启用 CORS(跨源资源共享)。请参考this resource

您需要将响应标头设置为:

Access-Control-Allow-Origin: *

This link 拥有设置 CORS 所需的所有信息

为所有域启用 CORS 不是一个好习惯,因此您应该在一切正常运行时限制它。

另一种解决方法是为 curl 请求提供单独的 API

在您自己的 API 中调用 URL 并使用您的服务器端通过 cURL 或其他方式访问数据。我目前有一个情况相同的工作项目(Laravel + AngularJs)。

我使用 cURL 请求进行远程身份验证检查的示例代码。

代码为 Laravel-PHP 格式,希望你能转换成你正在研究的语言。

请求者函数:

public function curlRequester($url,$fields)
    {
        // Open connection
        $ch = curl_init();

        // Set the url, number of POST vars, POST data
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true );

        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);

        // Execute post
        $result = curl_exec($ch);

        // Close connection
        curl_close($ch);

        $result_json_decoded = json_decode($result, true);


        return $result_json_decoded;
    }

控制器功能

public function login()
{

    // set POST params
    $fields = array(
        'username' => Input::get('username'),
        'password' => Input::get('password')
    );
    $url = 'http://www.this-is-api-url.com/login';

    $result = $this->curl->curlRequester($url,$fields);

    return response()->json($result);

}

角度请求函数

$scope.authCheck = function(){

        $http({
            url:'http://www.our-project-url/login',
            method:"post",
            data:{"username": "rameez", "password":"rameezrami"}
        })
        .success(function(response) {
            if(response.status==1){
                $location.path("/homepage");
            }else if(response.status==0){
                $scope.login_error_message_box = true;
                $scope.login_error_message_text =response.message;
            }

        });

    }

【讨论】:

  • 是的,我遵循了这一点,但找不到滞后的错误。
  • 嗨..从你发布的网络图片看来你没有在服务器端设置CORS ACCESS HEADER。
【解决方案2】:

您的服务器应为预检/实际 CORS 请求添加正确的 CORS 标头。我不建议您实现自己的过滤器,因为这是一个相当复杂的规范。

从 4.2 开始,Spring Framework 支持使用全局配置或过滤器 - see this blog post for more information 的 CORS。

如果您使用的是 Spring Boot,版本 1.3.0(即将发布)will integrate this support

【讨论】:

    【解决方案3】:

    您还需要更新 Angular 代码以允许通过 AJAX 进行 CORS。

    myApp.config(['$httpProvider', function($httpProvider) {
            $httpProvider.defaults.useXDomain = true;
            delete $httpProvider.defaults.headers.common['X-Requested-With'];
        }
    ]);
    

    如果上述方法不起作用,您可能还需要添加以下内容:

    myApp.all('/*', function (request, response, next) {
        response.header("Access-Control-Allow-Origin", "*");
        response.header("Access-Control-Allow-Headers", "X-Requested-With");
        response.header("Access-Control-Allow-Methods", "GET, POST", "PUT", "DELETE");
        next();    
    });
    

    正如@Marged 所说,您希望对“*”保持谨慎,我强烈建议您将其替换为您的域。

    【讨论】:

      【解决方案4】:

      你的过滤器是对的,你应该把你的过滤器作为一个组件包含在它可以被spring扫描的地方

      @Component
      public class CORSFilter implements Filter{
      
          @Override
          public void init(FilterConfig filterConfig) throws ServletException {
      
          }
      
          @Override
          public void doFilter(ServletRequest req, ServletResponse res,
                  FilterChain chain) throws IOException, ServletException {
      
              HttpServletResponse response = (HttpServletResponse) res;
              response.setHeader("Access-Control-Allow-Origin", "*");
              response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
              response.setHeader("Access-Control-Max-Age", "3600");
              response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
              chain.doFilter(req, res);
      
          }
      
          @Override
          public void destroy() {
      
          }
      
      }
      

      【讨论】:

        猜你喜欢
        • 2021-09-18
        • 2013-11-29
        • 2014-07-28
        • 2014-01-19
        • 2013-12-07
        相关资源
        最近更新 更多