问题
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