无法通过自定义注销处理程序注销

时间:2020-01-26 16:22:38

标签: spring-boot spring-security

在我的spring boot应用程序中,我想添加注销链接。

在模板welcome.html中:

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title th:text="${appName}">Template title</title>
<body>
<h1>Welcome to <span th:text="${appName}">Our App</span></h1>
<h2>Dictionaries:</h2>
<p><a href="/categories">Categories</a></p>
<p><a href="/users">Users</a></p>
<p><a href="/logout">Logout</a></p>
</body>
</html>

在我的SecurityConfiguration

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.web.DefaultRedirectStrategy;
import ru.otus.software_architect.eshop.handler.CustomLogoutSuccessHandler;

import javax.sql.DataSource;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Autowired
    private DataSource dataSource; // get by Spring

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                // Here, you are making the public directory on the classpath root available without authentication (e..g. for css files)
                .antMatchers("/public/**", "/registration.html").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login.html")
                .successHandler((request, response, authentication) -> new DefaultRedirectStrategy().sendRedirect(request, response, "/welcome"))
                .failureUrl("/login-error.html")
                .permitAll()
                .and()
                .logout()
                .logoutSuccessHandler(new CustomLogoutSuccessHandler())
                .permitAll();
    }

    // login by user from db
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication()
                .dataSource(dataSource)
                .passwordEncoder(NoOpPasswordEncoder.getInstance())
                .usersByUsernameQuery("SELECT username, password, active FROM usr WHERE username=?")
                .authoritiesByUsernameQuery("SELECT u.username, ur.role FROM usr u INNER JOIN user_roles ur ON u.id = ur.user_id WHERE u.username=?");
    }

我的处理程序:

public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler implements LogoutSuccessHandler {
    private static Logger logger = LogManager.getLogger(CustomLogoutSuccessHandler.class);

    @Override
    public void onLogoutSuccess(
            HttpServletRequest request,
            HttpServletResponse response,
            Authentication authentication)
            throws IOException, ServletException {
        logger.info("onLogoutSuccess:");
        // some custom logic here
        response.sendRedirect(request.getContextPath() + "/login.html");
    }
}

如您所见,它正好转到登录页面。

但是当我单击注销链接上的welcome.html时,方法onLogoutSuccess没有被调用,并且出现错误页面:

Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Sun Jan 26 18:21:53 EET 2020
There was an unexpected error (type=Not Found, status=404).
No message available

1 个答案:

答案 0 :(得分:1)

<a href="/logout">Logout</a>会将您重定向到"/logout",执行GET请求。
除非您在"/logout"处显示页面,否则您将收到404。

默认情况下,仅通过向POST发送"/logout"请求来触发注销。

由于您使用的是Thymeleaf,因此您可以改用类似的方法注销。

<form action="#" th:action="@{/logout}" method="post">
    <input type="submit" value="Logout" />
</form>
相关问题