Javascript CORS POST请求在Chrome、Safari和Firefox上失败
我在localhost:8080上使用Spring security实现了一个RESTfull后端,一个登录过滤器使用放置在头中的令牌响应登录请求,我甚至没有为此实现一个端点方法,这都是由Spring security magic通过以下代码行完成的:Javascript CORS POST请求在Chrome、Safari和Firefox上失败,javascript,angularjs,node.js,spring,google-chrome,Javascript,Angularjs,Node.js,Spring,Google Chrome,我在localhost:8080上使用Spring security实现了一个RESTfull后端,一个登录过滤器使用放置在头中的令牌响应登录请求,我甚至没有为此实现一个端点方法,这都是由Spring security magic通过以下代码行完成的: protected void configure(HttpSecurity http) throws Exception { // disable caching http.headers().cacheCon
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)
…
前端是一个Angularjs Nodejs NPM Bower项目,在localhost:8000上运行静态http服务器。在前端,我提出一个简单的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发布,一旦请求到达后端,请求就会变为空,事实上,当我从后端注销请求时,我看不到任何数据。我尝试了以下所有可能的组合:
前端侧:
1) $http(方法:POST)
2) $http.post(
3) 添加标志:访问控制允许来源、访问控制公开等
4) 添加所有可能的标题组合:“内容–类型”:“应用程序”/
浏览器端:
1) 使用标志启动chrome:--禁用web安全
2) 安装镀铬加长杆
后端端:
1) 弹簧安全禁用csfr
2) 春季安全许可证
3) Spring安全性HttpMethod.OPTION
什么都没有,NHOTING为我工作强>
有什么我遗漏的吗
是否有其他方式发送POST请求
编辑
如前所述,我对这些类进行了如下修改:
Web安全配置:
.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支持。在您的网络配置中,您可以覆盖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");
}
您还可以在类和方法级别允许user@CrossOrgin
@CrossOrigin(origin = "http://domain2.com",
maxAge = 3600)
public class ApiController {
}
我以前使用过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)
谢谢你,伙计,但这对我不起作用。我添加过滤器,然后在WebConfig中的loginFilter之前添加addFilter选项。它不会改变任何事情,CORS请求仍然阻塞。您必须将其添加到您的安全配置中,就在这
.addFilterBefore(新的JWTLoginFilter(“/login”,authenticationManager()),UsernamePasswordAuthenticationFilter.class)的正下方
您必须在基本身份验证筛选器之前添加它。
我的webconfig是WebSecurity配置适配器的子类,我必须完成更改应用程序结构吗?这是您对spring web security的配置。您需要创建另一个配置类并扩展WebMVCConfigureRadataper,然后重写addCorsMappings(CorsRegistry Registry)方法。完成了,但仍然不起作用!我将WebConfig与SpringSecurityConfig并行,我是否必须注意到Spring类在那里?取决于应用程序的设置方式。如果您使用的是spring boot,则只需使用@Configuration对这两种配置进行注释。如果它仍然不能工作,Spring会处理它,您可以添加您修改/添加的代码(配置类)以及您得到的任何错误(如果有的话)。