[英]CORS request won't work in Firefox, works in Chrome and Safari
[英]CORS POST request fails on Chrome, Safari and Firefox
我有一个在localhost:8080上运行的具有Spring Security的RESTfull后端,登录过滤器使用放置在标题中的令牌响应登录请求,我什至没有实现Endpoint方法,这全部由Spring Security魔术完成通过以下代码行:
protected void configure(HttpSecurity http) throws Exception {
// disable caching
http.headers().cacheControl();
http.csrf().disable() // disable csrf for our requests.
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
// We filter the api/login requests
.addFilterBefore(new JWTLoginFilter("/login", authenticationManager()), UsernamePasswordAuthenticationFilter.class)
…
前端是一个在localhost:8000上运行静态http服务器的Angularjs Nodejs NPM Bower项目。 在前端,我发出一个简单的POST请求,如下所示:
$scope.login = function () {
var data = {
"username":$scope.username,
"password":$scope.password
}
$http({
url: baseUrl,
method: "POST",
data: data
}).then(function (response) {
console.log("###### SUCCESS #####");
var headers = response.headers();
console.log("headers: "+JSON.stringify(headers));
var token = headers.authorization.split(" ")[1];
console.log("token: "+token);
$http.defaults.headers.common['Authorization'] = token;
$location.path("/view1");
}, function (responseData) {
// called asynchronously if an error occurs
// or server returns responseData with an error status.
console.log("###### FAIL #####");
console.log("Response: "+JSON.stringify(responseData));
$window.alert("Failed to Login");
});
这就像IE中的一种魅力一样(也适用于curl,wget和python请求),但在Chrome和Safary上却失败了。 我知道这些浏览器正在阻止CORS POST,从而使该请求一到达后端就为空,实际上,当我从后端注销请求时,我看不到任何数据。 我尝试了以下所有可能的组合:
前端侧:
1)$ http(方法:POST)
2)$ http.post(
3)添加标志:Access-Control-Allow-Origin,Access-Control-Expose等。
4)添加所有可能的标头组合:'Content-Type':'application /
浏览器端:
1)使用标志启动chrome:--disable-web-security
2)安装Chrome扩展程序CORS
后端:
1)春季安全禁用csfr
2)春季安全许可证全部
3)Spring Security HttpMethod.OPTION
没事,NHOTING对我有用!
有什么我想念的吗?
还有其他发送POST请求的方法吗?
编辑
如前所述,我将类修改如下:
WebSecurityConfig:
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
// We filter the api/login requests
.addFilterBefore(new JWTLoginFilter("/login", authenticationManager()), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new CORSFilter(), BasicAuthenticationFilter.class)
并实现了CORSFilter作为建议。
我还根据建议添加了WebConfig类:
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("http://localhost:8000")
.allowedMethods("PUT", "POST");
}
}
由于字符串为空,因此登录过滤器将抛出:
com.fasterxml.jackson.databind.JsonMappingException:由于输入结束,没有要映射的内容
Spring Security将拒绝访问此消息。
我还尝试将前端服务器移至其他端口,然后移至8000(4200、7000等),但均未成功。
您需要在春季启用Cors支持。 在您的WebConfig中,您可以覆盖addCorsMappings
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("http://localhost:4200"); //url of where angular is running.
}
}
这使得整个应用程序都可以使用cors。 您还可以使用允许特定的标头和方法的映射来更具体。
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://domain2.com")
.allowedMethods("PUT", "DELETE")
.allowedHeaders("header1", "header2", "header3");
}
您还可以在类和方法级别允许用户@CrossOrgin
@CrossOrigin(origin = "http://domain2.com",
maxAge = 3600)
public class ApiController {
}
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cors.html
我以前使用过CORS过滤器,并且效果很好:
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())) {
response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
response.addHeader("Access-Control-Allow-Headers", "Content-Type");
response.addHeader("Access-Control-Max-Age", "1");
}
filterChain.doFilter(request, response);
}
}
然后将其添加到您的配置中:
.addFilterBefore(new CORSFilter()), BasicAuthenticationFilter.class)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.