有两台服务器,第一个是 angular url: http://localhost:4200
,第二个是带有 Spring Boot url: 的 tomcat http:localhost:8080
。
当我尝试发送POST
请求时,浏览器说
Запрос из постороннего источника заблокирован: Политика одного источника
запрещает чтение удаленного ресурса на http://localhost:8080/.
(Причина: отсутствует заголовок CORS «Access-Control-Allow-Origin»).
日志Tomcat
2016-12-02 06:51:10.134 DEBUG 8380 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing OPTIONS request for [/]
2016-12-02 06:51:10.136 DEBUG 8380 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /
2016-12-02 06:51:10.140 DEBUG 8380 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Returning handler method [public void org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$EmptyHandler.handle()]
2016-12-02 06:51:10.149 DEBUG 8380 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
2016-12-02 06:51:10.149 DEBUG 8380 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Successfully completed request
2016-12-02 06:51:10.149 DEBUG 8380 --- [nio-8080-exec-1] o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'delegatingApplicationListener'
2016-12-02 06:51:10.150 DEBUG 8380 --- [nio-8080-exec-1] o.s.s.w.a.ExceptionTranslationFilter : Chain processed normally
2016-12-02 06:51:10.150 DEBUG 8380 --- [nio-8080-exec-1] o.s.s.w.header.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@329e259c
2016-12-02 06:51:10.150 DEBUG 8380 --- [nio-8080-exec-1] w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2016-12-02 06:51:10.150 DEBUG 8380 --- [nio-8080-exec-1] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
2016-12-02 06:51:10.150 DEBUG 8380 --- [nio-8080-exec-1] o.s.b.w.f.OrderedRequestContextFilter : Cleared thread-bound request context: org.apache.catalina.connector.RequestFacade@5dd5a01e
2016-12-02 06:51:10.159 DEBUG 8380 --- [nio-8080-exec-2] o.s.b.w.f.OrderedRequestContextFilter : Bound request context to thread: org.apache.catalina.connector.RequestFacade@5dd5a01e
2016-12-02 06:51:10.159 DEBUG 8380 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/'; against '/css/**'
2016-12-02 06:51:10.159 DEBUG 8380 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/'; against '/js/**'
2016-12-02 06:51:10.159 DEBUG 8380 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/'; against '/images/**'
2016-12-02 06:51:10.159 DEBUG 8380 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/'; against '/webjars/**'
2016-12-02 06:51:10.159 DEBUG 8380 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/'; against '/**/favicon.ico'
2016-12-02 06:51:10.159 DEBUG 8380 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/'; against '/error'
2016-12-02 06:51:10.159 DEBUG 8380 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : / at position 1 of 10 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2016-12-02 06:51:10.159 DEBUG 8380 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : / at position 2 of 10 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2016-12-02 06:51:10.159 DEBUG 8380 --- [nio-8080-exec-2] w.c.HttpSessionSecurityContextRepository : No HttpSession currently exists
2016-12-02 06:51:10.159 DEBUG 8380 --- [nio-8080-exec-2] w.c.HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: null. A new one will be created.
2016-12-02 06:51:10.159 DEBUG 8380 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : / at position 3 of 10 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2016-12-02 06:51:10.159 DEBUG 8380 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : / at position 4 of 10 in additional filter chain; firing Filter: 'CsrfFilter'
2016-12-02 06:51:10.167 DEBUG 8380 --- [nio-8080-exec-2] o.s.security.web.csrf.CsrfFilter : Invalid CSRF token found for http://localhost:8080/
2016-12-02 06:51:10.167 DEBUG 8380 --- [nio-8080-exec-2] o.s.s.w.header.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@329e259c
2016-12-02 06:51:10.167 DEBUG 8380 --- [nio-8080-exec-2] w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2016-12-02 06:51:10.167 DEBUG 8380 --- [nio-8080-exec-2] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
2016-12-02 06:51:10.167 DEBUG 8380 --- [nio-8080-exec-2] o.s.b.w.f.OrderedRequestContextFilter : Cleared thread-bound request context: org.apache.catalina.connector.RequestFacade@5dd5a01e
2016-12-02 06:51:10.170 DEBUG 8380 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing POST request for [/error]
2016-12-02 06:51:10.170 DEBUG 8380 --- [nio-8080-exec-2] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /error
2016-12-02 06:51:10.171 DEBUG 8380 --- [nio-8080-exec-2] s.w.s.m.m.a.RequestMappingHandlerMapping : Returning handler method [public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)]
2016-12-02 06:51:10.171 DEBUG 8380 --- [nio-8080-exec-2] o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'basicErrorController'
2016-12-02 06:51:10.181 DEBUG 8380 --- [nio-8080-exec-2] o.s.c.e.PropertySourcesPropertyResolver : Found key 'spring.template.provider.cache' in [refresh] with type [String]
2016-12-02 06:51:10.185 DEBUG 8380 --- [nio-8080-exec-2] o.s.c.e.PropertySourcesPropertyResolver : Found key 'spring.template.provider.cache' in [refresh] with type [String]
2016-12-02 06:51:10.190 DEBUG 8380 --- [nio-8080-exec-2] o.s.w.s.v.ContentNegotiatingViewResolver : Requested media types are [text/html, text/html;q=0.8] based on Accept header types and producible media types [text/html])
2016-12-02 06:51:10.190 DEBUG 8380 --- [nio-8080-exec-2] o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'error'
2016-12-02 06:51:10.192 DEBUG 8380 --- [nio-8080-exec-2] o.s.b.f.s.DefaultListableBeanFactory : Invoking afterPropertiesSet() on bean with name 'error'
2016-12-02 06:51:10.192 DEBUG 8380 --- [nio-8080-exec-2] o.s.w.s.v.ContentNegotiatingViewResolver : Returning [org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$SpelView@1fba2013] based on requested media type 'text/html'
2016-12-02 06:51:10.192 DEBUG 8380 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Rendering view [org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$SpelView@1fba2013] in DispatcherServlet with name 'dispatcherServlet'
2016-12-02 06:51:10.197 DEBUG 8380 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Successfully completed request
如果您需要更多信息,我随时准备提供。
更新 1
CORS原来在config中配置如下:
@Configuration
@EnableWebMvc
public class WebMvcConfigure extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry
.addMapping("/**")
.allowedOrigins("*");
}
}
CSRF 的问题可以通过禁用它来部分解决,但在我看来这仍然不是最佳选择。我设法设置了 spring,以便将会话保存到 spring 自动创建的表中,并且为该会话分配了一个 csrf 令牌,该令牌也保存到表中,但只有一个关于添加带有会话 ID 的 cookie 的标题是发送给客户端,并且 csrf 令牌不会发送到任何地方。
以下是清除 cookie 时来自服务器的内容:
Access-Control-Allow-Origin: http://localhost:4200
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Language: ru-RU
Content-Length: 362
Content-Type: text/html;charset=ISO-8859-1
Date: Sat, 24 Dec 2016 20:11:44 GMT
Expires: 0
Pragma: no-cache
Set-Cookie: SESSION=7b4d0509-4cfb-40e0-9484-72abcdfe2375;path=/;Secure;HttpOnly
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
Vary: Origin
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
access-control-allow-credentials: true
这是客户端在下一个请求中发送的内容:
Host: localhost:8080
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:50.0) Gecko/20100101 Firefox/50.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br
Content-Type: application/json
Referer: http://localhost:4200/registration
Content-Length: 69
Origin: http://localhost:4200
Cookie: SESSION=7b4d0509-4cfb-40e0-9484-72abcdfe2375
DNT: 1
Connection: keep-alive
是否值得扩展该类HttpSessionCsrfTokenRepository
,以便令牌不仅保存到数据库中,而且还发送到客户端进行保存,或者是否有其他方法可以做到这一点?
你应该看看这里:https ://angular.io/docs/ts/latest/guide/security.html
Angular 的 http 在其 XSRFStrategy 中内置了对该技术的客户端部分的支持。默认的 CookieXSRFStrategy 是自动打开的。在发送 HTTP 请求之前,CookieXSRFStrategy 查找名为 XSRF-TOKEN 的 cookie,并使用该 cookie 的值设置名为 X-XSRF-TOKEN 的标头。
服务器必须通过设置初始 XSRF-TOKEN cookie 并确认每个后续状态修改请求都包含匹配的 XSRF-TOKEN cookie 和 X-XSRF-TOKEN 标头来完成自己的工作。
XSRF/CSRF 令牌对于每个用户和会话应该是唯一的,具有由加密安全随机数生成器生成的较大随机值,并且应该在一两天内过期
对接http://docs.spring.io/spring-security/site/docs/current/reference/html/csrf.html#csrf-cookie设置
或者您的服务器可能为此目的使用不同的 cookie 或标头名称。Angular 应用程序可以通过提供自己的 CookieXSRFStrategy 值来自定义 cookie 和标头名称。
该错误表示服务器上不允许跨域请求。尝试按照您指定的 spring 网站上
allowedOrigins("*")
的指示全局解决它们,或者代替“*”请求来自的主机。您还表示很可能是 CSRF。在spring security 4及以上版本中,该功能默认开启,必须禁用或启用。要禁用此功能,请调用对象上的
HttpSecurity
方法,以下.csrf().disable()
是如何执行此操作的示例:接下来,之后,在angular2中设置参数,在angular1
withCredentials = true;
中是这样设置的:$httpProvider.defaults.withCredentials = true;
,或者用这个参数发起请求,例如:如果不设置此设置,每次跨域请求都会创建一个新会话,而 spring security 将不起作用。