CORS,使用Authorization标头防止请求预检

时间:2016-08-21 17:12:09

标签: javascript angularjs ionic-framework

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

  $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。

谢谢。

4 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:0)

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

How to skip the OPTIONS preflight request in AngularJS

答案 2 :(得分:0)

为避免预检请求,只需创建自己的控制器,然后从服务器代码调用另一个源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调用将在服务器端完成。

答案 3 :(得分:0)

正如其他人所指出的,您看到的是CORS飞行前请求。

如果要设置<div id="app"> <div id="result">0</div> <div id="keypad"> <div id="nums"> <div class="key">7</div> <div class="key">8</div> <div class="key">9</div> <div class="key">4</div> <div class="key">5</div> <div class="key">6</div> <div class="key">1</div> <div class="key">2</div> <div class="key">3</div> <div class="key">0</div> <div class="key">.</div> <div class="key">=</div> </div> <div id="ops"> <div class="key">×</div> <div class="key">-</div> <div class="keyy">+</div> <div class="key">÷</div> <div class="key">CM</div> <div class="key">M-</div> <div class="key">M+</div> </div> </div> </div>标头,则无法避免,但是如果您控制后端(或愿意使用代理),则有一些解决方法。更多信息:https://damon.ghost.io/killing-cors-preflight-requests-on-a-react-spa/

简而言之:

  • 可以缓存CORS飞行前标头
  • 可以将授权标头移到URL参数(如果这是一个好主意,则是一个完整的其他讨论)
  • 您可以发送不带适当标题的JSON(同样,不是最好的主意,但是...)
  • 如果适合您的用例,最简单的解决方案是使用代理,从而完全避免跨域请求