欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 焦点 > Spring——SpringSecurity开发经验实战

Spring——SpringSecurity开发经验实战

2025/2/24 16:13:35 来源:https://blog.csdn.net/weixin_41605937/article/details/145816115  浏览:    关键词:Spring——SpringSecurity开发经验实战

摘要

本文介绍了一个简单的 Spring Security 实战示例,涵盖基本的身份验证和授权流程。首先介绍了 Spring Security 是一个强大的安全框架,用于在 Spring 应用中实现身份验证、授权以及保护应用免受常见安全攻击。接着详细阐述了项目结构、添加 Spring Security 依赖、创建数据库表、创建实体类、创建 UserDetailsService 实现、配置 Spring Security、使用@PreAuthorize注解控制方法权限、配置启动类、配置 application.properties 以及运行和测试等步骤。

1. Spring Security简介

Spring Security 是一个强大的安全框架,主要用于在 Spring 应用中实现身份验证、授权以及保护应用免受常见安全攻击。以下是一个简单的 Spring Security 实战示例,涵盖了基本的身份验证和授权流程。

2. 项目结构

src└── main├── java│    └── com│         └── example│              └── security│                   ├── SecurityConfig.java│                   ├── WebController.java│                   ├── Application.java│                   ├── CustomUserDetailsService.java│                   ├── User.java│                   ├── Role.java│                   └── UserRepository.java└── resources├── application.properties├── schema.sql└── data.sql

3. 添加 Spring Security 依赖

首先,确保在 pom.xmlbuild.gradle 中添加了 Spring Security 的依赖。

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-config</artifactId>
</dependency>

4. 创建数据库表

首先,我们需要为用户和角色创建数据库表。下面是一个简单的 SQL 脚本,用于在数据库中创建用户和角色表。

4.1. schema.sql 文件:

CREATE TABLE roles (id BIGINT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(50) NOT NULL
);CREATE TABLE users (id BIGINT AUTO_INCREMENT PRIMARY KEY,username VARCHAR(50) NOT NULL UNIQUE,password VARCHAR(255) NOT NULL,enabled BOOLEAN NOT NULL DEFAULT true
);CREATE TABLE user_roles (user_id BIGINT,role_id BIGINT,PRIMARY KEY (user_id, role_id),FOREIGN KEY (user_id) REFERENCES users(id),FOREIGN KEY (role_id) REFERENCES roles(id)
);

4.2. data.sql 文件:

INSERT INTO roles (name) VALUES ('ROLE_ADMIN');
INSERT INTO roles (name) VALUES ('ROLE_USER');INSERT INTO users (username, password, enabled) VALUES ('admin', '{noop}admin', true);
INSERT INTO users (username, password, enabled) VALUES ('user', '{noop}user', true);INSERT INTO user_roles (user_id, role_id) 
SELECT u.id, r.id 
FROM users u, roles r 
WHERE u.username = 'admin' AND r.name = 'ROLE_ADMIN';INSERT INTO user_roles (user_id, role_id) 
SELECT u.id, r.id 
FROM users u, roles r 
WHERE u.username = 'user' AND r.name = 'ROLE_USER';

这里,{noop} 是 Spring Security 5 之前的一个标记,用于指示密码不加密。生产环境中应使用加密密码,如 BCrypt

5. 创建实体类

我们需要两个实体类 UserRole,分别表示用户和角色信息。

5.1. User.java

package com.example.security;import javax.persistence.*;
import java.util.Set;@Entity
public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String username;private String password;private boolean enabled;@ManyToMany(fetch = FetchType.EAGER)@JoinTable(name = "user_roles", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))private Set<Role> roles;// Getters and Setters
}

5.2. Role.java

package com.example.security;import javax.persistence.*;@Entity
public class Role {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;// Getters and Setters
}

6. 创建 UserDetailsService 实现

我们将通过 UserDetailsService 从数据库加载用户信息,Spring Security 会使用这个服务来进行身份验证和权限控制。

6.1. CustomUserDetailsService.java

package com.example.security;import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;import java.util.stream.Collectors;@Service
public class CustomUserDetailsService implements UserDetailsService {@Autowiredprivate final UserRepository userRepository;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {// 查询数据库,加载用户及其角色User user = userRepository.findByUsername(username).orElseThrow(() -> new UsernameNotFoundException("User not found"));// 将角色转换为 GrantedAuthorityreturn new User(user.getUsername(),user.getPassword(),user.isEnabled(),true, true, true,user.getRoles().stream().map(role -> new org.springframework.security.core.authority.SimpleGrantedAuthority(role.getName())).collect(Collectors.toList()));}
}

6.2. UserRepository.java

package com.example.security;import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;public interface UserRepository extends JpaRepository<User, Long> {Optional<User> findByUsername(String username);
}

7. 配置 Spring Security

SecurityConfig中,配置数据库认证,并启用方法级别的权限控制。

7.1. SecurityConfig.java

package com.example.security;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.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)  // 启用方法级权限控制
public class SecurityConfig {@Autowiredprivate final CustomUserDetailsService customUserDetailsService;@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/login", "/public/**").permitAll().anyRequest().authenticated().and().formLogin().permitAll().and().logout().permitAll();return http.build();}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Beanpublic void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());}
}

8. 使用@PreAuthorize注解控制方法权限

在控制器方法上使用 @PreAuthorize 注解进行权限控制。比如,你可以根据角色控制谁能访问哪些页面。

8.1. WebController.java

package com.example.security;import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;@Controller
public class WebController {@GetMapping("/admin")@PreAuthorize("hasRole('ROLE_ADMIN')")  // 只有角色为 ROLE_ADMIN 的用户可以访问public String adminPage() {return "admin";}@GetMapping("/user")@PreAuthorize("hasRole('ROLE_USER')")   // 只有角色为 ROLE_USER 的用户可以访问public String userPage() {return "user";}@GetMapping("/dashboard")@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_USER')")  // 角色为 ROLE_ADMIN 或 ROLE_USER 的用户可以访问public String dashboard() {return "dashboard";}
}

9. 配置启动类

确保你有一个 Application 启动类来启动 Spring Boot 应用。

9.1. Application.java

package com.example.security;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

10. 配置 application.properties

确保你的 application.properties 中包含数据库连接配置。

application.properties

spring.datasource.url=jdbc:mysql://localhost:3306/security_db?useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.security.user.name=admin
spring.security.user.password=admin

11. 运行和测试

  1. 启动 Spring Boot 应用。
  2. 使用 adminuser 用户分别登录,访问 /admin/user/dashboard 页面,检查是否能根据角色权限控制访问。

这个示例展示了如何在 Spring Boot 中使用数据库存储用户和角色信息,并通过 @PreAuthorize 注解进行方法级别的权限控制。我们通过自定义 UserDetailsService 从数据库中加载用户信息并设置相应的角色。这样,Spring Security 会根据用户的角色来控制对不同控制器方法的访问权限。

博文参考

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词