[英]Spring Security 4.x set logout method to GET with xml config
[英]Spring CSRF override “POST” logout behaviour in security XML config
目前我们的遗留应用程序的Spring CSRF解决方案存在问题,因为CSRF实现更改了默认Spring安全性Spring安全配置的行为:
<http pattern="">
...
<logout
logout-url="/logout"
delete-cookies="..."
success-handler-ref="logoutSuccessHandler"
/>
<csrf/>
</http>
org.springframework.security.config.annotation.web.configurers.LogoutConfigurer
注销配置器。 根据Spring文档:
添加CSRF会将LogoutFilter更新为仅使用HTTP POST。 这可确保注销需要CSRF令牌,并且恶意用户无法强制注销您的用户。
进行此更改的代码如下:
private RequestMatcher getLogoutRequestMatcher(H http) {
if(logoutRequestMatcher != null) {
return logoutRequestMatcher;
}
if(http.getConfigurer(CsrfConfigurer.class) != null) {
this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl, "POST");
} else {
this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl);
}
return this.logoutRequestMatcher;
}
通常,对于CSRF保护,这种行为非常有意义。 但对于我来说,这种实现不灵活(为什么硬编码实际的实现而不是autowire依赖?)是非常奇怪的。
问题是我们的应用程序是这样构建的,即在常规Spring注销之前,它会在Spring Controllers中执行额外的清理。 主要是它实现了Switch User功能,但是以自定义方式实现。 因此,更改注销链接以执行POST不是一种选择,因为主要是在自定义控制器上执行清理。
似乎为了使用指定的方法,只有一种可能的解决方案:
@RequestMapping(value = "/logout", method = RequestMethod.GET) //or it can be a post
public String logout() {
// 1. Perform Clean up
// 2. Decide whether to logout or redirect to other page
// 3. Perform redirect based on decision
}
//如果决定退出,则会转到此Controller方法:
@RequestMapping(value = "csrflogout", method = RequestMethod.GET)
public void csrfLogout(){
//1 Create manual post request
//2. Copy session information
//3. Perform Post to logout URL that is specified in security xml
}
从代码质量的角度来看,这种方法通常并不好。 所以,有两个问题:
您描述的行为是行为,如果您没有显式配置注销支持但只启用它,您明确配置它将使用该配置。
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
}
这也被记录在参考指南中。
然而,真正的解决方案是你不应该使用控制器来实现额外的注销功能,而是使用LogoutHandler 。 这将很好地与Spring Security集成,您不需要重定向/转发到不同的URL。
基本上,主要的复杂性是在Spring Security XML上下文中重写logoutFilter,以使用org.springframework.security.web.util.matcher.AntPathRequestMatcher的默认实现(使用“GET”而不是“POST”请求)。 为了做到这一点,将几个bean添加到安全xml上下文中:
<bean id="logoutAntPathRequestMatcher" class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
<constructor-arg value="logout" />
</bean>
和注销过滤器本身:
<bean id="logoutFilter"
class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg name="logoutSuccessHandler" ref="logoutSuccessHandler"/>
<constructor-arg name="handlers">
<list>
<ref bean="securityContextLogoutHandler" />
<ref bean="cookieClearingLogoutHandler" />
<ref bean="csrfLogoutHandler" />
</list>
</constructor-arg>
<property name="filterProcessesUrl" value="/logout"/>
<property name="logoutRequestMatcher" ref="logoutAntPathRequestMatcher"/>
</bean>
Internet Explorer 11更新后,我看到了同样的错误。 CsrfConfigurer.class不为null,并且在注销时需要发布。
if(http.getConfigurer(CsrfConfigurer.class) != null) {
this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl, "POST");
} else {
this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl);
}
我通过绕过logoutfilter并插入新的过滤器来解决我的问题
示例如下。
<beans:bean id="logoutAntPathRequestMatcher" class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
<beans:constructor-arg value="/logout"/>
</beans:bean>
<beans:bean id="securityContextLogoutHandler" class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler">
</beans:bean>
<beans:bean id="cookieClearingLogoutHandler" class="org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler">
<beans:constructor-arg value="JSESSIONID"/>
</beans:bean>
<beans:bean id="logoutFilter"
class="org.springframework.security.web.authentication.logout.LogoutFilter">
<beans:constructor-arg name="logoutSuccessUrl" value="/login"/>
<beans:constructor-arg name="handlers">
<beans:list>
<beans:ref bean="securityContextLogoutHandler" />
<beans:ref bean="cookieClearingLogoutHandler" />
</beans:list>
</beans:constructor-arg>
<beans:property name="filterProcessesUrl" value="/logout"/>
<beans:property name="logoutRequestMatcher" ref="logoutAntPathRequestMatcher"/>
</beans:bean>
<http>
...
<sec:custom-filter ref="logoutFilter" after="LOGOUT_FILTER"/>
...
</http>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.