【问题标题】:CORS policy blocks localhostCORS 策略阻止本地主机
【发布时间】:2019-11-17 18:50:39
【问题描述】:

我使用带有 rest API 的 Spring Boot 2 制作了一些 Web 项目。我有两个项目,一个是rest API,另一个是web项目调用rest API。我已经在使用@CrossOrigin(origins = "*")。所以,它在控制器类中运行良好。

但是,当我向其他控制器类调用请求时,chrome 将其打印给我,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.。我该如何解决这个问题?

这是我的工作控制器类。盲区没有其他特别之处:

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

这是工作 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);

这不是工作控制器。一开始我只是用了`@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 {
...
}

这不适用于 JWT 的 ajax。

$.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();

我该如何解决这个问题?

【问题讨论】:

  • 预检请求是 OPTIONS 请求,您没有在允许的方法中列出该请求。

标签: javascript spring spring-boot cors


【解决方案1】:

选项 1添加 RequestMethod.OPTIONS

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

为什么选择选项?

此飞行前请求 (RequestMethod.OPTIONS) 由某些浏览器发出,作为一种安全措施,以确保正在完成的请求受到服务器的信任。这意味着服务器知道在请求上发送的方法、来源和标头是安全的。


选项 2CORS 的 WebConfig

您可以为 CORS 源配置创建一个 WebConfig 类,这样我们不需要在每个控制器上都写@CrossOrigin

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

    }

}

【讨论】:

  • 它没有解决我的问题T^T。我尝试应用两个选项。选项 1 没有解决我的问题。所以,我尝试了选项 2。但是,它也没有解决我的问题并出现了一个新问题(关于 @PathVariable 参数)。我该怎么办...?
  • 您好@Rect您是否仍然面临CORS问题或其他问题。您可以与错误分享更多详细信息,以便我获得更多想法
  • 你好@Patel Romil,我仍然面临同样的问题。我认为没有更多细节。如果您需要其他信息,请告诉我。我会满足你的要求。
  • 你好@Rect你在谈论@PathVariable的一个新问题所以我通过一些新问题instaed of 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
  • @Rect 那么@PathVariable 或相同的has been blocked by CORS policy: 是否有任何问题或错误
【解决方案2】:

尝试将OPTIONS 方法添加到允许方法列表中:

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

OPTIONS 方法在 preflight requests 中用于识别可接受的 HTTP 方法列表。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-03
    • 1970-01-01
    • 2020-09-11
    • 2021-04-16
    • 2018-02-26
    • 2019-11-19
    • 2020-09-12
    • 1970-01-01
    相关资源
    最近更新 更多