由于某些原因,这个简单的问题阻碍了许多开发人员。这个简单的事情让我挣扎了很多小时。这个问题涉及多个维度:
- CORS(如果您在不同的域和端口上使用前端和后端。
- 后端CORS配置
- Axios的基本身份验证配置
CORS
我的开发设置是使用在localhost:8081上运行的vuejs Webpack应用程序和在localhost:8080上运行的spring boot应用程序。因此,当尝试从前端调用rest API时,如果没有正确的CORS设置,浏览器将无法让我从spring后端收到响应。CORS可用于放松现代浏览器所具有的跨域脚本(XSS)保护。据我了解,浏览器正在保护您的SPA免受XSS的攻击。当然,有关StackOverflow的一些答案建议添加一个chrome插件来禁用XSS保护,但这确实有效,并且如果确实如此,只会将不可避免的问题推迟到以后。
后端CORS配置
这是您应该在Spring Boot应用程序中设置CORS的方法:
添加一个CorsFilter类以在对客户端请求的响应中添加适当的标头。Access-Control-Allow-Origin和Access-Control-Allow-Header是基本身份验证中最重要的内容。
public class CorsFilter implements Filter {
...
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request = (HttpServletRequest) servletRequest;
response.setHeader("Access-Control-Allow-Origin", "http://localhost:8081");
response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH");
**response.setHeader("Access-Control-Allow-Headers", "authorization, Content-Type");**
response.setHeader("Access-Control-Max-Age", "3600");
filterChain.doFilter(servletRequest, servletResponse);
}
...
}
添加一个扩展Spring WebSecurityConfigurationAdapter的配置类。在本课程中,您将插入CORS过滤器:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
@Bean
CorsFilter corsFilter() {
CorsFilter filter = new CorsFilter();
return filter;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(corsFilter(), SessionManagementFilter.class) //adds your custom CorsFilter
.csrf()
.disable()
.authorizeRequests()
.antMatchers("/api/login")
.permitAll()
.anyRequest()
.authenticated()
.and()
.httpBasic()
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.authenticationProvider(getProvider());
}
...
}
您无需在控制器中放入与CORS相关的任何内容。
前端
现在,在前端,您需要使用Authorization标头创建axios查询:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<p>{{ status }}</p>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
status: ''
},
created: function () {
this.getBackendResource();
},
methods: {
getBackendResource: function () {
this.status = 'Loading...';
var vm = this;
var user = "aUserName";
var pass = "aPassword";
var url = 'http://localhost:8080/api/resource';
var authorizationBasic = window.btoa(user + ':' + pass);
var config = {
"headers": {
"Authorization": "Basic " + authorizationBasic
}
};
axios.get(url, config)
.then(function (response) {
vm.status = response.data[0];
})
.catch(function (error) {
vm.status = 'An error occured.' + error;
})
}
}
})
</script>
</body>
</html>
希望这可以帮助。