Spring Security多登录页面示例

这篇具有很好参考价值的文章主要介绍了Spring Security多登录页面示例。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在 Web 应用程序开发中,有两个单独的模块是很常见的 - 一个用于管理员用户,一个用于普通用户。每个模块都有一个单独的登录页面,并且可以与相同或不同的身份验证源相关联。换句话说,应用程序为不同类型的用户提供了多个登录页面:管理员和用户,或管理员和客户。在这篇 Spring Boot 文章中,我想与您分享如何使用 Spring Security 编写此类身份验证代码。在详细信息中,您将了解:

  • 如何为具有相同身份验证源的管理员用户和普通用户实现登录页面
  • 如何为具有不同身份验证源的管理员和客户实现登录页面

在这两种情况下,我还展示了不同 Spring Boot 和 Spring Security 版本的代码示例,即 Spring Boot 版本 2.7.0 及更早版本:Spring Boot 2.7.0+ 附带 Spring Security 5.7.1+,它不推荐使用WebSecurityConfigurerAdapter和仍然支持它的旧版本。请注意,为了简单起见,我在下面的代码示例中使用了 H2 内存中数据库和纯文本密码。实际上,您可以轻松地切换到物理数据库,例如MySQL。

 

1. 设置项目的依赖关系

如果使用 Maven,请确保为项目包含以下依赖项:这意味着我们使用 Spring Web、Spring Data JPA、Spring Security、Thymeleaf、Thymeleaf Extras for Spring Security 和 H2 数据库。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</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.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

2. 使用相同的身份验证提供程序实现多个登录页面

在此方案中,我们将对管理员登录页面和用户登录页面进行编码 - 两者都共享相同的身份验证源(用户凭据存储在单个表中)。角色名称用于区分管理员用户 (ADMIN) 或普通用户 (USER)。因此,按如下方式定义角色枚举类型:并按如下方式对用户实体类进行编码:

1
2
3
package net.codejava;
 
public enum Role { ADMIN, USER }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package net.codejava;
 
import javax.persistence.*;
 
@Entity
@Table(name = "users")
public class User {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
     
    @Column(nullable = false, unique = true, length = 40)  
    private String email;
     
    @Column(nullable = false, unique = true, length = 10)
    private String password;
     
    @Enumerated(EnumType.STRING)
    private Role role;
 
    public User() {}
     
    public User(String email, String password, Role role) {
        this.email = email;
        this.password = password;
        this.role = role;
    }
 
    // getters and setters are not shown for brevity   
     
}
 

接下来,为数据访问层编写UserRepository接口代码:我们需要一些示例数据用于测试目的。因此,编写以下类,该类将在应用程序启动时初始化数据库:您会看到,它将 4 个用户保存到数据库中:其中两个具有角色 ADMIN,两个具有角色 USER - 密码为纯文本。要实现身份验证,请创建一个类型为UserDetails的类,如下所示:并按如下方式编写UserDetailsService类型的类:

1
2
3
4
5
6
7
8
9
package net.codejava;
 
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
 
@Repository
public interface UserRepository extends CrudRepository<User, Integer> {
    public User findByEmail(String email); 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package net.codejava;
 
import java.util.List;
 
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
@Configuration
public class DatabaseLoader {
 
    private UserRepository repo;
     
    public DatabaseLoader(UserRepository repo) {
        this.repo = repo;
    }
 
    @Bean
    public CommandLineRunner initializeDatabase() {
        return args -> {
            User user1 = new User("david@gmail.com""david123", Role.ADMIN);
            User user2 = new User("john@yahoo.com""john2020", Role.ADMIN);
            User user3 = new User("nam@codejava.net""nam2022", Role.USER);
            User user4 = new User("ravi@gmail.com""ravi2121", Role.USER);
             
            repo.saveAll(List.of(user1, user2, user3, user4));
             
            System.out.println("Database initialized");
        };
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package net.codejava;
 
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
 
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
 
public class CustomUserDetails implements UserDetails {
    private User user;
     
    public CustomUserDetails(User user) {
        this.user = user;
    }
 
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
         
        authorities.add(new SimpleGrantedAuthority(user.getRole().toString()));
         
        return authorities;
    }
 
    @Override
    public String getPassword() {
        return user.getPassword();
    }
 
    @Override
    public String getUsername() {
        return user.getEmail();
    }
 
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
 
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }
 
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
 
    @Override
    public boolean isEnabled() {
        return true;
    }
 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package net.codejava;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.*s;
 
public class CustomUserDetailsService implements UserDetailsService {
    @Autowired private UserRepository repo;
 
    @Override
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
        User user = repo.findByEmail(email);
        if (user == null) {
            throw new UsernameNotFoundException("No user found with the given email");
        }
         
        return new CustomUserDetails(user);
    }
 
}

 

为管理员用户实现登录页面

现在,创建一个 Spring 安全配置类,用于为管理员用户配置身份验证提供程序和登录页面。代码如下:你看,这个安全配置类扩展了WebSecurityConfigurerAdapter类,这意味着它应该与低于 2.7.0 的 Spring 引导版本和低于 5.7.1 的 Spring 安全版本一起使用。例如,Spring Boot 版本 2.3.4:让我解释一下这个配置类中的代码:它声明了两个 Spring bean,类型分别为UserDetailsServicePasswordEncoder,身份验证提供程序将使用它们来对用户进行身份验证。以下语句允许对应用程序主页的公共访问(所有人):因为在主页上,我们显示如下所示的登录选项:下面是主页的代码(src/main/resources/templates/index.html):以下语句将 Spring 安全性过滤器链应用于路径以 /admin/ 开头的所有请求:这意味着我们应该将所有管理页面放在 /admin/ path 下。下一条语句要求对所有请求进行身份验证 - 用户必须具有角色 ADMIN 才能访问管理页面:要了解配置登录页面的其余代码,请参阅本文。供您参考,以下是管理员登录页面 (templates/admin/admin_login.html) 的代码:管理员登录页面如下所示:如果您输入管理员用户的正确凭据(请参阅DatabaseLoader类),您将看到管理员主页:然后单击注销按钮注销。管理员主页 (templates/admin/admin_home.html) 的代码如下:如果您使用的是 Spring Boot 版本 >= 2.70 或 Spring Security 版本 >= 5.7.1,则需要对AdminSecurityConfig类使用以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package net.codejava.admin;
 
import org.springframework.context.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.*;
 
import net.codejava.CustomUserDetailsService;
 
@Configuration
@Order(1)
public class AdminSecurityConfig extends WebSecurityConfigurerAdapter {
     
    @Bean
    public UserDetailsService userDetailsService() {
        return new CustomUserDetailsService();
    }
     
    @Bean
    public PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }
 
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/").permitAll();
         
        http.antMatcher("/admin/**")
            .authorizeRequests().anyRequest().hasAuthority("ADMIN")
            .and()
            .formLogin()
                .loginPage("/admin/login")
                .usernameParameter("email")
                .loginProcessingUrl("/admin/login")
                .defaultSuccessUrl("/admin/home")
                .permitAll()
            .and()
            .logout()
                .logoutUrl("/admin/logout")
                .logoutSuccessUrl("/");
    }  
     
     
}
1
2
3
4
5
6
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.4.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
1
http.authorizeRequests().antMatchers("/").permitAll();

Spring Security多登录页面示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Spring Multiple Login Pages Demo</title>
</head>
<body>
    <div align="center">
        <h2>Welcome to CodeJava.net</h2>
        <h4><a th:href="/@{/admin/login}">Admin Login</a></h4>
        <p/>
        <h4><a th:href="/@{/user/login}">User Login</a></h4>
    </div>
</body>
</html>
1
http.antMatcher("/admin/**")
1
.authorizeRequests().anyRequest().hasAuthority("ADMIN")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Admin Login - CodeJava.net</title>
</head>
<body>
<form th:action="@{/admin/login}" method="post" style="max-width: 400px; margin: 0 auto;">
    <h2>Admin Login - CodeJava.net</h2>
     
    <div th:if="${param.error}">
        <h4 style="color: red">[[${session.SPRING_SECURITY_LAST_EXCEPTION.message}]]</h4>
    </div>
             
    <table>
        <tr>
            <td>E-mail: </td>
            <td><input type="email" name="email" required /></td>
        </tr>
        <tr>
            <td>Password: </td>
            <td><input type="password" name="password" required /></td>
        </tr>
        <tr><td>&nbsp;</td></tr>
        <tr>
            <td colspan="2" align="center"><input type="submit" value="Login" /></td>
        </tr>
    </table>
</form>
</body>
</html>

Spring Security多登录页面示例

Spring Security多登录页面示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Welcome to CodeJava.net Admin Control Panel</title>
</head>
<body>
    <div align="center">
        <h2>Welcome to CodeJava.net Admin Control Panel</h2>
        <p>Your user name is: <b>[[${#request.userPrincipal.principal.username}]]</b></p>
        <form th:action="@{/admin/logout}" method="post">
            <input type="submit" value="Logout" />
        </form>      
    </div>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package net.codejava.admin;
 
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.*;
import org.springframework.security.web.SecurityFilterChain;
 
import net.codejava.CustomUserDetailsService;
 
@Configuration
@Order(1)
public class AdminSecurityConfig {
     
    @Bean
    public UserDetailsService userDetailsService() {
        return new CustomUserDetailsService();
    }
     
    @Bean
    public PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }
 
    @Bean
    public SecurityFilterChain filterChain1(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/").permitAll();
         
        http.antMatcher("/admin/**")
            .authorizeRequests().anyRequest().hasAuthority("ADMIN")
            .and()
            .formLogin()
                .loginPage("/admin/login")
                .usernameParameter("email")
                .loginProcessingUrl("/admin/login")
                .defaultSuccessUrl("/admin/home")
                .permitAll()
            .and()
            .logout()
                .logoutUrl("/admin/logout")
                .logoutSuccessUrl("/");
         
        return http.build();
    }     
}

  

实现普通用户的登录页面

与管理员登录模块类似,我们需要为用户登录模块创建第二个安全配置类,如下所示(下面是 Spring Boot 版本 < 2.7.0 或 Spring Security < 5.7.1 的代码):如果您注意到,我们指定 AdminSecurityConfig 类的过滤顺序为 @Order(1),UserSecurityConfig类为 @Order(2).这意味着将有两个不同的 Spring 安全过滤器:一个用于管理模块,一个用于用户模块。两个筛选器不能具有相同的顺序。供您参考,以下是用户登录页面 (templates/user/user_login.html) 的代码:用户登录页面如以下屏幕截图所示:如果您输入普通用户的正确凭据,您将看到出现用户主页:供您参考,以下是用户主页 (templates/user/user_home.html) 的代码:为了使所有这些工作, 编写控制器类,如下所示:另外,如果您使用 Spring Boot 版本 >= 2.7.0 或 Spring Security >= 5.7.1,则需要按如下方式对UserSecurityConfig类进行编码:请注意,在此方法中,两个 Spring 安全性配置类共享相同的身份验证提供程序和密码编码器。如果您尝试在用户登录页面中使用管理员凭据,您将收到 403 错误,反之亦然。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package net.codejava.user;
 
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
 
@Configuration
@Order(2)
public class UserSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
         
        http.antMatcher("/user/**")
            .authorizeRequests().anyRequest().hasAuthority("USER")
            .and()
            .formLogin()
                .loginPage("/user/login")
                .usernameParameter("email")
                .loginProcessingUrl("/user/login")
                .defaultSuccessUrl("/user/home")
                .permitAll()
            .and()
            .logout()
                .logoutUrl("/user/logout")
                .logoutSuccessUrl("/");    
    }  
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>User Login - CodeJava.net</title>
</head>
<body>
<form th:action="@{/user/login}" method="post" style="max-width: 400px; margin: 0 auto;">
    <h2>User Login - CodeJava.net</h2>
     
    <div th:if="${param.error}">
        <h4 style="color: red">[[${session.SPRING_SECURITY_LAST_EXCEPTION.message}]]</h4>
    </div>
         
    <table>
        <tr>
            <td>E-mail: </td>
            <td><input type="email" name="email" required /></td>
        </tr>
        <tr>
            <td>Password: </td>
            <td><input type="password" name="password" required /></td>
        </tr>
        <tr><td>&nbsp;</td></tr>
        <tr>
            <td colspan="2" align="center"><input type="submit" value="Login" /></td>
        </tr>
    </table>
</form>
</body>
</html>

Spring Security多登录页面示例

Spring Security多登录页面示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Welcome to CodeJava.net</title>
</head>
<body>
    <div align="center">
        <h2>Welcome to CodeJava.net User Home</h2>
        <p>Your user name is: <b>[[${#request.userPrincipal.principal.username}]]</b></p>
        <form th:action="@{/user/logout}" method="post">
            <input type="submit" value="Logout" />
        </form>      
    </div>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package net.codejava;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
 
@Controller
public class MainController {
 
    @GetMapping("")
    public String viewHomePage() {
        return "index";
    }
     
    @GetMapping("/admin/login")
    public String viewAdminLoginPage() {
        return "admin/admin_login";
    }
     
    @GetMapping("/admin/home")
    public String viewAdminHomePage() {
        return "admin/admin_home";
    }
     
    @GetMapping("/user/login")
    public String viewUserLoginPage() {
        return "user/user_login";
    }
     
    @GetMapping("/user/home")
    public String viewUserHomePage() {
        return "user/user_home";
    }  
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package net.codejava.user;
 
import org.springframework.context.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
 
@Configuration
@Order(2)
public class UserSecurityConfig {
    @Bean
    public SecurityFilterChain filterChain2(HttpSecurity http) throws Exception {
         
        http.antMatcher("/user/**")
            .authorizeRequests().anyRequest().hasAuthority("USER")
            .and()
            .formLogin()
                .loginPage("/user/login")
                .usernameParameter("email")
                .loginProcessingUrl("/user/login")
                .defaultSuccessUrl("/user/home")
                .permitAll()
            .and()
            .logout()
                .logoutUrl("/user/logout")
                .logoutSuccessUrl("/");
         
        return http.build();
    }  
}

3. 使用不同的身份验证提供程序实现多个登录页面

在此方案中,我们将实现管理员登录页面和客户登录页面 - 每个页面都使用自己的身份验证源。这意味着管理员身份验证使用用户表中的凭据,客户身份验证使用客户表中的凭据。首先,更新用户实体类(删除角色枚举),如下所示:然后更新CustomUserDetails类的getAuthority() 方法:CustomUserDetailsService类的代码保持不变。并添加表示客户用户的 Customer 实体类:并按如下所示创建CustomerRepository接口:对于示例数据库,对DatabaseLoader类进行编码,如下所示:您会看到,此代码保留了两个管理员用户和两个具有纯文本密码的客户。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package net.codejava.admin;
 
import javax.persistence.*;
 
@Entity
@Table(name = "users")
public class User {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
     
    @Column(nullable = false, unique = true, length = 40)  
    private String email;
     
    @Column(nullable = false, length = 10)
    private String password;
 
    public User() {}
     
    public User(String email, String password) {
        this.email = email;
        this.password = password;
    }
     
    // getters and setters are not shown for brevity
}
1
2
3
4
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
    return null;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package net.codejava.customer;
 
import javax.persistence.*;
 
@Entity
@Table(name = "customers")
public class Customer {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
     
    @Column(nullable = false, unique = true, length = 40)  
    private String email;
     
    @Column(nullable = false, length = 10)
    private String password;
     
    @Column(nullable = false, length = 30)
    private String fullName;
 
    public Customer() { }
     
    public Customer(String email, String password, String fullName) {
        this.email = email;
        this.password = password;
        this.fullName = fullName;
    }
 
    // getters and setters are not shown for brevity   
}
1
2
3
4
5
6
7
8
9
package net.codejava.customer;
 
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
 
@Repository
public interface CustomerRepository extends CrudRepository<Customer, Integer> {
    public Customer findByEmail(String email); 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package net.codejava;
 
import java.util.List;
 
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.*;
 
import net.codejava.admin.*;
import net.codejava.customer.*;
 
@Configuration
public class DatabaseLoader {
 
    private UserRepository userRepo;
    private CustomerRepository customerRepo;
 
    public DatabaseLoader(UserRepository userRepo, CustomerRepository customerRepo) {
        this.userRepo = userRepo;
        this.customerRepo = customerRepo;
    }
 
    @Bean
    public CommandLineRunner initializeDatabase() {
        return args -> {
            User user1 = new User("david@gmail.com""david123");
            User user2 = new User("john@yahoo.com""john2020");
             
            userRepo.saveAll(List.of(user1, user2));
             
            Customer customer1 = new Customer("alex@gmail.com""alex123""Alex Stevenson");
            Customer customer2 = new Customer("peter@mail.ru""peter246""Peter Senkovski");
             
            customerRepo.saveAll(List.of(customer1, customer2));
             
            System.out.println("Database initialized");
        };
    }
}

 

为管理员用户实现登录页面

要实现管理模块的身份验证,请按如下方式对AdminSecurityConfig类进行编码(对于 Spring 引导版本 >= 2.7.0 或 Spring Security >= 5.7.1):请注意,HTML 页面的代码与上一节中所示的代码相同。如果您使用 Spring 引导版本 < 2.7.0 或 Spring 安全< 5.7.1,请使用以下代码作为安全配置类:如您所见,我们定义了一个身份验证提供程序,以便为管理员登录提供单独的身份验证源。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package net.codejava.admin;
 
import org.springframework.context.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.*;
import org.springframework.security.web.SecurityFilterChain;
 
@Configuration
@Order(1)
public class AdminSecurityConfig {
 
    @Bean
    public UserDetailsService userDetailsService() {
        return new CustomUserDetailsService();
    }
 
    @Bean
    public PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }
 
    @Bean
    public DaoAuthenticationProvider authenticationProvider1() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(userDetailsService());
        authProvider.setPasswordEncoder(passwordEncoder());
 
        return authProvider;
    }
 
    @Bean
    public SecurityFilterChain filterChain1(HttpSecurity http) throws Exception {
        http.authenticationProvider(authenticationProvider1());
 
        http.authorizeRequests().antMatchers("/").permitAll();
 
        http.antMatcher("/admin/**")
            .authorizeRequests().anyRequest().authenticated()
            .and()
            .formLogin()
                .loginPage("/admin/login")
                    .usernameParameter("email")
                    .loginProcessingUrl("/admin/login")
                    .defaultSuccessUrl("/admin/home")
                .permitAll()
            .and()
            .logout()
                .logoutUrl("/admin/logout")
                .logoutSuccessUrl("/");
 
        return http.build();
    }
 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package net.codejava.admin;
 
import org.springframework.context.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.*;
 
@Configuration
@Order(1)
public class AdminSecurityConfig extends WebSecurityConfigurerAdapter {
 
    @Bean
    public UserDetailsService userDetailsService() {
        return new CustomUserDetailsService();
    }
 
    @Bean
    public PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }
 
    @Bean
    public DaoAuthenticationProvider authenticationProvider1() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(userDetailsService());
        authProvider.setPasswordEncoder(passwordEncoder());
 
        return authProvider;
    }
 
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authenticationProvider(authenticationProvider1());
 
        http.authorizeRequests().antMatchers("/").permitAll();
 
        http.antMatcher("/admin/**")
            .authorizeRequests().anyRequest().authenticated()
            .and()
            .formLogin()
                .loginPage("/admin/login")
                    .usernameParameter("email")
                    .loginProcessingUrl("/admin/login")
                    .defaultSuccessUrl("/admin/home")
                    .permitAll()
                .and()
                    .logout()
                        .logoutUrl("/admin/logout")
                        .logoutSuccessUrl("/");
 
    }
 
}

 

为客户实现登录页面

与管理模块类似,对 CustomerUserDetails类进行编码,如下所示:以及CustomerUserDetailsService类的代码:下面是客户身份验证模块的安全配置类的代码,适用于 Spring 引导版本 >= 2.70 或 Spring 安全 >= 5.7.1:如果您使用 Spring 引导版本 < 2.70 或 Spring 安全版本 < 5.7.1, 对CustomerSecurityConfig类使用以下代码:如您所见,我们定义了不同的UserDetailsServicePasswordEncoderAuthenticationProvider,以便为客户登录模块使用单独的身份验证源。并且视图页面和控制器类的代码与前面的代码类似。这是一些代码示例,向您展示如何使用 Spring 安全性实现多个登录页面,涵盖了两种场景:管理员用户和普通用户共享同一个身份验证提供程序;以及使用不同身份验证源的管理员用户和客户用户。希望这篇文章对您有所帮助。感谢您 reading.PS:要了解编码的实际效果,我建议您观看以下视频:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package net.codejava.customer;
 
import java.util.Collection;
 
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
 
public class CustomerUserDetails implements UserDetails {
    private Customer customer;
 
    public CustomerUserDetails(Customer customer) {
        this.customer = customer;
    }
 
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }
 
    @Override
    public String getPassword() {
        return customer.getPassword();
    }
 
    @Override
    public String getUsername() {
        return customer.getEmail();
    }
 
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
 
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }
 
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
 
    @Override
    public boolean isEnabled() {
        return true;
    }
 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package net.codejava.customer;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.*;
 
public class CustomerUserDetailsService implements UserDetailsService {
 
    @Autowired private CustomerRepository repo;
     
    @Override
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
        Customer customer = repo.findByEmail(email);
        if (customer == null) {
            throw new UsernameNotFoundException("No customer found with the given email.");
        }
         
        return new CustomerUserDetails(customer);
    }
 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package net.codejava.customer;
 
import org.springframework.context.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.*;
import org.springframework.security.web.SecurityFilterChain;
 
@Configuration
@Order(2)
public class CustomerSecurityConfig {
 
    @Bean
    public UserDetailsService customerUserDetailsService() {
        return new CustomerUserDetailsService();
    }
 
    @Bean
    public PasswordEncoder passwordEncoder2() {
        return NoOpPasswordEncoder.getInstance();
    }
 
    @Bean
    public DaoAuthenticationProvider authenticationProvider2() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(customerUserDetailsService());
        authProvider.setPasswordEncoder(passwordEncoder2());
 
        return authProvider;
    }
 
    @Bean
    public SecurityFilterChain filterChain2(HttpSecurity http) throws Exception {
        http.authenticationProvider(authenticationProvider2());
 
        http.antMatcher("/customer/**")
            .authorizeRequests().anyRequest().authenticated()
            .and()
            .formLogin()
                .loginPage("/customer/login")
                .usernameParameter("email")
                .loginProcessingUrl("/customer/login")
                .defaultSuccessUrl("/customer/home")
                .permitAll()
            .and()
                .logout()
                    .logoutUrl("/customer/logout")
                    .logoutSuccessUrl("/");
 
        return http.build();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package net.codejava.customer;
 
import org.springframework.context.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.*;
 
@Configuration
@Order(2)
public class CustomerSecurityConfig extends WebSecurityConfigurerAdapter {
 
    @Bean
    public UserDetailsService customerUserDetailsService() {
        return new CustomerUserDetailsService();
    }
 
    @Bean
    public PasswordEncoder passwordEncoder2() {
        return NoOpPasswordEncoder.getInstance();
    }
 
    @Bean
    public DaoAuthenticationProvider authenticationProvider2() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(customerUserDetailsService());
        authProvider.setPasswordEncoder(passwordEncoder2());
 
        return authProvider;
    }
 
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authenticationProvider(authenticationProvider2());
 
        http.antMatcher("/customer/**")
            .authorizeRequests().anyRequest().authenticated()
            .and()
                .formLogin()
                    .loginPage("/customer/login")
                    .usernameParameter("email")
                    .loginProcessingUrl("/customer/login")
                    .defaultSuccessUrl("/customer/home")
                .permitAll()
            .and()
                .logout()
                    .logoutUrl("/customer/logout")
                    .logoutSuccessUrl("/");
    }
}
附件:

Spring Security多登录页面示例文章来源地址https://www.toymoban.com/news/detail-422174.html

SpringBootMultipleLoginExamples.zip
[示例弹簧启动项目] 426 千字节

到了这里,关于Spring Security多登录页面示例的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring Security oauth2.0微信小程序登录

    微信小程序前期开发准备,可以参考这篇文章微信小程序前期准备 1、学习过Spring Secrity oauth2.0的都知道,他有四种登录模式可以选择 authorization code(授权码模式) implicit(简化模式) resource owner password credentials(密码模式) client credentials(客户端模式) 前三种模式都需要用

    2024年02月10日
    浏览(48)
  • Spring-2-深入理解Spring 注解依赖注入(DI):简化Java应用程序开发

      掌握纯注解开发依赖注入(DI)模式 学习使用纯注解进行第三方Bean注入 问题导入 思考:如何使用注解方式将Bean对象注入到类中 1.1 使用@Autowired注解开启自动装配模式(按类型) 说明:不管是使用配置文件还是配置类,都必须进行对应的Spring注解包扫描才可以使用。@Autowired默

    2024年02月14日
    浏览(58)
  • spring boot整合第三方微信开发工具 weixin-java-miniapp 实现小程序微信登录

    有时候项目需要用到微信登录或获取用户的手机号码,weixin-java-miniapp是一个好用的第三方工具,不用我们自己写httpcline调用。 导入jar包 添加一个resource.properties文件,写上小程序的appid和secret 添加两个配置文件 WxMaProperties.java WxMaConfiguration.java 如何使用 小程序给微信发送消息

    2024年02月16日
    浏览(59)
  • Spring-1-深入理解Spring XML中的依赖注入(DI):简化Java应用程序开发

    前两篇文章我们介绍了什么是Spring,以及Spring的一些核心概念,并且快速快发一个Spring项目,以及详细讲解IOC,今天详细介绍一些DI(依赖注入) 能够配置setter方式注入属性值 能够配置构造方式注入属性值 能够理解什么是自动装配 思考:向一个类中传递数据的方式有几种?(给类

    2024年02月13日
    浏览(50)
  • Spring是一个开源的Java开发框架,它提供了一种快速、简单的方式来开发企业级应用程序

    Spring是一个开源的Java开发框架,它提供了一种快速、简单的方式来开发企业级应用程序。Spring的主要优点包括简化Java EE开发、提供依赖注入和面向切面编程等功能。以下是Spring的一些核心特性: 依赖注入(DI):Spring通过DI机制,将对象的依赖关系注入到应用程序中,简化了

    2024年02月03日
    浏览(81)
  • Spring Security--自动登录

    也就是remember me 在配置链上加一个  然后发送请求时加上:remember-me字段 value值可以为,ture,1,on 我们记住登录后,关掉浏览器再打开,访问一下接口,可以访问,说明记住登录成功了。    因为有的接口可以支持rememberMe认证,有的接口不支持,用上图的方式做区别。 //禁止

    2024年02月08日
    浏览(36)
  • Spring Security登录用户数据获取(4)

    登录成功之后,在后续的业务逻辑中,开发者可能还需要获取登录成功的用户对象,如果不使用任何安全管理框架,那么可以将用户信息保存在HttpSession中,以后需要的时候直接从HttpSession中获取数据。在Spring Security中,用户登录信息本质上还是保存在 HttpSession中,但是为了方

    2024年02月03日
    浏览(50)
  • Spring-Security实现登录接口

    Security 是 Spring 家族中的一个安全管理框架。相比与另外一个安全框架 Shiro ,它提供了更丰富的功能,社区资源也比Shiro丰富。 具体介绍和入门看springSecurity入门 在实现之前幺要了解一下登录校验的流程以及 SpringSecurity 的原理以及认证流程 1、登录校验流程 2、 SpringSecurity完

    2024年01月18日
    浏览(50)
  • Spring Security进行登录认证和授权

    用户首次登录提交用户名和密码后spring security 的 UsernamePasswordAuthenticationFilter 把用户名密码封装 Authentication 对象 然后内部调用 ProvideManager 的 authenticate 方法进行认证,然后 ProvideManager 进一步通过内部调用 DaoAuthencationPriovider 的 authenticate 方法进行认证 DaoAuthencationPriovider 通过

    2024年02月11日
    浏览(45)
  • 系列十一、Spring Security登录接口兼容JSON格式登录

            前后端分离中,前端和后端的数据交互通常是JSON格式,而Spring Security的登录接口默认支持的是form-data或者x-www-form-urlencoded的,如下所示: 那么如何让Spring Security的登录接口也支持JSON格式登录呢?请看下文分析 

    2024年01月20日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包