【发布时间】:2017-08-15 19:17:12
【问题描述】:
我有一个在 localhost:8080 上运行 Spring 安全性实现的 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)
…
前端是 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 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) Spring Security 禁用 csfr
2) Spring Security 全部许可
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 等),但没有成功。
【问题讨论】:
标签: javascript angularjs node.js spring google-chrome