如何在spring安全中使用thymeleaf配置注销功能?



我是新来的,我只是想知道我在哪里出错在配置注销部分在春天,我做了一个日志表单表单耐心,但当我试图注销它提示404页。

这是我的源代码。

控制器

import lombok.AllArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/patient")
@AllArgsConstructor
public class PatientLoginPage {
@GetMapping("/login")
public String patientLoginPage(Model model) {
//        model.addAttribute("successRegistration", true);
return "PatientWebPages/PatientLoginPage";
}
@GetMapping("/login-error")
public String errorPatientLoginPage(Model model){
model.addAttribute("errorMessage", true);
return "PatientWebPages/PatientLoginPage";
}
@GetMapping("login-success")
public String successPatientLoginPage(Model model) {
model.addAttribute("successRegistration", true);
return "PatientWebPages/PatientLoginPage";
}
}
安全配置


import com.capstone.dentalclinic.demo.security.PasswordEncoder;
import com.capstone.dentalclinic.demo.services.patient.PatientServicesImpl;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
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.WebSecurityCustomizer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.server.authentication.logout.DelegatingServerLogoutHandler;
import org.springframework.security.web.server.authentication.logout.SecurityContextServerLogoutHandler;
import org.springframework.security.web.server.authentication.logout.WebSessionServerLogoutHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@Configuration
@EnableWebSecurity
@AllArgsConstructor
@Order(1)
public class PatientSecurityConfig {
private final PatientServicesImpl patientServicesImpl;
private final PasswordEncoder passwordEncoder;
@Bean
public DaoAuthenticationProvider daoAuthenticationProviderPatient() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setPasswordEncoder(passwordEncoder.bcryptPasswordEncoder());
provider.setUserDetailsService(patientServicesImpl);
return provider;
}
@Bean
public SecurityFilterChain securityFilterChainPatient (HttpSecurity http) throws  Exception{
http.authorizeRequests().antMatchers("/patient/login", "/patient/registration", "/Service",
"/patient/login-error", "/patient/login-success", "/forgot-password", "/new-password").permitAll();
http
.csrf().disable()
.authenticationProvider(daoAuthenticationProviderPatient())
.antMatcher("/patient/**")
.authorizeRequests().anyRequest().hasAnyAuthority("PATIENT")
.and()
.formLogin()
.loginPage("/patient/login")
.defaultSuccessUrl("/patient/dashboard", true)
.failureUrl("/patient/login-error")
.and()
.logout()
.logoutUrl("/logout").permitAll()
.logoutSuccessUrl("/patient/login")
//                .invalidateHttpSession(true)
//                            .logoutSuccessHandler(logoutSuccessHandler)
//                            .addLogoutHandler(logoutHandler)
.deleteCookies("JSESSIONID");
return http.build();
}
@Bean
public WebSecurityCustomizer webSecurityCustomizer1() {
return (web) -> web
.ignoring()
.antMatchers("/resources/**","/static/**", "/static/*", "/static/", "/css/**", "/assets/**",
"/javascript/**");
}
}

dashboar.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org/">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/png" sizes="32x32" href="/assets/administrator/new-resized-logo.png">
<link rel="shortcut icon" type="image/x-icon" sizes="16x16" href="/assets/administrator/new-resized-logo.png">
<link rel="manifest" href="/site.webmanifest">
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff">

<!--Bootstrap CDN -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
<!-- CSS Link -->
<link rel="stylesheet" th:href="@{/css/patients/PatientDashboard.css}">

<link rel="stylesheet" href="/admin-system/src/main/resources/static/css/patients/PatientDashboard.css">
</head>
<body>
<!-- Navbar -->
<nav class="navbar sticky-top navbar-expand-sm navbar-dark bg-danger opacity-100">
<div class="container-sm">
<a class="navbar-brand" href="/patient/dashboard">
<img th:src="@{/assets/patients/logo.png}" width="85" height="85" alt="Logo">
</a>

<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>  

<div class=" collapse navbar-collapse" id="navbarNavDropdown">
<ul class="navbar-nav ms-auto ">
<li class="nav-item">
<a class="nav-link shadow-text mx-2" aria-current="page" href="#profile">PROFILE</a>
</li>
<li class="nav-item">
<a class="nav-link shadow-text mx-2" href="#record">RECORDS</a>
</li>
<a class="button-logout shadow-text mx-3" th:href="@{/logout}">LOGOUT</a>
</ul>
</div>
</div>
</nav>
<!-- Navbar -->
<!-- Main dashboard -->

<div class="container-md mt-5 mb-5">
<div class="header">
<h1 class="text-center fw-bolder display-4 p-5">Welcome to<br>Patient Dashboard</h1>
</div>
</div>
<!-- Tables -->
<div class="container-md mt-5 w-auto" id="profile">
<table class="table table-borderless table-hover">
<thead class="thead-dark">
<tr>
<th class="text-center fw-bold h2" colspan="4" scope="col">Basic Information </th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-start fw-bolder w-25 fs-5" >First Name</td>
<td class="text-center w-25 fs-5" th:text="${data.firstName}"></td>
</tr>
<tr>
<td class="text-start fw-bolder w-25 fs-5">Middle Name</td>
<td class="text-center w-25 fs-5" th:text="${data.middleName}"></td>
</tr>
<tr>
<td class="text-start fw-bolder w-25 fs-5">Last Name</td>
<td class="text-center w-25 fs-5" th:text="${data.lastName}"></td>
</tr>
<tr>
<td class="text-start fw-bolder w-25 fs-5">Suffix</td>
<td class="text-center w-25 fs-5" th:text="${data.suffix}"></td>
</tr>
<tr>
<td class="text-start fw-bolder w-25 fs-5">Date of Birth</td>
<td class="text-center w-25 fs-5" th:text="${data.birthDate}"></td>
</tr>
<tr>
<td class="text-start fw-bolder w-25 fs-5">Gender</td>
<td class="text-center w-25 fs-5" th:text="${data.gender}"></td>
</tr>
<tr>
<td class="text-start fw-bolder w-25 fs-5">Civil Status</td>
<td class="text-center w-25 fs-5" th:text="${data.civilStatus}"></td>
</tr>
<tr>
<td class="text-start fw-bolder w-25 fs-5">Physical Disability or Condition</td>
<td class="text-center w-25 fs-5" th:text="${data.physicalDisability}"></td>
</tr>
</tbody>
</table>
</div>
<div class="container-md mt-2 w-auto">
<table class="table table-borderless table-hover">
<thead class="thead-dark">
<tr>
<th class="text-center fw-bold h2" colspan="4" scope="col">Contact Information</th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-start fw-bolder w-25 fs-5">Email Address</td>
<td class="text-center w-25 fs-5" th:text="${data.emailAddress}"></td>
</tr>
<tr>
<td class="text-start fw-bolder w-25 fs-5">Complete Address</td>
<td class="text-center w-25 fs-5" th:text="${data.homeAddress}"></td>
</tr>
<tr>
<td class="text-start fw-bolder w-25 fs-5">Phone Number</td>
<td class="text-center w-25 fs-5" th:text="${data.contactNumber}"></td>
</tr>
</tbody>
</table>
</div>
<!-- Tables -->
</body>
</html>

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.capstone.dentalclinic</groupId>
<artifactId>admin</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>admin</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency> -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>

我错过了什么吗?请给我点化一下。

我试着看了很多教程,但仍然可以解决它。

您的应用程序正在寻找"注销";你没有的页面,因此404。为什么?因为在你的securityFilterChainPatient中你写了:.logoutUrl("/logout")

删除.logoutUrl("/logout").permitAll()

应用程序将应用标准的注销过程,然后转到"/patient/login">

change:

.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/patient/login?logout")
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID")
.permitAll();

您也可以尝试在配置文件中删除此部分。它会自动重定向到登录页面

.logout()
.logoutUrl("/logout").permitAll()
.logoutSuccessUrl("/patient/login")
//                .invalidateHttpSession(true)
//                            .logoutSuccessHandler(logoutSuccessHandler)
//                            .addLogoutHandler(logoutHandler)
.deleteCookies("JSESSIONID");```