1. Overview
1.概述
In this short tutorial, we’re going to take a close look at how to disable logout redirects in Spring Security.
在这个简短的教程中,我们将仔细研究如何在Spring Security中禁用注销重定向。
We’ll first start with a brief background on how the logout flow works in Spring Security. Then, we’ll illustrate, through a practical example, how to avoid user redirection after a successful logout.
首先,我们将简要介绍一下Spring Security中注销流程的工作背景。然后,我们将通过一个实际的例子来说明如何在成功注销后避免用户重定向。
2. Logout in Spring Security
2.在Spring Security中注销
In short, Spring Security provides out-of-box support for the logout mechanism through the logout() DSL method. Basically, Spring Security triggers log out when a user hits the default logout URL which is /logout.
简而言之,Spring Security通过logout() DSL方法为注销机制提供开箱即用的支持。基本上,当用户点击默认的注销URL(即/logout.时,Spring Security会触发注销。
It’s worth mentioning that the default value of the logout URL was /j_spring_security_logout before Spring Security 4.
值得一提的是,在Spring Security 4之前,注销URL的默认值是/j_spring_security_logout。。
Spring Security offers the possibility to redirect users to a particular URL after logging out. However, there are some occasions when we want to avoid this behavior.
Spring Security提供了在注销后将用户重定向到一个特定URL的可能性。然而,在某些情况下,我们希望避免这种行为。
So, without further ado, let’s see how to implement the logic of disabling logout redirects in Spring Security.
因此,不再赘述,让我们看看如何在Spring Security中实现禁用注销重定向的逻辑。
3. Disable Spring Security Logout Redirect
3.禁用Spring Security注销重定向
By default, Spring Security redirects users to /login?logout after a successful logout. So, in this section, we’re going to focus on how to prevent user redirection to the login page after logging out.
默认情况下,Spring Security会在用户成功注销后将其重定向到/login?logout。因此,在本节中,我们将重点讨论如何防止用户在注销后重定向到登录页面。
Note that we can override the default redirect URL with the help of the logoutSuccessUrl() DSL method.
请注意,我们可以在logoutSuccessUrl() DSL方法的帮助下覆盖默认的重定向URL,。
The main point here is to show how to avoid redirection when the /logout URL is being called from a REST client.
这里的重点是展示当/logoutURL被REST客户端调用时,如何避免重定向。
As a matter of fact, the LogoutSuccessHandler interface offers a flexible way to execute custom logic when the logout process is performed successfully.
事实上,LogoutSuccessHandler接口提供了一种灵活的方式,当注销过程被成功执行时执行自定义逻辑。
So here, we’ll use a custom LogoutSuccessHandler to return only a clean 200 status code. That way, it won’t redirect us to any page.
所以在这里,我们将使用一个自定义的LogoutSuccessHandler,只返回一个干净的200状态代码。这样,它就不会将我们重定向到任何页面。
Now, let’s implement the necessary Spring Security configuration required to disable logout redirects:
现在,让我们实现禁用注销重定向所需的Spring Security配置。
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeRequests(authz -> authz.mvcMatchers("/login")
.permitAll()
.anyRequest()
.authenticated())
.logout(logout -> logout.permitAll()
.logoutSuccessHandler((request, response, authentication) -> {
response.setStatus(HttpServletResponse.SC_OK);
}));
return http.build();
}
}
The important part to note from the above configuration is the logoutSuccessHandler() method. As we can see, we use a lambda expression to define our custom logout success handler.
上述配置中需要注意的重要部分是logoutSuccessHandler()方法。正如我们所看到的,我们使用lambda表达式来定义我们的自定义注销成功处理器。
Bear in mind that we can also create a simple implementation class of the LogoutSuccessHandler interface and use DSL to pass it to the logoutSuccessHandler() method.
请记住,我们也可以创建一个简单的实现类的LogoutSuccessHandler接口,并使用DSL将其传递给logoutSuccessHandler()方法。
4. Testing
4.测试
Now that we put all the pieces together let’s test the /logout endpoint to confirm that everything works as expected.
现在我们把所有的部分放在一起,让我们测试一下/logout端点,以确认一切都按预期进行。
Note that we’ll be using MockMvc to send /logout request in our test.
注意,我们将使用MockMvc来在我们的测试中发送/logout请求。
First, let’s create a simple test class and inject the MockMvc object in it:
首先,让我们创建一个简单的测试类,并在其中注入MockMvc对象:。
public class LogoutApplicationUnitTest {
@Autowired
private MockMvc mockMvc;
// test case
}
Now, let’s write a method to test our /logout endpoint:
现在,让我们写一个方法来测试我们的/logout端点:。
@Test
public void whenLogout_thenDisableRedirect() throws Exception {
this.mockMvc.perform(post("/logout").with(csrf()))
.andExpect(status().isOk())
.andExpect(jsonPath("$").doesNotExist())
.andExpect(unauthenticated())
.andReturn();
}
Lastly, let’s try to break down our test code:
最后,让我们试着分解我们的测试代码。
- perform(post(“/logout”)) invokes the /logout endpoint as a simple POST request
- with(csrf()) adds the expected _csrf parameter to the query
- status() returns the status code of the HTTP response
- jsonPath() allows to access and inspect the body of the HTTP response
5. Conclusion
5.总结
To sum up, we’ve explained and illustrated how to tackle the challenge of disabling logout redirects in Spring Security and Spring Boot.
综上所述,我们已经解释并说明了如何解决Spring Security和Spring Boot中禁用注销重定向的难题。
As usual, the complete source code for this article is available over on GitHub.
像往常一样,本文的完整源代码可在GitHub上获得,。