Usually, the log out button looks like this
<form th:action="@{/logout}" method="post">
<input type="submit" value="Logout" />
</form>
Logout URL:
By default, the logout url is /logout, you can customized by this way.
WebSecurityConfig.java
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/login_error_handler").permitAll()
.anyRequest().authenticated()
.and()
.logout()
.logoutUrl("/logout_my");
;
}
templates/logout_my.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
Logout
</body>
</html>
templates/home.html
<!DOCTYPE html>
<html xmlns:th="http:/www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
Home (protected)
<form th:action="@{/logout_my}" method="post">
<input type="submit" value="Logout" />
</form>
</body>
</html>
WebMVCConfig.java
@Configuration
public class WebMVCConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/home").setViewName("home");
// logout
registry.addViewController("/logout_my").setViewName("logout_my");
}
}
The original /logout endpoint will be unattached. If you visit it, it will have error (whitelabel page or direct you to the customized error page)
Logout successful page
Default is login page
.logoutSuccessUrl("/logout_success")
The complete the codes are here for Form Authentication
Dependencies
WebSecurityConfig.java
package com.example.demo10;
/**
* Created by TUTEHUB on 2022/1/25 3:23 PM.
* Copyright © 2022 TUTEHUB. All rights reserved.
* ------------------------
* Non-disclosure Terms
* -------------------------
* These codes are TUTEHUB's property, as the developer, such as employee, contractor, and intern, working for TUTEHUB cannot disclose, spread, copy, preserve, sell, and do other activities without the consent of TUTEHUB.
* Developer dph agrees with above terms.
* Technique Support: jobyme88.com
* Contact: noreply@fengcaoculture.com
*/
import org.springframework.context.annotation.Bean;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import static org.springframework.security.config.Customizer.withDefaults;
/**
* @description
*/
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/login_error_handler", "/logout_success", "/logout_success_handler").permitAll()
.anyRequest().authenticated()
/**
* Login
*/
.and()
// use the login page
.formLogin()
// use customized login page
// can only use this name
.loginPage("/login")
// everyone can visit the /login
.permitAll()
/**
* Level 1
*/
// if login successfully
// for unsecured endpoint
// will be directed here
// the endpoint is mapped in WebMVCConfig
.defaultSuccessUrl("/login_success")
// if login failed
// replace default /login?error
// the endpoint is mapped in WebMVCConfig
.failureUrl("/login_error")
/**
* Level 2
*/
// if login successfully
// execute some extra code
// the endpoint is mapped in @Controller
// will override .defaultSuccessUrl
.successForwardUrl("/login_success_forward")
// if login failed
// execute some extra code
// the endpoint is mapped in @Controller
// will override .failureUrl
.failureForwardUrl("/login_error_forward")
/**
* Level 3
*/
.successHandler(new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
System.out.println("[shark] Logged user: " + authentication.getName());
response.sendRedirect("/login_success_handler");
}
})
.failureHandler(new AuthenticationFailureHandler() {
@Override
public void onAuthenticationFailure(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
System.out.println("[shark] Login failed");
System.out.println(exception);
// needs to open visit
response.sendRedirect("/login_error_handler");
}
})
/**
* Logout
*/
.and()
// open the /logout page
// GET /logout
// otherwise you will see error when you type /logout in the browser
.logout()
// By default, the logout endpoint is /logout
// customized this endpoint
.logoutUrl("/logout_my")
// Default is login page
// needs to be opened, otherwise you need to login
/**
* Level 1
*/
.logoutSuccessUrl("/logout_success")
/**
* Level 2
*/
.logoutSuccessHandler(new LogoutSuccessHandler() {
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication)
throws IOException, ServletException {
System.out.println("[shark] This user logged out: " + authentication.getName());
response.sendRedirect("/logout_success_handler");
}
})
;
;
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.passwordEncoder(passwordEncoder())
.withUser("user")
.password(passwordEncoder().encode("user"))
.roles("USER");
}
}
WebMVCConfig.java
package com.example.demo10;/**
* Created by TUTEHUB on 2022/2/5 6:56 PM.
* Copyright © 2022 TUTEHUB. All rights reserved.
* ------------------------
* Non-disclosure Terms
* -------------------------
* These codes are TUTEHUB's property, as the developer, such as employee, contractor, and intern, working for TUTEHUB cannot disclose, spread, copy, preserve, sell, and do other activities without the consent of TUTEHUB.
* Developer dph agrees with above terms.
* Technique Support: jobyme88.com
* Contact: noreply@fengcaoculture.com
*/
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @description
*/
@Configuration
public class WebMVCConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/home").setViewName("home");
// login
registry.addViewController("/login").setViewName("login");
registry.addViewController("/login_success").setViewName("login_success");
registry.addViewController("/login_error").setViewName("login_error");
registry.addViewController("/login_success_handler").setViewName("login_success_handler");
registry.addViewController("/login_error_handler").setViewName("login_error_handler");
// logout
registry.addViewController("/logout_my").setViewName("logout_my");
registry.addViewController("/logout_success").setViewName("logout_success");
registry.addViewController("/logout_success_handler").setViewName("logout_success_handler");
}
}
WebController.java
package com.example.demo10;/**
* Created by TUTEHUB on 2022/2/6 10:01 AM.
* Copyright © 2022 TUTEHUB. All rights reserved.
* ------------------------
* Non-disclosure Terms
* -------------------------
* These codes are TUTEHUB's property, as the developer, such as employee, contractor, and intern, working for TUTEHUB cannot disclose, spread, copy, preserve, sell, and do other activities without the consent of TUTEHUB.
* Developer dph agrees with above terms.
* Technique Support: jobyme88.com
* Contact: noreply@fengcaoculture.com
*/
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
/**
* @description
*/
@Controller
public class WebController {
@PostMapping("/login_success_forward")
public String loginSuccessHandler() {
System.out.println("[shark] Logging user login success...");
return "login_success_forward";
}
@PostMapping("/login_error_forward")
public String loginFailureHandler() {
System.out.println("[shark] Login failure handler....");
return "login_error_forward";
}
}
templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
Index (not protected)
</body>
</html>
templates/home.html
<!DOCTYPE html>
<html xmlns:th="http:/www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
Home (protected)
<form th:action="@{/logout_my}" method="post">
<input type="submit" value="Logout" />
</form>
</body>
</html>
templates/error.html
<!DOCTYPE html>
<html>
<head>
<title>Error occurred</title>
</head>
<body>
<h1>Error occurred</h1>
<p>
An error has occurred. Please contact the administrator; - template generic
</p>
</body>
</html>
templates/login.html
<!DOCTYPE html>
<html xmlns:th="http:/www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Login - Company ABC</title>
</head>
<body>
<div>
<form th:action="@{/login}" method="post" style="max-width: 400px; margin: 0 auto;">
<p>
Username: <input type="text" name="username" required />
</p>
<p>
Password: <input type="password" name="password" required />
</p>
<p>
<input type="submit" value="Login" />
</p>
</form>
</div>
</body>
</html>
templates/login_success.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
Login Successfully
</body>
</html>
templates/login_success_forward.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
Login Successfully Forward
</body>
</html>
templates/login_success_handler.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
Login Successfully Handler
</body>
</html>
templates/login_error.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
Oops,you log in wrongly.
</body>
</html>
templates/login_error_forward.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
Login Error Forward
</body>
</html>
templates/login_error_handler.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
Login Error Handler
</body>
</html>
templates/logout_my.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
Logout
</body>
</html>
templates/logout_success.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
Logout successfully
</body>
</html>
templates/logout_success_handler.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
Logout successfully handler
</body>
</html>
The complete github is https://github.com/sharkdeng/spring-login-logout