在我的 Spring 项目中,我将注销目标 url 设置为“/login?logout”以显示登录页面并显示消息“您现在已注销”。
在 Spring Security 配置中,我这样做了:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/error").permitAll()
.anyRequest().fullyAuthenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.successHandler(loginSuccessHandler)
.failureUrl("/login?error")
.and()
.httpBasic()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.permitAll()
.logoutSuccessHandler(logoutSuccessHandler);
}
还有 logoutSuccessHandler :
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
if (authentication != null) {
Log.debug(authentication.getName() + " LOGOUT !!");
}
setDefaultTargetUrl("/login?logout");
super.onLogoutSuccess(request, response, authentication);
}
当我尝试注销时,我到达了“/login”页面(没有 ?logout)。 我不明白为什么它会在此页面上重定向我。
我认为应用程序正在尝试将我重定向到“/login?logout”,但由于我不再连接,Spring 安全性希望我再次登录。
当我在登录时尝试访问“/login?logout”页面时,它会显示正确的页面。
我通过添加以下内容找到了解决此问题的方法:
.authorizeRequests()
.antMatchers("/error","/login").permitAll()
loginPage("/login").permitAll()
为什么不这样做?
我是不是做错了什么?
最佳答案
为什么不 loginPage("/login").permitAll()
允许访问 /login?logout
?
因为当您在 FormLoginConfigurer
或大多数其他配置器上执行 permitAll
时,它只允许访问那些 exact URLs .
那么,为什么 authorizeRequests().antMatchers("/login").permitAll()
那么允许访问呢?
因为它使用了一个AntPathRequestMatcher
,它matches on the request path only , 和路径 does not contain the query string .
但我知道我已经看到了允许我访问的代码 /login?logout
没有任何明确的 permitAll
完全没有。这是怎么回事?
Spring Security 喜欢提供“合理的”默认值,如果没有指定默认登录和注销页面,它认为提供默认的登录和注销页面是“合理的”。默认的注销页面是/login?logout
,所以如果你什么都不指定,你就可以使用它。这是由 DefaultLoginPageGeneratingFilter
完成的,它会自动生成一些 HTML 和 short-circuits URL authorization .
那么当我指定一个 logoutSuccessHandler
时,为什么我无法访问默认页面 /login?logout
页面?
当您指定自己的 logoutSuccessHandler
或 logoutSuccessUrl
时,Spring Security 假定您提供自己的注销 View ,因此它不会初始化 DefaultLoginPageGeneratingFilter
用于在注销页面短路 URL 授权,并希望您自己在自己的 View 上配置授权。
但我想保留默认的注销页面。我只想添加一些自定义的额外处理。我不能这样做吗?
如果您想指定自己的 logoutSuccessHandler
但仍保留默认的 /login?logout
View ,则必须告诉 DefaultLoginPageGeneratingFilter
仍然继续提供它。您可以使用自定义 SecurityConfigurer
,如下:
.logoutSuccessHandler(logoutSuccessHandler)
.and()
.apply(new SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity>() {
@Override public void configure(HttpSecurity builder) throws Exception {
builder.getSharedObject(DefaultLoginPageGeneratingFilter.class).setLogoutSuccessUrl("/login?logout");
}
})
关于java - 为什么/login?logout 会重定向到/login?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33167609/