本文介绍了无法通过自定义注销处理程序注销的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的 Spring Boot 应用程序中,我想添加注销链接.

In my spring boot app I want to add link to logout.

在模板welcome.html:

In template 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");
    }
}

正如你所看到的,它只是转发到登录页面.

as you can see it just forward to login page.

但是当我在注销链接上单击welcome.html 时,方法onLogoutSuccess 不会被调用并且我得到错误页面:

But when I click on welcome.html on logout link the method onLogoutSuccess is not call and I get error page:

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

推荐答案

Logout</a> 会将您重定向到 "/logout" 执行 GET 请求.
除非您在 "/logout" 处呈现页面,否则您将收到 404.

<a href="/logout">Logout</a> will redirect you to "/logout" performing a GET request.
Unless you have a page rendered at "/logout", you will receive a 404.

默认情况下,登出仅在向 "/logout" 发出 POST 请求时触发.

By default logout is only triggered with a POST request to "/logout".

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

Since you are using Thymeleaf, you could instead use something like this for logging out.

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

这篇关于无法通过自定义注销处理程序注销的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!