CORS policy blocks localhost

六月ゝ 毕业季﹏ 提交于 2020-01-16 18:23:26

问题


I made some web project using Spring Boot 2 with rest API. I had two projects, the one is rest API, another is web project calling rest API. I already using @CrossOrigin(origins = "*"). So, It works well in the controller class.

However, when I call request to other controller class, chrome print it to me, Access to XMLHttpRequest at 'http://localhost:8080/signout/1234' from origin 'http://localhost:8081' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.. How can I solve this problem?

This is my working controller class. There is no other special in blind space:

@CrossOrigin(origins = "*")
@RestController
@RequestMapping("/admin")
public class AdminController {
...
@PutMapping("/users")
public User updateUser(@Valid @RequestBody User updatedUser) throws ResourceNotFoundException {
        User savedUser = userRepository.findByUsername(updatedUser.getUsername());
        savedUser.setPassword(updatedUser.getPassword());
        savedUser = userRepository.save(savedUser);
        return savedUser;
    }
...
}

This is working ajax:

var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
       if (this.readyState == 4 && this.status == 200){
            ...
        } else if (this.status == 500) {
            alert(this.responseText);
        }
    }

    var json = JSON.stringify(param);
    xmlHttp.open("POST", mainurl+"admin/role", false);
    xmlHttp.setRequestHeader("Content-type", "application/json; charset=utf-8");
    xmlHttp.send(json);

This is not working controller. At first I just used `@CrossOrigin(origins = "*").

//@CrossOrigin(origins = "http://localhost:8081", allowedHeaders = "*")
@CrossOrigin(origins = "*", allowCredentials = "true", methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE})
@RestController
@RequestMapping("/")
public class UserController {
...
}

This is not working ajax with JWT.

$.ajax({
        type: "DELETE", 
        url: "http://localhost:8080/signout/"+username,
        async: true,
//      crossDomain: true,
        beforeSend: function (xhr) {
            xhr.setRequestHeader("Authorization", 'Bearer '+ "${token}");
        },
        success: function(result, status, xhr){
            //service 표시
        },
        error: function(xhr, status, err) {
            alert(xhr.responseText);
        }
    });

//      var xmlHttp = new XMLHttpRequest();
//      xmlHttp.onreadystatechange = function() {
//          if (this.readyState == 4 && this.status == 200){
//              location.href=window.location.protocol + "//" + window.location.host + "/sso_ui/";
//          } else if (this.status == 500) {
//              alert(this.responseText);
//          }
//      }

//      xmlHttp.open("DELETE", "http://localhost:8080/signout/"+username, false);
//      xmlHttp.setRequestHeader("Content-type", "application/json; charset=utf-8");
//      xmlHttp.setRequestHeader('Authorization', 'Bearer ' + "${token}");
//      xmlHttp.send();

How can I solve this problem?


回答1:


Try to add OPTIONS method to the list of allows methods:

@CrossOrigin(origins = "*", allowCredentials = "true", methods = {RequestMethod.OPTIONS, RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE})

OPTIONS method is being used in preflight requests to identify the list of acceptable HTTP methods.




回答2:


Option 1: Add RequestMethod.OPTIONS

 @CrossOrigin(origins = "*", allowCredentials = "true", methods = {RequestMethod.OPTIONS, RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE})

Why OPTIONS?

This pre-flight request (RequestMethod.OPTIONS) is made by some browsers as a safety measure to ensure that the request being done is trusted by the server. Meaning the server understands that the method, origin and headers being sent on the request are safe to act upon.


Option 2: WebConfig for CORS

You can create one WebConfig Class for CORS Origin Configuration so that we don't need to write @CrossOrigin at each and every controller.

WebConfig.java

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@EnableWebMvc
public class WebConfig implements Filter,WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
      HttpServletResponse response = (HttpServletResponse) res;
      HttpServletRequest request = (HttpServletRequest) req;
      System.out.println("WebConfig; "+request.getRequestURI());
      response.setHeader("Access-Control-Allow-Origin", "*");
      response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
      response.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With,observe");
      response.setHeader("Access-Control-Max-Age", "3600");
      response.setHeader("Access-Control-Allow-Credentials", "true");
      response.setHeader("Access-Control-Expose-Headers", "Authorization");
      response.addHeader("Access-Control-Expose-Headers", "USERID");
      response.addHeader("Access-Control-Expose-Headers", "ROLE");
      response.addHeader("Access-Control-Expose-Headers", "responseType");
      response.addHeader("Access-Control-Expose-Headers", "observe");
      System.out.println("Request Method: "+request.getMethod());
      if (!(request.getMethod().equalsIgnoreCase("OPTIONS"))) {
          try {
              chain.doFilter(req, res);
          } catch(Exception e) {
              e.printStackTrace();
          }
      } else {
          System.out.println("Pre-flight");
          response.setHeader("Access-Control-Allow-Origin", "*");
          response.setHeader("Access-Control-Allow-Methods", "POST,GET,DELETE,PUT");
          response.setHeader("Access-Control-Max-Age", "3600");
          response.setHeader("Access-Control-Allow-Headers", "Access-Control-Expose-Headers"+"Authorization, content-type," +
          "USERID"+"ROLE"+
                  "access-control-request-headers,access-control-request-method,accept,origin,authorization,x-requested-with,responseType,observe");
          response.setStatus(HttpServletResponse.SC_OK);
      }

    }

}


来源:https://stackoverflow.com/questions/56931810/cors-policy-blocks-localhost

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