Spring Security 快速入门

  1. 引入依赖
    • 如果使用Maven,在pom.xml文件中添加Spring Security依赖。对于Spring Boot项目:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring - boot - starter - security</artifactId>
</dependency>
  • 如果是普通Spring项目,还需要添加Spring Security相关的核心依赖和Web相关依赖等。
  1. 简单配置
    • 创建一个配置类,继承WebSecurityConfigurerAdapter,用于配置Spring Security。
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.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
           .authorizeRequests()
               .antMatchers("/", "/home").permitAll()
               .anyRequest().authenticated()
               .and()
           .formLogin()
               .loginPage("/login")
               .permitAll()
               .and()
           .logout()
               .permitAll();
    }

    @Bean
    @Override
    public UserDetailsService userDetailsService() {
        UserDetails user =
            User.withDefaultPasswordEncoder()
               .username("user")
               .password("password")
               .roles("USER")
               .build();

        UserDetails admin =
            User.withDefaultPasswordEncoder()
               .username("admin")
               .password("admin")
               .roles("ADMIN")
               .build();

        return new InMemoryUserDetailsManager(user, admin);
    }
}
  • 在上述配置中:
    • configure(HttpSecurity http)方法定义了访问规则。//home路径允许所有用户访问,其他路径需要认证。
    • formLogin()配置了基于表单的登录,loginPage("/login")指定了登录页面路径,并且允许所有用户访问登录页面。
    • logout()配置了注销功能,允许所有用户访问注销路径。
    • userDetailsService()方法在内存中创建了两个用户useradmin,并为其分配了角色。
  1. 创建登录和页面
    • 创建一个简单的login.html作为登录页面:
<!DOCTYPE html>
<html lang="zh - CN">
<head>
    <meta charset="UTF - 8">
    <title>登录</title>
</head>
<body>
    <form action="/login" method="post">
        <label for="username">用户名:</label>
        <input type="text" id="username" name="username" required><br>
        <label for="password">密码:</label>
        <input type="password" id="password" name="password" required><br>
        <input type="submit" value="登录">
    </form>
</body>
</html>
  • 创建一个home.html作为登录成功后的页面:
<!DOCTYPE html>
<html lang="zh - CN">
<head>
    <meta charset="UTF - 8">
    <title>首页</title>
</head>
<body>
    <h1>欢迎登录</h1>
</body>
</html>
  1. 启动应用
    • 启动Spring Boot应用(如果是Spring Boot项目)或部署到应用服务器(如Tomcat等)。访问应用,未登录时会被重定向到登录页面,输入正确的用户名和密码后可访问受保护的资源。

Spring Security 高级应用

  1. 自定义认证逻辑
    • 实现UserDetailsService接口,从数据库或其他数据源加载用户信息。
import org.springframework.beans.factory.annotation.Autowired;
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;

@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("用户不存在");
        }
        // 将用户信息转换为Spring Security的UserDetails
        return org.springframework.security.core.userdetails.User.withDefaultPasswordEncoder()
              .username(user.getUsername())
              .password(user.getPassword())
              .roles(user.getRole())
              .build();
    }
}
  • 在配置类中使用自定义的UserDetailsService
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomUserDetailsService customUserDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 配置其他安全规则
    }

    @Override
    @Bean
    public UserDetailsService userDetailsService() {
        return customUserDetailsService;
    }
}
  1. 基于角色和权限的授权
    • 在配置类的configure(HttpSecurity http)方法中细化授权规则。例如,只有具有ADMIN角色的用户才能访问特定的管理页面:
http
   .authorizeRequests()
       .antMatchers("/admin/**").hasRole("ADMIN")
       .antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
       .anyRequest().authenticated();
  • 也可以基于权限进行授权,在数据库中为用户分配具体的权限,然后在配置中使用hasAuthority方法进行判断。
  1. OAuth2集成
    • 引入OAuth2相关依赖:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring - boot - starter - oauth2 - client</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring - boot - starter - oauth2 - resource - server</artifactId>
</dependency>
  • 配置OAuth2客户端,例如配置GitHub登录:
spring:
  security:
    oauth2:
      client:
        registration:
          github:
            client - id: your - github - client - id
            client - secret: your - github - client - secret
            scope: read:user,user:email
            authorization - grant - type: authorization_code
            redirect - uri: "{baseUrl}/login/oauth2/code/{registrationId}"
            client - name: GitHub
  • 配置资源服务器,保护受OAuth2保护的资源:
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
           .authorizeRequests()
               .antMatchers("/api/**").authenticated();
    }
}
  1. 安全事件监听和审计
    • 实现ApplicationListener接口监听Spring Security相关事件,如登录成功、失败事件等。
import org.springframework.context.ApplicationListener;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.stereotype.Component;

@Component
public class LoginSuccessListener implements ApplicationListener<AuthenticationSuccessEvent> {

    @Override
    public void onApplicationEvent(AuthenticationSuccessEvent event) {
        // 记录登录成功日志或进行其他审计操作
        System.out.println("用户 " + event.getAuthentication().getName() + " 登录成功");
    }
}
  • 类似地,可以监听AuthenticationFailureBadCredentialsEvent等事件来记录登录失败信息,实现审计功能。
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐