How to debug “No 'Access-Control-Allow-Origin' header is present on the requested resource”

匿名 (未验证) 提交于 2019-12-03 07:36:14

问题:

I am getting this error shown on browser console:

XMLHttpRequest cannot load http://localhost:8080/api/login. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9009' is therefore not allowed access.

The environment I am using are:

  • Backend- Spring Boot
  • Front End- Angularjs
  • Web Server- Grunt

On server, I am already defining headers in request and response as:

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;         } } 

I already found this question on this link No 'Access-Control-Allow-Origin' header is present on the requested resource but couldn't find the appropriate solution.

Here is the browser network image:

回答1:

Your server should add the proper CORS headers for preflight/actual CORS requests. I wouldn't recommend implementing your own Filter, since this is a rather complex specification.

As of 4.2, Spring Framework supports CORS with a global configuration or with a Filter - see this blog post for more information.

If you're using Spring Boot, version 1.3.0 (to be released soon) will integrate this support.



回答2:

You need to enable CORS(Cross Origin Resource Sharing) on your web server. Please refer to this resource.

You need to set your response header to:

Access-Control-Allow-Origin: * 

This link has all the info needed to set CORS

Enabling CORS for all domain is not a good practice, so you should restrict it when everything is up and running.

Another workaround is to have a separate API for curl request

Call a URL in your own API and access the data using your server side with cURL or something. I have a current working project with same situation (Laravel + AngularJs).

My sample code for the remote auth check with cURL request.

Code is in Laravel-PHP format, I hope you can convert to the language you are working on.

Requester function:

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;     } 

Controller function

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);  } 

Angular request function

$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;             }          });      } 


回答3:

Your Filter is right, You should include your filter as a component and put it where it can be scanned by 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() {      }  } 


回答4:

You need to also make an update in your angular code to allow CORS via AJAX.

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

If the above doesn't work, you may need to also add the following:

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();     }); 

As noted by @Marged you want to be cautious about the "*" and I would highly recommend replacing that with your domain(s).



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!