可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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).