由于某些原因,这个简单的问题阻碍了许多开发人员。我为这个简单的事情挣扎了好几个小时。这个问题多维度:
- 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-Headers 是基本身份验证最重要的东西。
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>
希望这会有所帮助。