我有一个spring引导应用程序,其步骤如下:
用户登录到application
。
问题:
在Mozilla Firefox中一切都很好
在Chrome浏览器中,第一次似乎没有问题(所有步骤1-5),但经过多次(可以是第二次、第三次或更多次随机方式)之后,应用程序将显示登录页面(返回到应用程序/卡片响应时的步骤4),因为用户是未经身份验证的。
如果我在第4步之前和之后(在Application->Cookies)之前和之后在浏览器中检查会话cookie (JSESSIONID),并且是相同的,不变的。此外,在应用程序显示登录页后,如果我将URL /card-response直接放在浏览器中,则无需登录页面就可以访问应用程序,因此应用程序正在考虑我的身份验证。
在spring应用程序日志中:
DEBUG org.springframework.security.web.access.ExceptionTranslationFilter@4f5a3111, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@3fdb1ce4]] (1/1)
DEBUG org.springframework.security.web.FilterChainProxy - Securing POST /card-response
TRACE org.springframework.security.web.FilterChainProxy - Invoking WebAsyncManagerIntegrationFilter (1/13)
TRACE org.springframework.security.web.FilterChainProxy - Invoking SecurityContextPersistenceFilter (2/13)
TRACE org.springframework.security.web.context.HttpSessionSecurityContextRepository - **No HttpSession currently exists**
TRACE org.springframework.security.web.context.HttpSessionSecurityContextRepository - Created SecurityContextImpl [Null authentication]
DEBUG org.springframework.security.web.context.SecurityContextPersistenceFilter - Set SecurityContextHolder to empty SecurityContext在WebSecurityConfig我有
http
.authorizeRequests()
.antMatchers("/resources/free/**").permitAll()
.antMatchers("/rest-mock/**").permitAll()
.antMatchers("/reset-password-init").permitAll()
.antMatchers("/reset-password/**").permitAll()
.antMatchers("/remote-login/**").permitAll()
.antMatchers("/check-certificate/**").permitAll()
.anyRequest().authenticated()
.and().formLogin().loginPage("/login").successHandler(successHandler).permitAll()
.and().exceptionHandling().accessDeniedPage("/logout")
.and().logout().invalidateHttpSession(true).clearAuthentication(true).deleteCookies("JSESSIONID").permitAll()
.and().csrf()
.ignoringAntMatchers("/card-response/**","/rest-mock/**");如果步骤4正常(总是使用Firefox access,并不时使用Chrome access),那么spring应用程序日志是:
DEBUG org.springframework.security.web.FilterChainProxy - Securing GET /card-response
TRACE org.springframework.security.web.FilterChainProxy - Invoking WebAsyncManagerIntegrationFilter (1/13)
TRACE org.springframework.security.web.FilterChainProxy - Invoking SecurityContextPersistenceFilter (2/13)
TRACE org.springframework.security.web.context.HttpSessionSecurityContextRepository - Retrieved SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=User [id=28327, user_name=xxxxxxxxxx, first_name=xxxxxxxxxx, last_name=xxxxxxxxxx, email=xxxxx@domain.ro], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=D24B7748BA6C2C59B1C4FAB3D16C6B19], Granted Authorities=[Role [id=3, name=Lawyer]]]] from SPRING_SECURITY_CONTEXT
DEBUG org.springframework.security.web.context.SecurityContextPersistenceFilter - Set SecurityContextHolder to SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=User [id=28327, user_name=xxxxxxxxxx, first_name=xxxxxxxxxx, last_name=xxxxxxxxxx, email=xxxxx@domain.ro], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [SessionId=D24B7748BA6C2C59B1C4FAB3D16C6B19], Granted Authorities=[Role [id=3, name=Lawyer]]]]
TRACE org.springframework.security.web.FilterChainProxy - Invoking HeaderWriterFilter (3/13)因此,此上下文中的会话不是空的,一切正常。
问题是为什么spring安全性获得空会话并记录“当前不存在HttpSession”,但是在Chrome会话cookie中,在第一步开始时没有改变。
对于步骤4的成功,请求头包含cookie:
POST /caav_interface/card-response HTTP/1.1
Host: localhost:8081
Connection: keep-alive
Content-Length: 281
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: null
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: navigate
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: JSESSIONID=7B0E48E550B98EAE6CBF2D7E2AB76B59对于不成功的请求,请求不包含它:
POST /caav_interface/card-response HTTP/1.1
Host: localhost:8081
Connection: keep-alive
Content-Length: 281
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: null
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: navigate
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9因此,Chrome似乎并不总是在标题中传递cookie。
发布于 2021-01-08 13:55:50
解决办法:
Chrome考虑不带SameSite属性的JSESSIONID禁止在不同站点之间传递它。
因此,cookie必须有属性"SameSite=None;Secure“才能在站点之间传递它。
有时候在Chrome中工作的原因是Chrome在最初的1到2分钟内在站点之间传递它。
属性安全是必要的,因为Chrome考虑在没有SSL/TLS上下文的站点之间传递cookie是不安全的。
考虑到对于本地测试/开发,您必须省略这些属性,或者在Firefox浏览器上进行测试。
在java中实现:从onAuthenticationSuccess重写SavedRequestAwareAuthenticationSuccessHandler方法
Collection<String> headers = response.getHeaders(HttpHeaders.SET_COOKIE);
boolean firstHeader = true;
// there can be multiple Set-Cookie attributes
for (String header : headers) {
if (firstHeader) {
response.setHeader(HttpHeaders.SET_COOKIE,
String.format("%s; %s", header, "SameSite=None; Secure"));
firstHeader = false;
continue;
}
response.addHeader(HttpHeaders.SET_COOKIE,
String.format("%s; %s", header, "SameSite=None; Secure"));
}谢谢你为我指明了正确的方向!
希望能帮上忙,我花了很多时间在这上面
https://stackoverflow.com/questions/65569279
复制相似问题