Почему пользовательская форма входа в Spring не найдена, но другие страницы работают нормально?

#java #spring-boot #spring-mvc #spring-security

#java #spring-boot #spring-mvc #spring-безопасность

Вопрос:

Я пытаюсь добавить пользовательскую страницу входа в Sprint Security, но в итоге получается ошибка 404 «Страница не найдена». Я уже внедрил механизм входа в систему, и он работает для формы входа в систему Spring Security по умолчанию. Теперь я понятия не имею, что делать, чтобы заставить пользовательскую страницу входа работать.

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.3.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.krzychu</groupId>
    <artifactId>hairdresser</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>hairdresser</name>
    <description>Haidresser CRUD</description>

    <properties>
        <java.version>12</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</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-data-rest</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-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.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
 

SecurityConfig.java

 package com.krzychu.hairdresser.config;

import com.krzychu.hairdresser.services.MyUserDetailsService;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@EnableWebMvc
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyUserDetailsService userDetailsService;

    @Autowired
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .userDetailsService(userDetailsService)
                .passwordEncoder(bCryptPasswordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                    .antMatchers("/resources/**").permitAll()
                    .anyRequest().permitAll()
                    .and()
                .formLogin()
                    .loginPage("/login")
                    .permitAll()
                    .and()
                .logout()
                    .permitAll();
    }
}

 

login.html

 <html xmlns:th="https://www.thymeleaf.org">
<head th:include="layout :: head(title=~{::title},links=~{})">
    <title>Please Login</title>
</head>
<body th:include="layout :: body" th:with="content=~{::content}">
<div th:fragment="content">
    <form name="f" th:action="@{/login}" method="post">
        <fieldset>
            <legend>Please Login</legend>
            <div th:if="${param.error}" class="alert alert-error">
                Invalid username and password.
            </div>
            <div th:if="${param.logout}" class="alert alert-success">
                You have been logged out.
            </div>
            <label for="username">Username</label>
            <input type="text" id="username" name="username"/>
            <label for="password">Password</label>
            <input type="password" id="password" name="password"/>
            <div class="form-actions">
                <button type="submit" class="btn">Log in</button>
            </div>
        </fieldset>
    </form>
</div>
</body>
</html>
 

Структура папок

application.properties

 spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=${DB_URL}
spring.datasource.username=
spring.datasource.password=

spring.main.allow-bean-definition-overriding=true
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
 

Комментарии:

1. Можете ли вы поделиться всем своим классом конфигурации?

2. Конечно, только что отредактированный пост

Ответ №1:

Вы можете заменить EnableWebMvc на EnableWebSecurity следующим образом

 @EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
  // ...
}
 

Редактировать
Добавьте контроллер для входа в систему следующим образом

 @Controller
public class LoginController {
    @GetMapping("/login")
    public String index(HttpServletRequest request, Model model) {
        
        // ...
        
        return "login";
    }
}
 

В этом примере предполагается login.html , что в вашей templates папке есть файл

Редактировать 2
Если это еще не сделано, вы должны добавить a ViewResolver как a @Bean в свой класс конфигурации

 @Bean
public TemplateEngine templateEngine(ITemplateResolver templateResolver, SpringSecurityDialect sec) {
    TemplateEngine templateEngine = new TemplateEngine();
    templateEngine.setTemplateResolver(templateResolver);
    templateEngine.addDialect(sec);
    return templateEngine;
}
 

Добавьте эту зависимость

     <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>
 

Комментарии:

1. Это не помогло.

2. Возможно, вам необходимо предоставить дополнительный контент. Поделитесь своим LoginController

3. У меня нет LoginController. Я думал, что мне это не нужно, не так ли?

4. Именно поэтому была отображена страница входа по умолчанию. Конечно, для этого вам нужен контроллер

5. @dm_tr Ну, я уверен, но даже после добавления этой зависимости она все равно не работает

Ответ №2:

почему не дают возможности удалить теги, у которых есть th:include=»layout , просто чтобы проверить, что подключение элементов выполнено правильно, и отсутствует только определение макета??