【问题标题】:CORS, prevent preflight of request with Authorization headerCORS,防止带有授权标头的请求预检
【发布时间】:2016-12-28 06:03:36
【问题描述】:

当我添加 Authorization 标头时,AngularJS 将我的 POST 请求转换为 OPTIONS

  $http({
    url: ApiEndpoint + 'logout',
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      'Authorization': UserService.getApiKey()
    }
  })

我正在使用我在浏览器中测试的 Ionic 开发一个混合移动应用程序,因为它是一个 CORS 请求。

我已经看到this 的问题了。建议的解决方法是更改​​我所做的Content-Type,并且它在没有Authorization 的情况下工作。使用Authorization 标头,请求再次更改为 OPTIONS 方法。

您能否提出客户端解决方案,因为您无法控制服务器 API。

谢谢。

【问题讨论】:

  • 预检将在您的情况下触发,因为设置“授权”标头会使您的请求在 MDN 术语中不简单。唯一允许手动设置以分类为 simple 的标题是 Accept、Accept-Language、Content-Language 和 Content-Type。参考:developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS。不确定您是否可以避免飞行前,但您可以在给定的时间范围内缓存请求。

标签: javascript angularjs ionic-framework


【解决方案1】:

正如Developer 所说,CORS 请求将被预检,除非它是simple request

【讨论】:

    【解决方案2】:

    正如其他人所指出的,您看到的是 CORS 预检请求。

    如果您想设置Authorization 标头,则无法避免它们,但如果您控制后端(或愿意使用代理),则有一些解决方法。更多信息:https://damon.ghost.io/killing-cors-preflight-requests-on-a-react-spa/

    简而言之:

    • CORS 预检标头可以被浏览器缓存(将 Access-Control-Max-Age header 设置为应缓存响应的秒数)
    • 可以将授权标头移至 URL 参数(如果这是个好主意,则另当别论)
    • 您可以在没有正确标头的情况下发送 JSON(同样,这不是最好的想法,但是...)
    • 如果它适合您的用例,最简单的解决方案是使用代理,从而完全避免跨域请求

    【讨论】:

    • “CORS preflight headers can be cached”——如果你能添加一些关于如何完成的解释会很好。
    • 当然,完成。 (并且我需要在此处添加一些虚假文本,以便此评论至少有 15 个字符长)
    【解决方案3】:

    以下答案可能也适用于您正在做的事情 - 尽管如果数据格式正确,您的“Content-Type”标头应该没问题:

    How to skip the OPTIONS preflight request in AngularJS

    【讨论】:

    • 谢谢,我看到了这个问题,建议的解决方法是更改​​我所做的Content-Type,并且它在没有Authorization 的情况下工作。当我添加 Authorization 时,请求更改为 OPTIONS 方法
    • @Developer 是对的。 Authorization 标头会导致您的请求不是“简单”请求(它不是“安全列表”标头 - 请参阅此处:fetch.spec.whatwg.org/#cors-safelisted-request-header),因此浏览器将执行预检请求。
    【解决方案4】:

    为避免预检请求,只需创建自己的控制器,然后从服务器代码调用其他源 REST 服务。

    <pre>
    
    public void doPost(HttpServletRequest request, HttpServletResponse response)
    			throws IOException {
    		String outputString = request.getParameter("data");  /*Refer the ajax data $.ajax({
    	        url:"callRestApi",
    	        type:'POST',
    	        data: { 
    				"data":"data Value"
    			},
    	        beforeSend: function (xhr) {
    	            xhr.setRequestHeader ("Authorization", "Basic " + btoa(uname + ":" + passwd));
    	        },
    	        success:function(){
    	        	alert("Successfully created JSON data from DB");
    	        },
    	        error:function(textStatus, jqXHR){
    	        	alert("Unable to process some of the types, Please check logs for details.");
    	        }
    	    });*/
    		HttpURLConnection conn = null;
    		URL url = new URL("");// just example, in your case pass the URL here
    		conn = (HttpURLConnection) url.openConnection();
    		conn.setRequestMethod("POST");
    		conn.setDoInput(true);
    		conn.setDoOutput(true);
    		conn.setRequestProperty("Content-Type", "");// just example, in your
    													// case pass the content
    													// type here
    		conn.setRequestProperty("Authorization", "");// just example, in your
    														// case pass the
    														// authorization key
    														// here
    		DataOutputStream outputStream = new DataOutputStream(
    				conn.getOutputStream());
    		outputStream.write(outputString.getBytes());
    		outputStream.flush();
    		outputStream.close();
    		StringBuffer sb = new StringBuffer();
    		if (conn != null && conn.getResponseCode() == 200) {
    			byte[] buffer = new byte[8192];
    			int bytesRead;
    			InputStream in = conn.getInputStream();
    			while ((bytesRead = in.read(buffer)) != -1) {
    				sb.append(new String(buffer, 0, bytesRead, "UTF-8"));
    				buffer = new byte[8192];
    				bytesRead = 0;
    			}
    		}
    		System.out.println("Output ===>" + sb.toString());
    	}
    </pre>

    在上面的例子中不会有任何预检请求。因为 Rest API 调用将在服务器端完成。

    【讨论】:

    • 如果服务器无法访问其他服务器,这将不起作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-25
    • 2021-06-12
    • 2017-08-07
    • 1970-01-01
    • 2021-08-24
    • 1970-01-01
    • 2019-11-03
    相关资源
    最近更新 更多