我正在研究React中的前端应用程序,该应用程序连接到用Spring引导编写的中间件服务。 我试图从前端调用端点,如下所示:
return axios.post('http://localhost:8085/workshop/client/createClient', {username})
.then((response) => {
console.log('Success')
})
.catch((error) => console.log(error));
每当我在浏览器中发出请求时,我都会收到以下错误:
OPTIONS http://localhost:8085/workshop/client/createClient 401 ()
Failed to load http://localhost:8085/workshop/client/createClient: Response for preflight has invalid HTTP status code 401.
据我了解,这是因为我的中间件应用程序阻止了预检请求。 在线阅读了有关启用此功能的信息,我在我的春季启动应用程序中添加了一个CorsFilter:
@Slf4j
public class CORSFilter implements Filter {
private static final String ONE_HOUR = "3600";
@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, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", ONE_HOUR);
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With,Origin,Content-Type, Accept, x-device-user-agent, Content-Type");
if (req instanceof HttpServletRequest) {
HttpServletRequest httpServletRequest = (HttpServletRequest) req;
if (httpServletRequest.getHeader(HttpHeaders.ORIGIN) != null
&& httpServletRequest.getMethod().equals(HttpMethod.OPTIONS.name())
&& httpServletRequest.getHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD) != null) {
log.debug("Received an OPTIONS pre-flight request.");
return;
}
}
chain.doFilter(req, res);
}
@Override
public void destroy() {
}
}
和
@Configuration
public class MvcConfiguration {
@Bean
public FilterRegistrationBean corsFilter() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new CORSFilter());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.setOrder(0);
return filterRegistrationBean;
}
}
以下是端点示例:
@PostMapping("/createClient")
public ResponseEntity<?> createClient(@RequestBody CreateClientDto clientDto) {
try {
...
return new ResponseEntity<>(responseBody, OK);
} catch (Exception e ...) {}
}
非常感谢任何帮助:)
更新:我的网址略有错误(因此404)。我已更新错误消息。我似乎仍然遇到了CORS问题。
这些是我在开发工具中可以看到的响应头:
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:access-control-allow-credentials, access-control-allow-methods, access-control-allow-origin, allow, content-type
Access-Control-Allow-Methods:POST
Access-Control-Allow-Origin:http://localhost:3000
Allow:GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
Cache-Control:no-cache, no-store, max-age=0, must-revalidate
Content-Length:0
Date:Thu, 01 Mar 2018 14:06:38 GMT
Expires:0
Pragma:no-cache
Strict-Transport-Security:max-age=31536000 ; includeSubDomains
Vary:Origin
WWW-Authenticate:Basic realm="Spring"
X-Content-Type-Options:nosniff
X-Frame-Options:DENY
X-XSS-Protection:1; mode=block
请求标题:
OPTIONS /workshop/client/createClient HTTP/1.1
Host: localhost:8085
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://localhost:3000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36
Access-Control-Request-Headers: access-control-allow-credentials,access-control-allow-methods,access-control-allow-origin,allow,content-type
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en;q=0.9,en-US;q=0.8,da;q=0.7
答案 0 :(得分:2)
问题似乎已得到解决。我错过了Accept请求标题(感谢@Anadi Sharma),我还将spring-boot-starter-security作为依赖项,似乎未经授权返回。我也不需要CorsFilter,最后我只是在端点上使用了@CrossOrigin注释。
答案 1 :(得分:1)
这是一个标准的CORS问题,这基本上意味着用户代理即http://localhost:3000
无权访问http://localhost:8085
的资源。您可以在https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS了解更多相关信息。
您的请求标头应完全映射到服务器规则。将任何参数保留为*
都不起作用。
例如,如果您的请求标头包含以下内容:
Access-Control-Request-Method: POST
Access-Control-Request-Headers: <your custom headers>
然后,服务器规则显示映射您的请求标头:
Access-Control-Request-Method: GET, PUT, DELETE, POST
Access-Control-Request-Headers: <your custom headers>
让我知道它是否有帮助!
答案 2 :(得分:1)
我也遇到了这个问题,但是请允许我以一种更简单的交流方式给出直接的答案。
首先,您必须告诉服务器(Spring boot java)关于客户端(Reactjs) URL 。
例如,大多数情况下,spring boot使用http://localhost:8080
和Reactjs uses http://localhost:3000
。
因此,您必须导航到Spring boot java中的控制器,并允许Reactjs的 URL 被授予服务器中的可访问性权限(Spring boot)。这将帮助您摆脱 CORS 问题。
我们如何在Spring Boot中做到这一点?只需添加@CrossOrigin
批注,指定Reactjs URL 链接,如下所示:
例如:
@GetMapping("/orphans")
@CrossOrigin(origins = "http://localhost:3000")
Iterable<Student> read() {
return studentService.findAll();
}
上面的方法是列出所有孤儿,所以我给了Reactjs URL 链接权限,然后摆脱了 CORS 问题。
快乐的编码。
答案 3 :(得分:0)
请参阅下面的示例代码来解决此问题。
@CrossOrigin(origins = "http://localhost:3000")
@RequestMapping(value="/sample", method = RequestMethod.GET, produces = "application/json")
public Student getStudent(){
}
答案 4 :(得分:0)
在获取的代码行下方添加
export function getData(endpoint = '/', request = {}) {
let url = endpoint;
let req = Object.assign(
{
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
},
request
);
console.log('url,req', url, req);
return fetch(url, req).then(handleResponse).catch(handleErrors);
}
并在Rest Controller类下方添加以下行
@RestController
@CrossOrigin(origins = "*", allowedHeaders = "*")
class TestController{}
希望这会有所帮助:)