当前位置: 首页 > news >正文

springboot解析

1. 如何确定某个类如何被加载的

org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition

在该方法打断点,断点条件 beanName.equalsIgnoreCase("oauth2ClientFilterRegistration")

2. tomcat相关的类

tomcat容器:engine  》 host  》  context  》 wrapper,主要是context,表示一个应用

tomcat服务器创建:org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#createWebServer

context添加initializer:org.apache.catalina.core.StandardContext#addServletContainerInitializer

context添加filter:org.apache.catalina.core.ApplicationContext#addFilter(java.lang.String, java.lang.String, javax.servlet.Filter)

初始注册的filter:

"webMvcMetricsFilter" -> {ApplicationFilterRegistration@7490} 
"requestContextFilter" -> {ApplicationFilterRegistration@7492} 
"Tomcat WebSocket (JSR356) Filter" -> {ApplicationFilterRegistration@7494} 
"characterEncodingFilter" -> {ApplicationFilterRegistration@7495} 
"OAuth2ClientContextFilter" -> {ApplicationFilterRegistration@7497} 
"springSecurityFilterChain" -> {ApplicationFilterRegistration@7499} 
"formContentFilter" -> {ApplicationFilterRegistration@7501} 

其中springSecurityFilterChain实际上是在org.springframework.security.web.FilterChainProxy#doFilterInternal中调用自己的过滤器链,其中很多过滤器是在org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter#getHttp中添加的,如csrf、WebAsyncManagerIntegrationFilter、exceptionHandling、headers、sessionManagement等

3. oauth2

未认证的请求进来后FilterSecurityInterceptor代理过滤器会抛出AccessDeniedException,然后ExceptionTranslationFilter捕获到异常并重定向到/login(可以通过security.oauth2.sso.login-path配置),判断一个请求是否认证的方式是判断SecurityContextHolder获取到的Authentication是否为AnonymousAuthenticationToken,如果是的话说明为认证,抛出AccessDeniedException(通过WebExpressionVoter判断,详情如下:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            .antMatchers("/admin/**").access("hasRole('ADMIN')")
            .antMatchers("/user/**").access("hasRole('USER')")
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .and()
            .httpBasic()
            .and()
            .expressionHandler(customWebSecurityExpressionHandler());
    }

    @Bean
    public WebSecurityExpressionHandler customWebSecurityExpressionHandler() {
        DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler();
        handler.setRoleHierarchy(roleHierarchy());
        return handler;
    }

    @Bean
    public RoleHierarchy roleHierarchy() {
        RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
        roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER");
        return roleHierarchy;
    }
}

voter会根据配置的规则:

antMatchers("/admin/**").access("hasRole('ADMIN')")
            .antMatchers("/user/**").access("hasRole('USER')")
            .anyRequest().authenticated()

如access("hasRole('ADMIN')")或 authenticated()其实是access("authenticated"),将字符串作为表达式进行解析,解析的上下文是EvaluationContext,上下文中含有用于解析表达式的具体方法,如对于"authenticated",上下文中有isAuthenticated()方法,即上面讲到的判断Authentication是否为AnonymousAuthenticationToken,对于"hasRole('ADMIN')",上下文也有hasRole方法。

在 Spring Boot 中,可以通过 Spring Security 提供的注解来为方法设置访问权限。这些注解允许你在方法级别进行细粒度的访问控制,确保只有具有相应权限的用户才能调用特定的方法。以下是常用的注解及其使用方法:

### 常用注解
1. **`@PreAuthorize`**  
   在方法执行之前进行权限检查。如果表达式计算结果为 `true`,则允许执行方法;否则,抛出 `AccessDeniedException`。

2. **`@PostAuthorize`**  
   在方法执行之后进行权限检查。如果表达式计算结果为 `true`,则返回方法的结果;否则,抛出 `AccessDeniedException`。

3. **`@Secured`**  
   基于角色的访问控制。可以指定一个或多个角色,只有具有这些角色的用户才能调用该方法。

4. **`@RolesAllowed`**  
   与 `@Secured` 类似,但更简洁,直接指定允许访问的角色。

5. **`@PreFilter` 和 `@PostFilter`**  
   用于对集合或数组进行过滤。`@PreFilter` 在方法执行之前过滤输入数据,`@PostFilter` 在方法执行之后过滤输出数据。

### 示例
假设你有一个服务类 `UserService`,其中包含一些需要权限控制的方法:

```java
@Service
public class UserService {

    @PreAuthorize("hasRole('ADMIN')")
    public void deleteUser(Long userId) {
        // 删除用户逻辑
    }

    @PostAuthorize("returnObject.username == authentication.name")
    public User getUser(Long userId) {
        // 获取用户逻辑
        return new User(userId, "username");
    }

    @Secured("ROLE_USER")
    public void updateUser(User user) {
        // 更新用户逻辑
    }

    @RolesAllowed({"ROLE_USER", "ROLE_ADMIN"})
    public List<User> getAllUsers() {
        // 获取所有用户逻辑
        return Collections.emptyList();
    }

    @PreFilter("filterObject.username.startsWith('a')")
    public List<User> filterUsers(List<User> users) {
        // 返回过滤后的用户列表
        return users;
    }

    @PostFilter("filterObject.username.startsWith('a')")
    public List<User> getAllUsersWithFilter() {
        // 返回所有用户,但只返回用户名以 'a' 开头的用户
        return Collections.emptyList();
    }
}
```

### 配置方法
为了使这些注解生效,你需要在 Spring Security 的配置中启用方法级安全控制。这可以通过在配置类上添加 `@EnableMethodSecurity` 注解来实现:

```java
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            .antMatchers("/admin/**").hasRole("ADMIN")
            .antMatchers("/user/**").hasRole("USER")
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .and()
            .httpBasic();
    }
}
```

### 表达式语言
Spring Security 支持使用 SpEL(Spring Expression Language)来编写复杂的访问控制逻辑。例如:
- **`hasRole('ROLE')`**:检查用户是否具有指定角色。
- **`hasAuthority('AUTHORITY')`**:检查用户是否具有指定权限。
- **`authentication.principal.username`**:获取当前用户的用户名。
- **`#userId == authentication.principal.id`**:检查方法参数 `userId` 是否与当前用户的 ID 匹配。

### 注意事项
1. **启用方法级安全控制**:确保在配置类上添加了 `@EnableMethodSecurity` 注解。
2. **表达式语法**:确保 SpEL 表达式的语法正确,否则可能会导致运行时错误。
3. **性能影响**:方法级安全控制可能会对性能产生一定影响,特别是在高并发场景下。合理使用缓存等技术可以缓解这一问题。

通过这些注解,Spring Boot 提供了灵活且强大的方法级访问控制机制,帮助你实现细粒度的安全策略。

OAuth2ClientAuthenticationProcessingFilter:对请求进行认证,使用ResourceServerTokenServices获取用户信息,并将用户信息设置到SecurityContextHolder,其注册最终可追溯到OAuth2SsoDefaultConfiguration和@EnableOAuth2Sso

OAuth2ClientContextFilter:将请求重定向到sso认证页面

ExceptionTranslationFilter:捕获到AccessDeniedException时,使用AuthenticationEntryPoint将请求重定向到/login(DelegatingAuthenticationEntryPoint,使用@EnableOAuth2Sso时由SsoSecurityConfigurer配置)或者返回401(OAuth2AuthenticationEntryPoint,使用@EnableResourceServer时由ResourceServerSecurityConfigurer配置)

OAuth2AuthenticationProcessingFilter:@EnableResourceServer时的过滤器,提前请求头Authorization或者参数access_token的token获取用户信息

 UserInfoRestTemplateCustomizer:可以通过实现该接口来自定义OAuth2RestTemplate的OAuth2RequestAuthenticator来处理用户信息请求。

相关文章:

  • Ubuntu 下通过 Docker 部署 WordPress 服务器
  • SpringBoot3-web开发笔记(下)
  • Rockchip 显示架构
  • python基础:数据类型转换、运算符(算术运算符、比较运算符、逻辑运算符、三元运算符、位运算符)
  • 【力扣hot100题】(084)零钱兑换
  • Ubuntu24.04装机安装指南
  • Elasticsearch生态
  • C++ 编程指南34 - C++ 中 ABI 不兼容的典型情形
  • cursor+高德MCP:制作一份旅游攻略
  • NModbus 库在 C# 中的使用
  • 深入理解linux操作系统---第4讲 用户、组和密码管理
  • Dify + Stable Diffusion实现文生图工作流【两种方式】
  • ffmpeg 切割视频失败 ffmpeg 命令参数 -vbsf 在新版本中已经被弃用,需要使用 -bsf:v 替代
  • SD+融合ControlNet,扩散模型V1.5+约束条件边缘图+颜色图实现服装图像生成:定量对比试验结果+分析
  • 【测试】-- 测试分类
  • pg_rman备份pg数据库(在备库执行)
  • 权限管控与数据安全:衡石ChatBot在钉钉中的合规部署指南
  • 基于Cline和OpenRouter模型进行MCP实战
  • 通过平台大数据智能引擎及工具,构建设备管理、运行工况监测、故障诊断等应用模型的智慧快消开源了
  • 常见的HTTP状态码有哪些
  • 牛市早报|国家发改委:今年将推出约3万亿元优质项目,支持民营企业参与
  • 经彩申城!上海网络大V沙龙活动走进闵行
  • 昆明阳宗海风景名胜区19口井违规抽取地热水,整改后用自来水代替温泉
  • 加力、攻坚、借力、问效,上海为优化营商环境推出增量举措
  • 习近平《在庆祝中华全国总工会成立100周年暨全国劳动模范和先进工作者表彰大会上的讲话》单行本出版
  • 4月外汇储备增加410亿美元,黄金储备连续6个月增加