簡體   English   中英

在 spring 安全 6. 新實現中擁有自己的登錄頁面

[英]Own login page in spring security 6. new implementation

我正在嘗試將我的項目遷移到 spring 安全 6。我不能再使用“擴展 WebSecurityConfigurerAdapter”。 在那種情況下,我不知道如何重建我的代碼以使用我自己的登錄頁面。 有舊代碼:

package main.config;

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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
            .withUser("admin").password(passwordEncoder().encode("admin")).roles("ADMIN", "EMPLOYEE")
            .and()
            .withUser("employee").password(passwordEncoder().encode("employee")).roles("EMPLOYEE")
            .and()
            .withUser("client").password(passwordEncoder().encode("client")).roles("CLIENT");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/", "/login")
                .permitAll()
            .and()
                .formLogin()
                .loginPage("/login")
                .loginProcessingUrl("/checkUserAccount")
                .defaultSuccessUrl("/")
                .permitAll()
            .and()
                .logout()
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                .logoutSuccessUrl("/")
                .invalidateHttpSession(true)
                .permitAll();
    }
    
}

所以我在文檔中看到我可以用 SecurityFilterChain 方法替換它。 很長一段時間后我的代碼如下所示:

package main.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;


@Configuration
@EnableWebSecurity
public class SecurityConfiguration {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }

    @Bean
    public UserDetailsService users() {
        UserDetails admin = User.withUsername("admin")
            .password(passwordEncoder().encode("admin"))
            .roles("ADMIN", "EMPLOYEE").build();
        UserDetails employee = User.withUsername("employee")
            .password(passwordEncoder().encode("employee"))
            .roles("EMPLOYEE").build();
        UserDetails client = User.withUsername("client")
            .password(passwordEncoder().encode("client"))
            .roles("CLIENT").build();
        return new InMemoryUserDetailsManager(admin, employee, client);
    }
    
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests() 
        .requestMatchers("/", "/login")
        .permitAll()
        .and()
            .formLogin()
            .loginPage("/login")
            .loginProcessingUrl("/checkUserAccount")
            .defaultSuccessUrl("/")
            .permitAll()
        .and()
            .logout()
            .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
            .logoutSuccessUrl("/")
            .invalidateHttpSession(true)
            .permitAll();
        return http.build();
    }


}

但遺憾的是它被拋出:

> 
SEVERE: Exception sending context initialized event to listener instance of class [org.springframework.web.context.ContextLoaderListener]
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration': Unsatisfied dependency expressed through method 'setFilterChains' parameter 0: Error creating bean with name 'filterChain' defined in main.config.SecurityConfiguration: Failed to instantiate [org.springframework.security.web.SecurityFilterChain]: Factory method 'filterChain' threw exception with message: No bean named 'A Bean named mvcHandlerMappingIntrospector of type org.springframework.web.servlet.handler.HandlerMappingIntrospector is required to use MvcRequestMatcher. Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext.' available
    

我是新手,謝謝幫助。

編輯:

還有 SecurityInitializer:

 package main.config;


import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;

public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {

}

這是我的登錄名。html:

    <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
<meta charset="UTF-8">
<title>Home page</title>
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>

<link rel="stylesheet" href="http://use.fontawesome.com/releases/v5.3.1/css/all.css">
<link rel="stylesheet" type="text/css" href="resources/css/login.css">
</head>
<body>
    <div class="container">
        <div class="d-flex justify-content-center h-100">
            <div class="card">
                <div class="card-header">
                    <h2>Sign In</h2>
                </div>
                <div class="card-body">
                    <form action="#" th:action="@{/checkUserAccount}" method="post">
                        <div th:if="${param.error}" class="alert alert-login">
                            Invalid username and password.
                        </div>
                        
                        <div class="input-group form-group">
                            <div class="input-group-prepend">
                                <span class="input-group-text"><i class="fas fa-user"></i></span>
                            </div>
                            <input type="text" class="form-control" name="username" placeholder="Login">
                        </div>
                        <div class="input-group form-group">
                            <div class="input-group-prepend">
                                <span class="input-group-text"><i class="fas fa-key"></i></span>
                            </div>
                            <input type="password" class="form-control" name="password" placeholder="Password">
                        </div>
                        <div class="form-group">
                            <input type="submit" value="Login" class="btn login-button">
                            <a th:href="@{/}" class="btn btn-warning float-right">Back</a>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</body>
</html>

Edit2:沒有 SecurityFilterChain 它正在工作,但顯然它沒有指向我自己的登錄。 當我現在運行它時,我可以看到:

創建名稱為“org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration”的 bean 時出錯:通過方法“setFilterChains”參數 0 表示的不滿足依賴關系:創建名稱為“filterChain”的 bean 時在 main.config.SecurityConfiguration 中定義時出錯:無法實例化 [org.springframework.security.web.SecurityFilterChain]:工廠方法 'filterChain' 拋出異常並顯示消息:沒有名為 'A Bean named mvcHandlerMappingIntrospector of type org.springframework.web.servlet.handler.HandlerMappingIntrospector 需要使用MvcRequestMatcher。 請確保 Spring Security 和 Spring MVC 在共享的 ApplicationContext 中配置。 可用的

我也有這些依賴項:

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
    <version>6.0.1</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>6.0.1</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>6.0.3</version>
</dependency>

不使用AuthenticationManagerBuilder ,而是創建一個UserDetailsService bean。

@Bean
public UserDetailsService users() {
    UserDetails admin = User.withUsername("admin")
        .password(passwordEncoder().encode("admin"))
        .roles("ADMIN", "EMPLOYEE").build();
    UserDetails employee = User.withUsername("employee")
        .password(passwordEncoder().encode("employee"))
        .roles("EMPLOYEE").build();
    UserDetails client = User.withUsername("client")
        .password(passwordEncoder().encode("client"))
        .roles("CLIENT").build();
    return new InMemoryUserDetailsManager(admin, employee, client);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM