博主介绍:Java、Python、js全栈开发 “多面手”,精通多种编程语言和技术,痴迷于人工智能领域。秉持着对技术的热爱与执着,持续探索创新,愿在此分享交流和学习,与大家共进步。
DeepSeek-行业融合之万象视界(附实战案例详解100+)
全栈开发环境搭建运行攻略:多语言一站式指南(环境搭建+运行+调试+发布+保姆级详解)
感兴趣的可以先收藏起来,希望帮助更多的人
SpringSecurity 是 Spring 生态系统中的一个强大且高度可定制的身份验证和访问控制框架。它为基于 Spring 的应用程序提供了全面的安全服务,能够帮助开发者轻松地实现各种安全需求,如用户认证、授权、防止跨站请求伪造(CSRF)等。SpringSecurity 遵循 JavaEE 安全标准,并且与 Spring 框架无缝集成,使得开发者可以利用 Spring 的依赖注入、AOP 等特性来构建安全的应用程序。
SpringSecurity 广泛应用于各种 Web 应用程序、RESTful API 服务、企业级应用等。在 Web 应用中,它可以用于保护用户登录、权限管理、防止恶意攻击等;在 RESTful API 服务中,它可以实现 API 的身份验证和授权,确保只有合法的用户或服务能够访问 API。
在 SpringBoot 项目中使用 SpringSecurity,首先需要在 pom.xml
中引入相关依赖:
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-securityartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
dependencies>
创建一个配置类来配置 SpringSecurity,继承 WebSecurityConfigurerAdapter
类并重写相关方法:
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.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
}
在上述代码中,passwordEncoder()
方法用于创建一个密码编码器,这里使用 BCryptPasswordEncoder
对密码进行加密。configure(HttpSecurity http)
方法用于配置 HTTP 请求的安全规则,anyRequest().authenticated()
表示所有请求都需要进行身份验证,formLogin()
启用表单登录,httpBasic()
启用 HTTP 基本认证。
SpringSecurity 支持在内存中配置用户信息进行认证,修改 SecurityConfig
类如下:
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.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user")
.password(passwordEncoder().encode("password"))
.roles("USER");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
}
在 configure(AuthenticationManagerBuilder auth)
方法中,使用 inMemoryAuthentication()
配置内存认证,创建一个用户名为 user
,密码为 password
(经过加密),角色为 USER
的用户。
在实际应用中,通常会使用数据库来存储用户信息。首先需要创建用户实体类和用户服务类:
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
private String role;
// getters and setters
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("User not found");
}
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority(user.getRole()));
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), authorities);
}
}
然后修改 SecurityConfig
类:
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.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService customUserDetailsService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
}
在上述代码中,CustomUserDetailsService
实现了 UserDetailsService
接口,用于从数据库中加载用户信息。SecurityConfig
类中使用 userDetailsService()
方法将自定义的用户服务类注入到 SpringSecurity 中。
在 SecurityConfig
类中,可以根据用户的角色来控制对不同 URL 的访问权限:
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.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService customUserDetailsService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/**").hasRole("USER")
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
}
在上述代码中,antMatchers("/admin/**").hasRole("ADMIN")
表示只有具有 ADMIN
角色的用户才能访问以 /admin/
开头的 URL,antMatchers("/user/**").hasRole("USER")
表示只有具有 USER
角色的用户才能访问以 /user/
开头的 URL。
除了基于角色的授权,还可以基于具体的权限进行授权。首先需要在用户实体类中添加权限字段,然后在 CustomUserDetailsService
类中添加权限信息:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("User not found");
}
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority(user.getRole()));
authorities.add(new SimpleGrantedAuthority(user.getPermission()));
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), authorities);
}
}
然后在 SecurityConfig
类中使用 hasAuthority()
方法进行权限控制:
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.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService customUserDetailsService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasAuthority("ADMIN_PERMISSION")
.antMatchers("/user/**").hasAuthority("USER_PERMISSION")
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
}
使用 Spring Initializr 创建一个新的 SpringBoot 项目,添加 Spring Web
和 Spring Security
依赖。
创建一个简单的控制器来处理不同的请求:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/")
public String hello() {
return "Hello, World!";
}
@GetMapping("/admin")
public String admin() {
return "Welcome, Admin!";
}
@GetMapping("/user")
public String user() {
return "Welcome, User!";
}
}
根据前面的授权配置,在 SecurityConfig
类中配置不同 URL 的访问权限。
启动应用程序,访问不同的 URL,验证用户认证和授权功能。例如,访问 /
会跳转到登录页面,登录成功后可以访问相应的 URL;如果没有相应的角色或权限,访问会被拒绝。
SpringSecurity 是一个功能强大且高度可定制的安全框架,通过本文的介绍,我们了解了 SpringSecurity 的基本配置、用户认证和授权的实现方法,并通过实战案例进行了验证。在实际开发中,可以根据具体的需求对 SpringSecurity 进行定制,以确保应用程序的安全性。