SpringBoot开发——SpringSecurity安全框架17个业务场景案例(三)

发布于:2024-10-09 ⋅ 阅读:(6) ⋅ 点赞:(0)

文章目录

  • 一、Spring Security 常用应用场景介绍
  • 二、Spring Security场景案例
    • 12 表达式支持(Expression-Based)
      • 12.1 Spring Security 配置
      • 12.2 业务逻辑代码
      • 12.3 控制器
    • 13、安全上下文(Security Context)
      • 13.1 Spring Security 配置
      • 13.2 业务逻辑代码
      • 13.3 控制器
    • 14、安全过滤器链(Security Filter Chain)
      • 14.1 Spring Security 配置
      • 14.2 业务逻辑代码
      • 14.3 控制器
    • 15、用户详细信息服务(UserDetailsService)
      • 15.1 Spring Security 配置
      • 15.2 业务逻辑代码
      • 15.3 控制器
    • 16、多因素认证(Multi-Factor Authentication)
      • 16.1 Spring Security 配置
      • 16.2 业务逻辑代码
      • 16.3 控制器
    • 17、匿名访问(Anonymous Access)
      • 17.1 Spring Security 配置
      • 17.2 业务逻辑代码
      • 17.3 控制器

Spring Security通过一系列注解简化了安全配置,我们将深入探讨 Spring Security框架的17个关键应用场景,包括认证、授权、 OAuth2CSRF保护等。每个案例都配有详细的时序图和代码示例,旨在帮助开发者全面理解并有效利用 Spring Security的强大功能,以构建更安全、更可靠的应用程序。

一、Spring Security 常用应用场景介绍

1、认证(Authentication)

  • 应用场景:确保只有经过验证的用户才能访问应用程序。

2、授权(Authorization)

  • 应用场景:控制用户对特定资源的访问权限,如角色基础的访问控制。

3、表单登录(Form-Based Login)

  • 应用场景:为用户提供登录表单,处理登录请求和重定向。

4、HTTP 基本认证(HTTP Basic Authentication)

  • 应用场景:为 RESTful API 或其他服务提供基础的用户名和密码认证。

5、OAuth2 和 OpenID Connect

  • 应用场景:支持现代的授权框架,适用于需要第三方应用认证的场景。

6、CSRF 保护(CSRF Protection)

  • 应用场景:防止跨站请求伪造攻击,保护 Web 应用程序的安全。

7、密码编码(Password Encoding)

  • 应用场景:安全地存储用户密码,防止密码泄露。

8、方法级安全性(Method Security)

  • 应用场景:控制对特定方法或 Bean 属性的访问,实现细粒度的安全控制。

9、异常处理(Exception Handling)

  • 应用场景:自定义安全相关的异常处理,如认证失败、授权失败。

10、记住我(Remember-Me)

  • 应用场景:为用户提供持久的登录状态,方便用户再次访问。

11、预授权(Pre-Invocation)

  • 应用场景:在方法执行前进行安全检查,确保方法调用的安全性。

12、表达式支持(Expression-Based)

  • 应用场景:使用 Spring Expression Language (SpEL) 实现复杂的安全逻辑。

13、安全上下文(Security Context)

  • 应用场景:管理和检索认证信息,如获取当前认证用户。

14、安全过滤器链(Security Filter Chain)

  • 应用场景:处理 HTTP 请求的安全检查,如认证、授权。

15、用户详细信息服务(UserDetailsService)

  • 应用场景:自定义用户认证信息的加载逻辑,如从数据库加载用户数据。

16、多因素认证(Multi-Factor Authentication)

  • 应用场景:增加额外的安全层,如短信验证码、电子邮件确认。

17、匿名访问(Anonymous Access)

  • 应用场景:允许未认证的用户访问某些公共资源。

二、Spring Security场景案例

12 表达式支持(Expression-Based)

业务场景: 一个在线文档管理系统,其中某些文档的访问权限依赖于用户的多个属性,例如部门和角色。需要使用复杂的表达式来确定用户是否有权访问特定文档。

业务时序图
在这里插入图片描述
1.用户(User) 请求一个资源。

2.浏览器(Browser) 向服务器(Server)发送HTTP 请求

3.服务器(Server) 的 认证管理器(AuthenticationManager) 对请求进行认证。

4.认证管理器(AuthenticationManager) 返回认证令牌给服务器。

5.服务器(Server) 的 方法安全拦截器(MethodSecurityInterceptor) 检查授权。

6.方法安全拦截器(MethodSecurityInterceptor) 请求 表达式评估器(ExpressionEvaluator) 处理SpEL 表达式

7.表达式评估器(ExpressionEvaluator) 根据当前的安全上下文和定义的表达式返回评估结果。

8.方法安全拦截器(MethodSecurityInterceptor) 根据评估结果做出访问决策。

9.服务器(Server) 将响应返回给浏览器。

12.1 Spring Security 配置

首先,我们需要配置Spring Security以启用表达式支持。

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
   

    @Override
    protected void configure(HttpSecurity http) throws Exception {
   
        http
            .authorizeRequests()                 
				.antMatchers("/documents/**").access("hasRole('ADMIN') or hasAuthority('DOCUMENT_READ')")
                .anyRequest().authenticated()
            .and()
            .formLogin()
                .loginPage("/login")              
				.defaultSuccessUrl("/home")            
			.and()
            .logout()
                .logoutSuccessUrl("/login?logout");
    }

}

12.2 业务逻辑代码

创建一个服务来处理文档访问,并使用表达式来定义访问权限。

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;

@Service
public class DocumentService {
   

    /**
     * 获取文档内容
     * 
     * @param documentId 文档ID
     * @return 文档内容
     */
    @PreAuthorize("hasAuthority('DOCUMENT_READ') and #documentId == authentication.principal.departmentId")
    public String getDocumentContent(Long documentId) {
   
        // 模拟从数据库获取文档内容
        return "Content of the document " + documentId;
    }

}

12.3 控制器

创建一个控制器来处理文档访问请求。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DocumentController {
   
    @Autowired
    private DocumentService documentService;

    @GetMapping("/documents/{documentId}")
    public ResponseEntity<String> getDocument(@PathVariable Long documentId) {
   
        return ResponseEntity.ok(documentService.getDocumentContent(documentId));
    }

}

说明

  • 配置类:配置了Spring Security,并启用了方法级安全性,允许使用SpEL表达式来定义复杂的权限规则。
  • 业务逻辑: DocumentService 提供了获取文档内容的方法,该方法通过 @PreAuthorize 注解限制访问权限,使用SpEL表达式结合用户的角色和属性。
  • 控制器: DocumentController 提供了一个HTTP GET端点来获取文档内容。

13、安全上下文(Security Context)

业务场景: 一个多租户的SaaS应用程序,需要在每个请求中识别和处理当前认证用户的安全上下文,以确保用户只能访问其租户的数据。

业务时序图
在这里插入图片描述
1.用户(User) 尝试通过浏览器(Browser)访问一个受保护的资源。

2.浏览器(Browser) 向服务器(Server)发送 HTTP 请求

3.服务器(Server) 请求当前的安全上下文( SecurityContextHolder.getContext())。

4.安全上下文持有器(SecurityContextHolder) 提供当前的认证信息。

5.认证(Authentication) 对象检查用户是否有权访问请求的资源。

6.资源(Resource) 根据认证信息返回访问决策。

7.认证(Authentication) 根据需要更新安全上下文。

8.安全上下文持有器(SecurityContextHolder) 返回更新后的安全上下文。

9.服务器(Server) 根据安全上下文返回适当的响应给浏览器。

13.1 Spring Security 配置

首先,我们需要配置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.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@Ena