Spring Security入门:保护Web应用

2023年 9月 12日 25.4k 0

本文我们将构建一个简单但完整的小型 Web 应用程序,以演示 Spring Security 的入门教程。系统大致逻辑是:当合法用户成功登录系统之后,浏览器会跳转到一个系统主页,并展示一些个人健康档案(HealthRecord)数据。

让我们开始吧!

系统初始化

这部分工作涉及领域对象的定义、数据库初始化脚本的整理以及相关依赖组件的引入。

针对领域对象,我们重点来看如下所示的 User 类定义:

 @Entity
 public class User {
  
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     private Integer id;
  
     private String username;
     private String password;
  
     @Enumerated(EnumType.STRING)
     private PasswordEncoderType passwordEncoderType;
  
     @OneToMany(mappedBy = "user", fetch = FetchType.EAGER)
     private List authorities;
     …
 }
 public enum PasswordEncoderType {
     BCRYPT, SCRYPT
 }

可以看到,这里除了指定主键 id、用户名 username 和密码 password 之外,还包含了一个加密算法枚举值 EncryptionAlgorithm。在案例系统中,我们将提供 BCryptPasswordEncoder 和 SCryptPasswordEncoder 这两种可用的密码解密器,你可以通过该枚举值进行设置。

同时,我们在 User 类中还发现了一个 Authority 列表。显然,这个列表用来指定该 User 所具备的权限信息。Authority 类的定义如下所示:

 @Entity
 public class Authority {
  
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     private Integer id;
  
     private String name;
  
     @JoinColumn(name = "user")
     @ManyToOne
     private User user;
     …
 }

通过定义不难看出 User 和 Authority 之间是一对多的关系。

基于 User 和 Authority 领域对象,我们也给出创建数据库表的 SQL 定义,如下所示:

 CREATE TABLE IF NOT EXISTS `spring_security`.`user` (
   `id` INT NOT NULL AUTO_INCREMENT,
   `username` VARCHAR(45) NOT NULL,
   `password` TEXT NOT NULL,
   `password_encoder_type` VARCHAR(45) NOT NULL,
   PRIMARY KEY (`id`));
 ​
 CREATE TABLE IF NOT EXISTS `spring_security`.`authority` (
   `id` INT NOT NULL AUTO_INCREMENT,
   `name` VARCHAR(45) NOT NULL,
   `user` INT NOT NULL,
   PRIMARY KEY (`id`));
   
 CREATE TABLE IF NOT EXISTS `spring_security`.`health_record` (
   `id` INT NOT NULL AUTO_INCREMENT,
   `username` VARCHAR(45) NOT NULL,
   `name` VARCHAR(45) NOT NULL,
   `value` VARCHAR(45) NOT NULL,
   PRIMARY KEY (`id`));

在运行系统之前,我们同样也需要初始化数据,对应脚本如下所示:

 INSERT IGNORE INTO `spring_security`.`user` (`id`, `username`, `password`, `password_encoder_type`) VALUES ('1', 'studeyang', '$2a$10$xn3LI/AjqicFYZFruSwve.681477XaVNaUQbr1gioaWPn4t1KsnmG', 'BCRYPT');
 ​
 INSERT IGNORE INTO `spring_security`.`authority` (`id`, `name`, `user`) VALUES ('1', 'READ', '1');
 INSERT IGNORE INTO `spring_security`.`authority` (`id`, `name`, `user`) VALUES ('2', 'WRITE', '1');
 ​
 INSERT IGNORE INTO `spring_security`.`health_record` (`id`, `username`, `name`, `value`) VALUES ('1', 'studeyang', 'weight', '70');
 INSERT IGNORE INTO `spring_security`.`health_record` (`id`, `username`, `name`, `value`) VALUES ('2', 'studeyang', 'height', '177');
 INSERT IGNORE INTO `spring_security`.`health_record` (`id`, `username`, `name`, `value`) VALUES ('3', 'studeyang', 'bloodpressure', '70');
 INSERT IGNORE INTO `spring_security`.`health_record` (`id`, `username`, `name`, `value`) VALUES ('4', 'studeyang', 'pulse', '80');

这里初始化了一个用户名为 “studeyang”的用户,同时指定了它的密码为“12345”,加密算法为“BCRYPT”。

现在,领域对象和数据层面的初始化工作已经完成了,接下来我们需要在代码工程的 pom 文件中添加如下所示的 Maven 依赖:

       
         
             org.springframework.boot
             spring-boot-starter-data-jpa
         
         
             org.springframework.boot
             spring-boot-starter-security
         
         
             org.springframework.boot
             spring-boot-starter-thymeleaf
         
         
             org.springframework.boot
             spring-boot-starter-web
         
  
         
             mysql
             mysql-connector-java
             runtime
         
         
             org.springframework.security
             spring-security-test
             test
         
 

实现用户管理

实现自定义用户认证的过程通常涉及两大部分内容,一方面需要使用 User 和 Authority 对象来完成定制化的用户管理,另一方面需要把这个定制化的用户管理嵌入整个用户认证流程中。

如果你想实现自定义的用户信息,扩展 UserDetails 这个接口即可。实现方式如下所示:

 public class CustomUserDetails implements UserDetails {
 
     private final User user;
 
     public CustomUserDetails(User user) {
         this.user = user;
    }
 
     @Override
     public Collection

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论