Google Chrome 浏览器引入了需要设置 Same-Site header 的更改。为了实现这一点,我添加了一个自定义过滤器,如下所示,
public class SameSiteFilter extends GenericFilterBean {
private Logger LOG = LoggerFactory.getLogger(SameSiteFilter.class);
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse resp = (HttpServletResponse)response;
response = addSameSiteCookieAttribute((HttpServletResponse) response);
chain.doFilter(request, response);
}
private HttpServletResponse addSameSiteCookieAttribute(HttpServletResponse response) {
Collection<String> header = response.getHeaders(HttpHeaders.SET_COOKIE);
LOG.info(String.format("%s; %s", header, "SameSite=None; Secure"));
response.setHeader(HttpHeaders.SET_COOKIE, String.format("%s; %s", header, "SameSite=None; Secure"));
return response;
}
}
以下是安全配置的代码
@Configuration
@EnableWebMvcSecurity
public class CustomSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private OnyxUserDetailsService onyxUserDetailsService;
@Autowired
private CustomAuthenticationProvider customAuthenticationProvider;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/rest/user", "/info/**/*","/rest/version/check")
.permitAll().antMatchers("/data/**/*")
.access("hasRole('ROLE_ADMIN')").anyRequest()
.fullyAuthenticated().and().httpBasic().realmName("ADOBENET")
.and().logout().
logoutSuccessHandler((new LogoutSuccessHandler() {
@Override
public void onLogoutSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
response.setStatus(HttpStatus.OK.value());
response.getWriter().flush();
}
})).deleteCookies("JSESSIONID", "XSRF-TOKEN")
.invalidateHttpSession(true).logoutUrl("/rest/logout")
.logoutSuccessUrl("/rest/user").and()
.addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class)
.addFilterAfter(new SameSiteFilter(), BasicAuthenticationFilter.class)
.csrf().disable();
}
@Override
@Order(Ordered.HIGHEST_PRECEDENCE)
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.authenticationProvider(customAuthenticationProvider);
}
}
但是,当我查看收到的 header 时,我明白了
过滤器会在所有响应中添加必填字段,但包含 JSESSIONID cookie 的响应除外。如何将 header 添加到此 cookie。我尝试配置 tomcat 设置,但我们将代码部署为 WAR 文件,因此也不起作用。
最佳答案
为了解决这个问题,我添加了一个过滤器来筛选所有响应。这是相同的代码,
@Component
public class SameSiteFilter implements Filter {
private Logger LOG = LoggerFactory.getLogger(SameSiteFilter.class);
@Override
public void init(final FilterConfig filterConfig) throws ServletException {
LOG.info("Same Site Filter Initializing filter :{}", this);
}
@Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
LOG.info("Same Site Filter Logging Response :{}", res.getContentType());
Collection<String> headers = res.getHeaders(HttpHeaders.SET_COOKIE);
boolean firstHeader = true;
for (String header : headers) { // there can be multiple Set-Cookie attributes
if (firstHeader) {
res.setHeader(HttpHeaders.SET_COOKIE, String.format("%s; %s", header, "SameSite=None"));
LOG.info(String.format("Same Site Filter First Header %s; %s", header, "SameSite=None; Secure"));
firstHeader = false;
continue;
}
res.addHeader(HttpHeaders.SET_COOKIE, String.format("%s; %s", header, "SameSite=None"));
LOG.info(String.format("Same Site Filter Remaining Headers %s; %s", header, "SameSite=None; Secure"));
}
chain.doFilter(req, res);
}
@Override
public void destroy() {
LOG.warn("Same Site Filter Destructing filter :{}", this);
}
}
这允许在包含 cookie 的响应中添加所需的 header
关于java - 将相同的站点 header 添加到 JSESSIONID Spring Security,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60865649/