权限系统设计方案实践(Spring Security + RBAC 模型)

前言

        权限系统设计基本上是所有项目中都会涉及的一个重要部分。通过权限系统,我们将对用户角色、功能模块访问进行限制,从而保证系统安全性。本文将介绍中大型项目中常用的一套权限系统设计方案,通过 SpringSecurity 安全管理框架,并结合 RBAC 模型进行数据模型设计,可以完成一个较为完整的权限系统。


Spring Security

        Spring Security 是 Spring 中的安全管理框架,Spring Security 为 Java 应用提供了身份认证(Authentication)和访问控制(Authorization)功能。

Spring Security 的核心特点

  • 与 Spring 生态高度集成。

  • 支持丰富的认证方式,可扩展性强。

  • 灵活授权模型,将角色(Role)与权限(Authority)分离。

  • 强大的安全防护。

使用方法

        (使用方法介绍将在实践中进行超详细介绍,请继续阅读)


RBAC

        Role-Based Access Control,RBAC 模型是一种静态权限模型,RBAC 模型为用户添加一个或多个角色类型,通过角色类型这一中间层,将用户和权限解耦,以便于进行权限控制。在 RBAC 模型中,每个角色下面对应着不同的权限组,通过创建不同的角色,将权限进行划分。

RBAC 中的重要角色

  • 用户(User):系统的使用者。

  • 角色(Role):代表一系列权限的集合。

  • 权限(Permission):具体操作的访问能力。

4 级 RBAC 模型

RBAC0

        RBAC 中最基础的模型,只包含定义中的 用户-角色-权限 基本组件。

RBAC1

        角色继承模型,基于 RBAC0 添加层级关系,可以让一个角色继承另一个或一些角色的权限。

        层级关系种类很多,基础的包含:树形结构、网格结构(多继承)。

RBAC2

        约束规则,基于 RBAC0 添加角色的约束关系。

        约束规则包括:角色互斥(两角色不能同时赋给一个用户)、基数约束(角色赋给用户的数量有限)等。

RBAC3

        RBAC 完整模型,结合了 RBAC1 和 RBAC2,同时拥有层级关系和约束规则。

RBAC 模型的优缺点

优点

  • 通过对用户和权限进行解耦,便于进行权限集中控制。

  • 结构性强,通过应用 RBAC1 模型,便于控制层级关系间的权限控制。

缺点

  • 权限颗粒度较粗,根据角色划分而非功能。

  • 角色爆炸(Role Proliferation),因为需求权限颗粒度较细,从而导致创建大量单一权限角色用于单一功能控制导致角色数量暴增。

  • 缺乏灵活性,项目初期定义的角色可能后续不满足项目需求。


基于 Spring Security + RBAC 模型的权限系统设计实践

实践场景说明

        各个系统中均离不开用户管理模块,下面根据用户管理模块中的权限校验系统提出以下需求:

  • 动态分配用户权限,可以选择让用户调用哪些 api。

  • 设定权限集合,简化后续给予同类用户权限操作。

  • 权限高度定制化,可容纳毫无关联的 api 在统一权限集合内。

实践场景解析

        实践场景要求我们基于用户模块去做一套完整的权限校验系统,要求权限可以高度定制化。因此,我们可以考虑采用本文前半节所阐述的技术方案 Spring Security + RBAC 模型。通过使用 Spring Security 进行用户身份认证和权限校验操作,应用 RBAC 模型进行数据模型抽象处理,适应 Spring Security 中对于权限校验的要求。

技术选型

名称

版本

说明

Spring Boot

3.1.5

Spring Boot 主版本

JDK

17

项目使用的 Java 版本

Spring Boot Starter Web

3.1.5

Web 应用支持

Spring Boot Starter Security

3.1.5

安全框架支持

MyBatis-Plus

3.5.4

MyBatis 增强框架

MySQL

8.0.33

MySQL 数据库驱动

Lombok

1.18.28

代码简化工具

Knife4j

4.3.0

API 文档生成工具

JJWT API

0.11.5

JWT 令牌生成与解析

JJWT Impl

0.11.5

JWT 核心实现

JJWT Jackson

0.11.5

JWT 的 JSON 处理支持

实施步骤

1、数据库设计

  • sys_user:用户表,用于存储用户信息。

  • sys_role:角色表,用于存储角色信息。

  • sys_permission:系统权限表,用于存储系统中权限。

  • user_role:用户角色关联表。

  • role_permission:角色权限关联表。

2、编写 Demo 框架

        demo 框架不做详细解释,只介绍包与包下文件作用,后文会对重点代码进行详细解读(详细实现请查看文末源码链接)。

java.djhhh.securityrbacdemo
  • controller(业务控制层)

    • UserController:用于暴露 User 相关接口。

  • mapper(数据访问层)

    • RoleMapper:用于进行 Role 数据访问。

    • UserMapper:用于进行 User 数据访问。

  • service(服务层)

    • impl(实现)

      • UserServiceImpl:用户服务实现。

    • UserService:用户服务接口。

  • model(数据模型)

    • dto(数据传输对象)

      • UserDTO:用于登录数据封装。

    • entity(实体)

      • User:用户实体。

      • Permission:权限实体。

      • Role:角色实体。

    • vo(视图)

      • UserVO:用户视图

      • UserPermissinVO:用户权限视图。

  • result(结果模型)

    • Result:结果类封装,用于全局返回值统一。

    • ResultCodeEnum:结果枚举值。

  • security(安全框架)

    • permissionconstants(权限常量)

      • UserPerssionConstant:用户权限模块

    • JwtAuthenticationFilter:JWT 校验过滤器。

    • SecurityConfig:Spring Security 安全配置类

  • utils(工具)

    • JwtTokenUtil:JWT 工具类。

  • SecurityRbacDemoApplication:项目启动类。

resources
  • application.yml:配置文件。

3、配置文件编写

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/authentication-system-demo?useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: root
    hikari:
      maximum-pool-size: 20
      minimum-idle: 5

  security:
    user:
      name: admin
      password: 123456

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true

springdoc:
  swagger-ui:
    path: /swagger-ui.html
    tags-sorter: alpha
    operations-sorter: alpha
  api-docs:
    path: /v3/api-docs
  default-consumes-media-type: application/json
  default-produces-media-type: application/json

knife4j:
  enable: true
  setting:
    language: zh-CN
    enable-footer: false

jwt:
  secret: pKQzTRvVpla2baIvNh6oWNrBWRuCidWi
  expiration: 216000

4、梳理 Spring Security 实现流程

  1. 实现 User 实体类,让 User 类继承 UserDetails 类,并重写内部方法以便后续 Spring Security 进行权限校验使用。

  2. 实现 UserServcie,让 UserService 类实现 UserDetailsService 类,实现 loadUserByUsername 方法。

  3. 实现 SecurityConfig 配置类,内部实现安全过滤器配置,完成权限校验基本实现。

  4. Spring Security中两个特性:

    1. 用户认证已经通过配置项实现,可以自行进行用户认证授权操作。

    2. 访问控制还未实现,现在用户已经知道自己可以进行什么操作,该步骤应实现访问控制。

5、实现 User 实体类

  • getAuthorities:该方法是 User 中的重点方法,用作获取用户的权限列表。由于本系统采用的模型为 RBAC 模型,所以需要通过在 role 中再拿一次 permission。

  • (其余看注释即可)

@Data
@TableName("sys_user")
public class User implements UserDetails {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String username;
    private String password;
    private Boolean enabled;
    @TableField(exist = false)
    private List<Role> roles;
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return roles.stream()
                .map(Role::getPermissions) // 获取每个角色的权限列表
                .filter(Objects::nonNull) // 过滤掉 permissions 为 null 的角色
                .flatMap(Collection::stream) // 展开所有权限对象
                .filter(Objects::nonNull) // 过滤掉 null 的权限对象
                .map(Permission::getCode) // 提取权限码
                .filter(code -> code != null && !code.isBlank()) // 过滤空权限码
                .map(SimpleGrantedAuthority::new) // 转换为 Spring Security 权限对象
                .collect(Collectors.toList());
    }
    @Override
    public String getPassword() {
        return this.password;
    }
    @Override
    public String getUsername() {
        return this.username;
    }
    /**
     * 用户是否过期
     */
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
    /**
     * 用户是否锁定
     */
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }
    /**
     * 用户凭证是否过期
     */
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    /**
     * 用户是否启用
     */
    @Override
    public boolean isEnabled() {
        return this.enabled;
    }
}

6、实现 UserServcie 服务

  • loadUserByUsername:该方法为 UserService 中重点要实现的方法,该方法是 Spring Security 用户认证的核心实现,负责根据用户名加载用户信息以及关联的角色和权限。

@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    @Resource
    private final UserMapper userMapper;

    @Resource
    private final RoleMapper roleMapper;

    /**
     * UserDetailsService 类的 loadUserByUsername 方法是 Spring Security 用户认证的核心实现。
     * 负责根据用户名加载用户信息及其关联的角色和权限。
     * @param username 用户名
     * @return 用户
     */
    @Override
    public User loadUserByUsername(String username) {
        User user = userMapper.selectOne(
                new LambdaQueryWrapper<User>()
                    .eq(User::getUsername, username)
        );
        if (user == null) throw new UsernameNotFoundException("用户不存在");
        List<Role> roles = userMapper.selectRolesByUserId(user.getId());
        user.setRoles(roles != null ? roles : Collections.emptyList());
        user.getRoles().forEach(role -> {
            List<Permission> permissions = roleMapper.selectPermissionsByRoleId(role.getId());
            role.setPermissions(permissions != null ? permissions : Collections.emptyList());
        });
        return user;
    }

    //(其余代码略...)
}

7、实现 SecurityConfig 配置类

该配置类为该方案的核心,需要仔细研究(代码中含详细注解)。

  • passwordEncoder:用于密码加密。

  • jwtAuthenticationFilter引入 JWT 校验链。

  • filterChain:安全过滤器链配置(该配置项的核心,下面进行详细介绍)。

    • .authorizeHttpRequests请求授权规则配置。

      • .requestMatchers:配置无需认证的白名单。

      • .permitAll():调用后用于通过 requestMatchers 进行的白名单配置

      • .anyRequest().authenticated():声明其余请求要进行权限校验。

    • formLogin:登录配置(示例中使用自定义登录配置,给定配置以提醒此处可用)。

    • logout:登出配置(示例中未实现,扩展中会给出实现思路)。

    • sessionManagement:将 Session 设置为无状态。

    • addFilterBefore(jwtAuthenticationFilter):添加 JWT 校验。

    • expectionHandling:异常处理。

      • authenticationEntryPoint:未认证处理。

      • accessDenieHandler:权限不足处理。

    • cors:跨域配置。

    • csrf:CSRF 防护。

/**
 * Spring Security 安全配置类
 */
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {

    private final JwtTokenUtil jwtTokenUtil;
    private final UserDetailsService userDetailsService;

    @Autowired
    public SecurityConfig(JwtTokenUtil jwtTokenUtil, UserDetailsService userDetailsService) {
        this.jwtTokenUtil = jwtTokenUtil;
        this.userDetailsService = userDetailsService;
    }

    private final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 密码编码器 Bean
     * 使用 BCrypt 强哈希算法加密密码
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * JWT链引入
     * @return
     */
    @Bean
    public JwtAuthenticationFilter jwtAuthenticationFilter() {
        return new JwtAuthenticationFilter(jwtTokenUtil, userDetailsService);
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
        return config.getAuthenticationManager();
    }

    /**
     * 安全过滤器链配置(核心安全规则)
     */
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                //--- 请求授权规则 ---
                .authorizeHttpRequests(auth -> auth
                        // 白名单路径(无需认证)
                        .requestMatchers(
                                "/index.html",
                                "/user/logout",   //注册API
                                "/user/login",   //注册API
                                "/user/register",   //注册API
                                "/doc.html",                // Swagger 文档页
                                "/webjars/**",              // Swagger WebJars 资源
                                "/v3/api-docs/**",         // OpenAPI 文档端点
                                "/swagger-ui/**",           // Swagger UI 资源
                                "/swagger-resources/**",    // Swagger 资源配置
                                "/favicon.ico",             // 网站图标
                                "/login.html",              // 自定义登录页(根据实际路径调整)
                                "/css/**",                  // CSS 静态资源
                                "/js/**"                    // JavaScript 静态资源
                        ).permitAll()
                        // 其他所有请求需要认证
                        .anyRequest().authenticated()
                )

                //--- 表单登录配置 ---
                // 如果不适用JWT的话 可以参照此方案实施
//                .formLogin(form -> form
//                        .defaultSuccessUrl("/index.html")
//                        .loginProcessingUrl("/user/login")    // 表单提交地址
//                        // 登录成功处理(可跳转页面或返回 JSON)
//                        .successHandler((request, response, authentication) -> {
//                            // 示例:返回 JSON 响应(适合前后端分离)
//                            response.setContentType("application/json;charset=UTF-8");
//                            response.getWriter().write(
//                                    objectMapper.writeValueAsString(Result.ok("登录成功"))
//                            );
//                        })
//                        // 登录失败处理
//                        .failureHandler((request, response, exception) -> {
//                            String errorMessage;
//                            if (exception instanceof BadCredentialsException) {
//                                errorMessage = "密码错误";
//                            } else if (exception instanceof UsernameNotFoundException) {
//                                errorMessage = "用户不存在";
//                            } else {
//                                errorMessage = "登录失败";
//                            }
//                            response.setContentType("application/json;charset=UTF-8");
//                            response.setStatus(401);
//                            response.getWriter().write(
//                                    objectMapper.writeValueAsString(Result.fail(401, errorMessage))
//                            );
//                        })
//                        .permitAll()  // 允许所有人访问登录页
//                )

                //--- 注销配置 ---
//                .logout(logout -> logout
//                        .logoutUrl("/user/logout")           // 注销请求地址
//                )

                //--- 会话管理 ---
                .sessionManagement(session -> session
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 无状态
                )

                //--- 添加JWT校验 ---
                .addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)

                //--- 异常处理 ---
                .exceptionHandling(exceptions -> exceptions
                        // 未认证处理(访问需要登录的资源)
                        .authenticationEntryPoint((request, response, ex) -> {
                            response.setContentType("application/json;charset=UTF-8");
                            response.setStatus(401);
                            response.getWriter().write(
                                    objectMapper.writeValueAsString(Result.fail(401, "请先登录"))
                            );
                        })
                        // 权限不足处理
                        .accessDeniedHandler((request, response, ex) -> {
                            response.setContentType("application/json;charset=UTF-8");
                            response.setStatus(403);
                            response.getWriter().write(
                                    objectMapper.writeValueAsString(Result.fail(403, "权限不足"))
                            );
                        })
                )

                //--- CORS 跨域配置(按需启用)---
                .cors(cors -> cors.configurationSource(corsConfigurationSource()))

                //--- CSRF 防护(传统 Web 应用建议启用)---
                .csrf(AbstractHttpConfigurer::disable); // 禁用 CSRF

        return http.build();
    }

    /**
     * CORS 跨域配置(生产环境应缩小范围)
     */
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowedOrigins(List.of("http://localhost:8080")); // 允许的前端地址
        config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE"));
        config.setAllowCredentials(true); // 允许携带 Cookie
        config.setAllowedHeaders(List.of("*"));

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return source;
    }
}

8、访问控制

通过在方法上添加下面示例中的注解,即可进行自动进行访问控制。

(permission替换为你在sys_permissions设定的权限。)

@PreAuthorize("hasAuthority('permission')")

测试

        Demo中引入knife4j用作API文档工具,用此进行测试。

登录

        获取JWT令牌用作认证

获取用户权限列表

        权限通过状态下:

        若无权限状态下:

        (此处测试只进行简单展示,具体还需要自己上手实践才能感受到)

扩展

对权限进行集中管理

        通过对权限进行集中管理,既可以保证之后项目维护起来比较容易,又可以通过使用注解的方式,简化项目中的权限标识。

操作如下:

  1. 通过在sercurity包下创建一个permissionconstants包,用于集中管理权限。

  2. 在permissionconstants包下创建实例中的用户权限类,实现如下:

    // 用户模块
    public final class UserPermissionConstant {
        /**
         * 用户读权限
         */
        @Target(ElementType.METHOD) // 仅用于方法
        @Retention(RetentionPolicy.RUNTIME)
        @PreAuthorize("hasAuthority('user:read')")
        public @interface UserRead {
            String description() default "用户读权限";
        }
        /**
         * 用户写权限
         */
        @Target(ElementType.METHOD)
        @Retention(RetentionPolicy.RUNTIME)
        @PreAuthorize("hasAuthority('user:write')")
        public @interface UserWrite {
            String description() default "用户写权限";
        }
    }
  3. 后续使用的时候只需要通过类似如下注解即可。

@UserPermissionConstant.UserRead

实现登出功能

        JWT本身是无状态的。因此,如果我们想要使登录状态失效(也就是实现登出),本身上也是要违背一部分JWT无状态这一特性的。给出以下实现方案:

  • 通过Redis添加黑名单机制,将登出的JWT存放在Redis中,增强对JWT的验证机制即可实现登出功能。


总结

        本文介绍了一种权限校验的实现方式,通过Spring Security + RBAC模型进行权限系统设计,可以实现大部分应用场景下的权限校验功能。

Demo 代码 GitHub 源地址:https://github.com/Djhhhhhh/security-rbac-demo

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/981724.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数学软件Matlab下载|支持Win+Mac网盘资源分享

如大家所了解的&#xff0c;Matlab与Maple、Mathematica并称为三大数学软件。Matlab应用广泛&#xff0c;常被用于数据分析、无线通信、深度学习、图像处理与计算机视觉、信号处理、量化金融与风险管理、机器人&#xff0c;控制系统等领域。 Matlab将数值分析、矩阵计算、科学…

植物大战僵尸杂交版v3.3最新版本(附下载链接)

B站游戏作者潜艇伟伟迷于12月21日更新了植物大战僵尸杂交版3.3版本&#xff01;&#xff01;&#xff01;&#xff0c;有b站账户的记得要给作者三连关注一下呀&#xff01; 不多废话下载链接放上&#xff1a; 夸克网盘链接&#xff1a;&#xff1a;https://pan.quark.cn/s/6f2a…

GPU、NPU与LPU:大语言模型(LLM)硬件加速器全面对比分析

引言&#xff1a;大语言模型计算基础设施的演进 随着大语言模型&#xff08;LLM&#xff09;的快速发展与广泛应用&#xff0c;高性能计算硬件已成为支撑LLM训练与推理的关键基础设施。目前市场上主要有三类处理器用于加速LLM相关任务&#xff1a;GPU&#xff08;图形处理单元…

计算机网络数据传输探秘:包裹如何在数字世界旅行?

计算机网络数据传输探秘:包裹如何在数字世界旅行? 一、从快递网络看数据传输本质 想象你网购了一件商品: 打包:商家用纸箱包装,贴上地址标签(数据封装)运输:包裹经过网点→分拣中心→运输车(网络节点与链路)签收:快递员核对信息后交付(数据校验与接收)数据的网络…

VirtualBox虚拟机MacOS从Big Sur升级到Sequoia(失败)

VirtualBox虚拟机里安装好Big Sur版本&#xff0c;尝试升级到Sequoia&#xff0c;但是最终失败了。 软件升级 直接在系统偏好-软件更新里可以看到提示&#xff0c;提示可以升级到15版本Sequoia 点击同意&#xff0c;看能不能升级到Sequoia吧。升级前先用时光做了备份。 升级…

从数据到决策,永洪科技助力良信电器“智”领未来

在数字经济浪潮汹涌的时代&#xff0c;数字化转型已成为企业增强竞争力、实现可持续发展的必由之路。良信电器&#xff0c;作为国内知名的电气设备制造企业&#xff0c;积极响应时代号召&#xff0c;携手永洪科技&#xff0c;共同开启了数字化转型的新篇章。 上海良信电器股份有…

dify接入语音转文本模型后报错: microphone not authorized

遇到microphone not authorized莫慌,这是因为没有获取到设备的麦克风权限导致的 解决方法:&#xff08;三种选其一&#xff0c;我实际使用的是第三种&#xff09; 1.将http路径转换成https 2.接入的前端增加获取麦克风权限的功能 3.打开设备麦克风权限:&#xff08;能快速验证…

华为hcia——Datacom实验指南——配置手工模式以太网链路聚合

什么是以太网链路聚合&#xff08;Eth-trunk&#xff09; 是一种将多个物理链路捆绑在一起&#xff0c;让设备以为是一条大链路&#xff0c;能够增加带宽&#xff0c;增加冗余度&#xff0c;提升可靠性&#xff0c;实现负载平衡。 传输方式有两种 基于数据流传输和基于数据包…

【随手笔记】利尔达NB模组

1.名称 移芯EC6263GPP 参数 指令备注 利尔达上电输出 [2025-03-04 10:24:21.379] I_AT_WAIT:i_len2 [2025-03-04 10:24:21.724] LI_AT_WAIT:i_len16 [2025-03-04 10:24:21.724] [2025-03-04 10:24:21.733] Lierda [2025-03-04 10:24:21.733] [2025-03-04 10:24:21.745] OK移…

RNN实现精神分裂症患者诊断(pytorch)

RNN理论知识 RNN&#xff08;Recurrent Neural Network&#xff0c;循环神经网络&#xff09; 是一种 专门用于处理序列数据&#xff08;如时间序列、文本、语音、视频等&#xff09;的神经网络。与普通的前馈神经网络&#xff08;如 MLP、CNN&#xff09;不同&#xff0c;RNN…

阿里万相,正式开源

大家好&#xff0c;我是小悟。 阿里万相正式开源啦。这就像是AI界突然开启了一扇通往宝藏的大门&#xff0c;而且还是免费向所有人敞开的那种。 你想想看&#xff0c;在这个科技飞速发展的时代&#xff0c;AI就像是拥有神奇魔法的魔法师&#xff0c;不断地给我们带来各种意想…

json介绍、python数据和json数据的相互转换

目录 一 json介绍 json是什么&#xff1f; 用处 Json 和 XML 对比 各语言对Json的支持情况 Json规范详解 二 python数据和json数据的相互转换 dumps() : 转换成json loads(): 转换成python数据 总结 一 json介绍 json是什么&#xff1f; 实质上是一条字符串 是一种…

250301-OpenWebUI配置DeepSeek-火山方舟+硅基流动+联网搜索+推理显示

A. 最终效果 B. 火山方舟配置&#xff08;一定要点击添加&#xff09; C. 硅基流动配置&#xff08;最好要点击添加&#xff0c;否则会自动弹出所有模型&#xff09; D. 联网搜索配置 E. 推理过程显示 默认是没有下面的推理过程的显示的 F. SearXNG配置 注意&#xff1a;此…

Linux中死锁问题的探讨

在 Linux 中&#xff0c;死锁&#xff08;Deadlock&#xff09; 是指多个进程或线程因为竞争资源而相互等待&#xff0c;导致所有相关进程或线程都无法继续执行的状态。死锁是一种严重的系统问题&#xff0c;会导致系统资源浪费&#xff0c;甚至系统崩溃。 死锁的定义 死锁是指…

【Go】Go viper 配置模块

1. 配置相关概念 在项目开发过程中&#xff0c;一旦涉及到与第三方中间件打交道就不可避免的需要填写一些配置信息&#xff0c;例如 MySQL 的连接信息、Redis 的连接信息。如果这些配置都采用硬编码的方式无疑是一种不优雅的做法&#xff0c;有以下缺陷&#xff1a; 不同环境…

ffmpeg源码编译支持cuda

1.安装cuda CUDA Toolkit 11.3 Downloads | NVIDIA Developer 在选择组件的时候&#xff0c;将CUDA中的Nsight VSE和Visual Studio Integration取消勾选 不然会安装失败 2.编译ffmpeg 把cuda编译宏定义开启&#xff0c;再编译avcodec 3.编译livavutil报错struct "Cuda…

DELL EMC Unity存储如何让控制器进入service mode和退出service mode

近期遇到好几个关于DELL EMC unity &#xff08;VNXe&#xff09;存储系统挂掉的案例&#xff0c;都是很后期才寻找支持到我们这里&#xff0c;然后再看问题&#xff0c;已经变得很复杂&#xff0c;几乎都是从一个相对简单的问题搞成了一锅粥甚至最后丢数据的情况。 为此&…

金蝶ERP星空对接流程

1.金蝶ERP星空OPENAPI地址&#xff1a; 金蝶云星空开放平台 2.下载金蝶云星空的对应SDK包 金蝶云星空开放平台 3.引入SDK流程步骤 引入Kingdee.CDP.WebApi.SDK 右键项目添加引用&#xff0c;在打开的引用管理器中选择浏览页签&#xff0c;点击浏览按钮&#xff0c;找到从官…

深入探索像ChatGPT这样的大语言模型-03-POST-Training:Reinforcement Learning

参考 【必看珍藏】2月6日&#xff0c;安德烈卡帕西最新AI普及课&#xff1a;深入探索像ChatGPT这样的大语言模型&#xff5c;Andrej Karpathy fineweb知乎翻译介绍 fineweb-v1原始连接 fineweb中文翻译版本 Chinese Fineweb Edu数据集 查看网络的内部结果&#xff0c;可以参…

以影像技术重构智能座舱体验,开启驾乘互动新纪元

在汽车智能化浪潮席卷全球的今天&#xff0c;座舱体验早已突破传统驾驶功能的边界&#xff0c;成为车企竞争的核心赛道。美摄科技凭借其在图像处理与AI算法领域的深厚积累&#xff0c;推出全链路智能汽车图像及视频处理方案&#xff0c;以创新技术重新定义车载影像系统&#xf…