我正在开发基于React的第一个前端应用程序。此应用程序的目的是连接到RESTful API以获取和发布数据。问题是我无法发送令牌标头以通过安全检查,因此请求失败。
我根据我使用的浏览器得到不同的错误。
这是我的main.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import promise from 'es6-promise';
import 'isomorphic-fetch';
promise.polyfill();
class Employee extends React.Component {
constructor(props){
super(props);
this.state = {employees : []};
}
componentWillMount(){
fetch('http://localhost:8080/app/rest/employees',{ method: 'get', headers: {'Access-Control-Allow-Origin': 'http://localhost:8080', 'Content-Type': 'x-www-form-urlencoded', 'token' : '93edf459ba78d13be0e9d21143238f43796de1f6ebbc58b133af7f33b8222676'}})
.then((response) => {
return response.json();
})
.then((downscalings) => {
this.setState({ employees: values });
})
}
update(){
this.setState({name : 'John'});
}
render(){
return <div>
<input type="text" value="aaaa"></input>
<button onClick={this.update}>Set name</button>
</div>
}
}
ReactDOM.render(
<Employee/>,
document.getElementById('container')
);
这是浏览器的输出日志错误:
Failed to load resource: the server responded with a status of 401 (No Autorizado)
index.html:1 Fetch API cannot load http://localhost:8080/app/rest/employees. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. The response had HTTP status code 401. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
index.html:1 Uncaught (in promise) TypeError: Failed to fetch(…)
这是净追踪:
获取员工
本地主机:8080
0 B
OPTIONS员工
401未经授权
本地主机:8080
37 B
我假设未发送标头,因此REST服务拒绝该请求。由于警告,我还添加了CORS标头。我做错了什么?
答案 0 :(得分:2)
我将回答我自己的回答。感谢@ cema-sp找到正在发生的事情的关键。
这里的问题与我的Spring项目中的CORS配置有关。此Spring项目基于令牌安全性公开REST API。它有两个问题:
1-OPTIONS请求被安全令牌过滤器阻止:
我不知道CORS是如何工作的。 CORS,跨源资源共享,定义了一种启用客户端跨源请求的机制。 CORS受到FireFox,Chrome,Safari和IE等现代浏览器的广泛支持。如果您只是运行我的提取并调用后端,您可能会注意到GET请求已更改为OPTIONS并且有一个GET请求正在等待(您可以看到在我的初始帖子中查看图像)。浏览器向服务器发送OPTIONS请求,服务器需要发送带有正确标头的响应。因此,您需要将这些标头添加到OPTIONS请求中。
在回复中,您必须包含前端应用可用的标头。就我而言,我添加了令牌标头来验证请求。如果您使用的是Spring 3.1,则需要创建一个这样的过滤器:
public class CORSFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
response.addHeader("Access-Control-Allow-Origin", "*");
if (request.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(request.getMethod())) {
// CORS "pre-flight" request
response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
response.addHeader("Access-Control-Allow-Headers", "Content-Type, token");
response.addHeader("Access-Control-Max-Age", "1");// 30 min
}
filterChain.doFilter(request, response);
}
}
然后将其添加到web.xml
<filter>
<filter-name>cors</filter-name>
<filter-class>es.predictia.dp.web.security.CORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>cors</filter-name>
<url-pattern>/rest/*</url-pattern>
</filter-mapping>
如果您使用的是春季4,请查看此帖子https://spring.io/blog/2015/06/08/cors-support-in-spring-framework
2 - 它正在重置所有响应,以避免在响应中注入jsessionid。现在我直接删除了set-cookie。
谢谢大家