java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > spring security 框架

Spring Security 框架最佳实践

作者:海马

Spring Security 是一个功能强大、高度可定制的身份验证(Authentication)和访问控制(Authorization)框架,是保护基于 Spring 的应用的事实标准,本文给大家介绍Spring Security框架最佳实践,感兴趣的朋友跟随小编一起看看吧

一、什么是 Spring Security?

Spring Security 是一个功能强大、高度可定制的身份验证(Authentication)和访问控制(Authorization)框架,是保护基于 Spring 的应用的事实标准。

✅ 核心功能:

二、Spring Security 核心概念

1.Authentication(认证)

2.UserDetails&UserDetailsService

@Override
public UserDetails loadUserByUsername(String username) {
    // 从数据库查用户 → 返回 UserDetails(含加密密码 + 权限)
}

3.PasswordEncoder

// 注册时:
user.setPassword(passwordEncoder.encode(rawPassword));
// 登录时(框架自动调用):
passwordEncoder.matches(rawPassword, encodedPassword); // true/false

4.GrantedAuthority

5.SecurityContext&SecurityContextHolder

Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String username = auth.getName();

三、Spring Security 工作流程(认证过程)

sequenceDiagram
    participant User
    participant Filter as FilterChain (Spring Security)
    participant Provider as AuthenticationProvider
    participant Service as UserDetailsService
    participant Encoder as PasswordEncoder
    User->>Filter: 提交用户名/密码
    Filter->>Provider: 调用 authenticate()
    Provider->>Service: loadUserByUsername(username)
    Service-->>Provider: 返回 UserDetails(含加密密码)
    Provider->>Encoder: matches(输入密码, 数据库加密密码)
    alt 匹配成功
        Encoder-->>Provider: true
        Provider-->>Filter: 返回认证成功 Authentication
        Filter->>User: 登录成功,跳转
    else 匹配失败
        Encoder-->>Provider: false
        Provider-->>Filter: 抛出异常
        Filter->>User: 登录失败
    end

四、常用配置方式(Spring Boot)

1. 引入依赖(Maven)

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

2. 基础配置类(启用 Web 安全)

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(authz -> authz
                .requestMatchers("/login", "/register", "/css/**").permitAll()
                .requestMatchers("/admin/**").hasRole("ADMIN")
                .requestMatchers("/user/**").hasAnyRole("USER", "ADMIN")
                .anyRequest().authenticated()
            )
            .formLogin(form -> form
                .loginPage("/login")           // 自定义登录页
                .defaultSuccessUrl("/home")    // 登录成功跳转
                .permitAll()
            )
            .logout(logout -> logout
                .logoutSuccessUrl("/login?logout")
                .permitAll()
            );
        return http.build();
    }
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder(); // 推荐使用 BCrypt
    }
}

3. 自定义 UserDetailsService

@Component
public class MyUserServiceImpl implements UserDetailsService {
    @Autowired
    private UserMapper userMapper;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userMapper.findUserByName(username);
        if (user == null) throw new UsernameNotFoundException("用户不存在");
        // ✅ 直接返回数据库中的加密密码(注册时已加密存储!)
        return User.builder()
            .username(user.getUsername())
            .password(user.getSupwd()) // ← 不要再 encode!
            .roles("USER") // 或者 .authorities(getAuthorities())
            .build();
    }
}

五、权限控制(授权 Authorization)

1. 方法级别权限(推荐)

@Service
public class ArticleService {
    @PreAuthorize("hasRole('ADMIN')") // 需要 ADMIN 角色
    public void deleteArticle(Long id) {
        // ...
    }
    @PreAuthorize("hasAuthority('article:edit')") // 需要具体权限
    public void editArticle(Article article) {
        // ...
    }
    @PostAuthorize("returnObject.owner == authentication.name")
    public Article getArticle(Long id) {
        // 返回后检查:只有文章主人才能看
    }
}

⚠️ 要启用方法级权限,需在配置类加:@EnableMethodSecurity

@Configuration
@EnableWebSecurity
@EnableMethodSecurity // ← 启用 @PreAuthorize 等注解
public class SecurityConfig { ... }

2. 页面级别权限(Thymeleaf)

<!-- 只有 ADMIN 能看到 -->
<div sec:authorize="hasRole('ADMIN')">
    <a href="/admin" rel="external nofollow" >管理后台</a>
</div>
<!-- 显示当前用户名 -->
<span sec:authentication="name"></span>

需引入:

<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity6</artifactId>
</dependency>

六、常见自定义扩展

1. 自定义登录成功/失败处理器

@Component
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, 
                                        HttpServletResponse response, 
                                        Authentication authentication) throws IOException {
        response.sendRedirect("/home?loginSuccess");
    }
}

在配置中使用:

.formLogin(form -> form
    .successHandler(mySuccessHandler)
    .failureHandler(myFailureHandler)
)

2. 自定义权限异常处理

@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException {
        response.sendRedirect("/403");
    }
}

配置:

.exceptionHandling(ex -> ex
    .accessDeniedHandler(myAccessDeniedHandler)
)

七、与 JWT / 前后端分离集成(简要)

如果你是前后端分离项目(如 Vue + Spring Boot),通常不用 Session,改用 JWT:

  1. 用户 POST /login 提交用户名密码
  2. 后端验证成功 → 生成 JWT Token 返回
  3. 前端后续请求在 Header 中携带 Authorization: Bearer <token>
  4. 后端用 Filter 解析 Token → 设置 SecurityContext

⚠️ 此时 UserDetailsService 依然有用 —— 用于从 Token 中的用户名加载用户权限!

八、最佳实践 & 注意事项

项目建议
密码存储必须加密(BCrypt 最常用)
密码比对交给 Spring Security,不要手动比对
权限设计角色(ROLE_) + 细粒度权限(user:delete)结合
登录页可自定义,但路径要 permitAll
CSRF表单登录默认开启,JWT 项目可关闭
调试可临时 .authorizeHttpRequests(authz -> authz.anyRequest().permitAll()) 放行所有

✅ 总结一句话:

Spring Security = 认证(你是谁)+ 授权(你能干什么)+ 安全防护,你只需要提供“用户数据”和“权限规则”,框架自动完成验证和拦截。

📚 学习路径建议:

  1. 先跑通表单登录 + 自定义 UserDetailsService
  2. 学会配置 URL 权限控制
  3. 掌握方法级权限 @PreAuthorize
  4. 学习自定义处理器(登录成功/失败、无权限)
  5. 进阶:JWT、OAuth2、方法权限表达式、动态权限

💡 送你一个完整可运行的最小示例结构:

src/
├── controller/
│   └── LoginController.java       // 登录页、首页
├── service/
│   └── MyUserServiceImpl.java     // loadUserByUsername
├── config/
│   └── SecurityConfig.java        // 权限配置 + PasswordEncoder
└── entity/
    └── User.java                  // 用户实体(含加密密码字段)

到此这篇关于Spring Security 框架的文章就介绍到这了,更多相关spring security 框架内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文