明白!我帮你写一个Spring Security详解,每个核心场景都附带完整示例代码,覆盖认证、授权、用户存储、密码加密、自定义登录、方法级安全等,便于直接拿来用或学习。


Spring Security详解 —— 场景+代码全覆盖


1. 基础认证(In-Memory 用户)

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("alice").password("{noop}123456").roles("USER")
            .and()
            .withUser("admin").password("{noop}admin").roles("ADMIN");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .anyRequest().authenticated()  // 所有请求需要认证
            .and()
            .formLogin().permitAll()       // 开启表单登录
            .and()
            .logout().permitAll();
    }
}

2. 基于数据库的认证与密码加密

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Autowired
    private DataSource dataSource;
    
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication()
            .dataSource(dataSource)
            .passwordEncoder(passwordEncoder())
            .usersByUsernameQuery("SELECT username, password, enabled FROM users WHERE username = ?")
            .authoritiesByUsernameQuery("SELECT username, authority FROM authorities WHERE username = ?");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .anyRequest().authenticated()
            .and().formLogin().permitAll()
            .and().logout().permitAll();
    }
}

3. URL基于角色权限访问控制

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
        .antMatchers("/admin/**").hasRole("ADMIN")
        .antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
        .antMatchers("/", "/home", "/public/**").permitAll()
        .anyRequest().authenticated()
        .and().formLogin().permitAll();
}

4. 自定义登录页面和登录成功跳转

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.formLogin()
        .loginPage("/login")              // 自定义登录页
        .defaultSuccessUrl("/dashboard") // 登录成功跳转
        .failureUrl("/login?error")      // 登录失败跳转
        .permitAll();
}

5. 方法级权限控制(注解)

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration { }

@Service
public class ProductService {

    @PreAuthorize("hasRole('ADMIN')")
    public void adminOnlyOperation() {
        // 管理员专属操作
    }

    @PreAuthorize("hasAuthority('PRODUCT_READ')")
    public void userReadOperation() {
        // 拥有PRODUCT_READ权限可执行
    }
}

6. 用户注销配置

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.logout()
        .logoutUrl("/perform_logout")
        .logoutSuccessUrl("/login?logout")
        .invalidateHttpSession(true)
        .deleteCookies("JSESSIONID")
        .permitAll();
}

7. CSRF防护示例

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}

8. 基于JWT的无状态认证示例(简要)

public class JwtAuthenticationFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
            throws ServletException, IOException {
        String token = req.getHeader("Authorization");
        if (token != null && token.startsWith("Bearer ")) {
            // 验证token逻辑
            Authentication auth = getAuthentication(token);
            SecurityContextHolder.getContext().setAuthentication(auth);
        }
        chain.doFilter(req, res);
    }
}

SecurityConfig中注册过滤器:

http.addFilterBefore(new JwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);

9. 异常处理示例(访问拒绝)

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.exceptionHandling()
        .accessDeniedHandler((request, response, accessDeniedException) -> {
            response.sendRedirect("/403");
        });
}

10. CORS跨域支持配置

@Bean
public CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedOrigins(List.of("http://localhost:3000"));
    configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE"));
    configuration.setAllowedHeaders(List.of("*"));
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);
    return source;
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.cors().and().csrf().disable();
}