Linux 安全 - Capabilities机制
文章目录
- 前言
- 一、简介
- 二、Capabilities list
- 2.1 POSIX-draft defined capabilities
- 2.2 Linux-specific capabilities
- 三、 Past and current implementation
- 四、Thread capability sets
- 五、File capabilities
- 六、Transformation of capabilities during execve()
- 七、Capabilities and execution of programs by root
- 八、Capability bounding set
- 九、Effect of user ID changes on capabilities
- 十、 Programmatically adjusting capability sets
- 参考资料
前言
在这两篇文章中介绍了 Linux 安全机制 Credentials :Linux 安全 - Credentials,以及 Linux 安全 - SUID机制。
接下来我们详细介绍Capabilities,在介绍Capabilities之前先简单的和SUID机制对比一下:
在Linux中,除了SUID权限之外,还有一种更为细粒度的权限控制机制,称为Capabilities(能力)。Capabilities提供了对特定操作或系统资源的更细粒度的权限控制,以允许用户或进程执行特定的特权操作,而无需完全提升到超级用户(root)权限。
SUID权限和Capabilities的主要区别在于权限的粒度和授予权限的方式:
(1)SUID权限:SUID权限是应用于可执行文件的一种特殊权限位,允许普通用户在执行该文件时以文件所有者的权限运行。这意味着用户可以临时获得与文件所有者相同的权限级别,从而执行一些需要特权的操作。然而,SUID权限的授予是基于文件的整体权限,而不是基于特定操作。
(2)Capabilities:Capabilities是一种更细粒度的权限控制机制,它允许进程在不完全提升到超级用户权限的情况下执行特定的特权操作。相比于SUID权限,Capabilities允许对特定的系统功能或资源进行更细粒度的控制,而不必完全获得文件所有者的权限。例如,某些操作可能需要访问网络套接字、执行系统管理任务、挂载文件系统等。使用Capabilities,可以授予进程仅限于执行这些特定操作所需的权限,而不必提升到完全的超级用户权限。这使得权限控制更加细致,并可以减少潜在的安全风险。
SUID权限是一个文件级别的权限机制,允许以文件所有者的权限执行文件。而Capabilities是一种更细粒度的权限机制,允许进程在不完全提升到超级用户权限的情况下执行特定的特权操作。两者都提供了在普通用户环境下执行特权操作的机制,但Capabilities提供了更灵活和细粒度的权限控制。
一、简介
NAMEcapabilities - overview of Linux capabilities
为了进行权限检查,传统的UNIX实现将进程分为两类:特权进程(有效用户ID为0,也称为超级用户或root)和非特权进程(有效用户ID非零)。特权进程可以绕过所有内核权限检查,而非特权进程则需根据进程的凭据(通常是有效用户ID、有效组ID和附加组列表)进行完整的权限检查。
从内核2.2版本开始,Linux将传统上与超级用户相关联的特权分为不同的单元,称为能力(capabilities),这些能力可以独立地启用和禁用。能力是每个线程的属性。
在Linux中,能力提供了一种细粒度的权限控制机制。传统上,超级用户拥有完整的系统权限,但在使用能力的情况下,特权可以分解为多个单独的能力,每个能力都代表一项特定的权限。通过启用或禁用不同的能力,可以以更细粒度的方式控制进程的特权。这样可以提高系统的安全性,使特权进程只具有执行特定任务所需的必要权限,而非特权进程则受到更严格的权限检查。
需要注意的是,能力是线程级别的属性,因此不同线程可以具有不同的能力配置。它们可以通过使用prctl系统调用来设置和修改。能力的使用在Linux系统中提供了一种更灵活和精细的权限管理机制。
通俗来一点说就是:传统UNIX系统中控制进程的权限,要么是高权限的 root 用户,要么是一般权限的普通用户,这时候的问题是,root 用户权限太大,而普通用户权限太小。有时候一个普通用户想做一点高权限的事情,必须给他整个 root 的权限。这个太不安全了。
对于普通用户运行的进程,当有某个权限(权限请参考:Capabilities list)的时候,就能做这些操作;没有的时候,就不能做,这样粒度要小很多。
二、Capabilities list
以下列表显示了在Linux上实现的 capabilities ,以及每个 capabilities 允许的操作或行为:
2.1 POSIX-draft defined capabilities
CAP_CHOWN:允许覆盖更改文件所有者和组所有者的限制。
CAP_DAC_OVERRIDE:允许覆盖所有DAC(自主访问控制)访问限制,包括ACL(访问控制列表)的执行访问控制。
CAP_DAC_READ_SEARCH:允许覆盖对文件和目录的读取和搜索操作的所有限制。
CAP_FOWNER:允许覆盖对文件所有者ID必须等于用户ID的操作的限制。
CAP_FSETID:允许覆盖对文件设置S_ISUID和S_ISGID位的限制。
CAP_KILL:允许覆盖发送信号的进程的实际或有效用户ID必须与接收信号的进程的实际或有效用户ID相匹配的限制。
CAP_SETGID:允许操作组ID设置。
CAP_SETUID:允许操作用户ID设置。
更详细请参考 man Capabilities 和 文件:
linux-5.4.18/include/uapi/linux/capability.h
2.2 Linux-specific capabilities
CAP_SETPCAP:允许修改进程的能力。
CAP_LINUX_IMMUTABLE:允许修改文件属性S_IMMUTABLE和S_APPEND。
CAP_NET_BIND_SERVICE:允许绑定到低于1024的TCP/UDP套接字。
CAP_NET_BROADCAST:允许广播和监听多播。
CAP_NET_ADMIN:允许接口配置、管理IP防火墙和路由表、设置套接字的调试选项等。
CAP_NET_RAW:允许使用RAW和PACKET套接字。
CAP_IPC_LOCK:允许锁定共享内存段和mlock/mlockall调用。
CAP_IPC_OWNER:覆盖IPC所有权检查。
CAP_SYS_MODULE:允许插入和删除内核模块。
CAP_SYS_RAWIO:允许原始I/O访问和向任何设备发送USB消息。
CAP_SYS_CHROOT:允许使用chroot()。
CAP_SYS_PTRACE:允许对任何进程进行ptrace()。
CAP_SYS_PACCT:允许配置进程账户。
CAP_SYS_ADMIN:允许各种管理任务,如挂载/卸载、访问设备特定功能等。
CAP_SYS_BOOT:允许使用reboot()。
CAP_SYS_NICE:允许提高其他进程的优先级和设置优先级。
CAP_SYS_RESOURCE:允许覆盖资源限制和配额限制,修改数据日志模式等。
CAP_SYS_TIME:允许配置系统时钟和设置实时时钟。
CAP_SYS_TTY_CONFIG:允许配置tty设备和vhangup()tty。
CAP_MKNOD:允许特权方面的mknod()。
CAP_LEASE:允许对文件进行租约。
CAP_AUDIT_WRITE:允许通过单播netlink套接字写入审计日志。
CAP_AUDIT_CONTROL:允许通过单播netlink套接字配置审计。
CAP_SETFCAP:允许设置文件能力。
CAP_MAC_OVERRIDE:覆盖MAC(强制访问控制)访问。
CAP_MAC_ADMIN:允许MAC配置或状态更改。
CAP_SYSLOG:允许配置内核的系统日志。
CAP_WAKE_ALARM:允许触发将唤醒系统的事件。
CAP_BLOCK_SUSPEND:允许阻止系统挂起。
CAP_AUDIT_READ:允许通过多播netlink套接字读取审计日志。
更详细请参考 man Capabilities 和 文件:
linux-5.4.18/include/uapi/linux/capability.h
三、 Past and current implementation
完整的能力实现需要满足以下条件:
(1)对于所有特权操作,内核必须检查线程是否在其有效能力集中具有所需的能力。
(2)内核必须提供系统调用,允许更改和检索线程的能力集。
(3)文件系统必须支持将能力附加到可执行文件,以便在执行文件时进程获取这些能力。
四、Thread capability sets
每个线程都有以下 capability sets ,包含零个或多个上述的 capabilities :
struct cred {kernel_cap_t cap_inheritable; /* caps our children can inherit */kernel_cap_t cap_permitted; /* caps we're permitted */kernel_cap_t cap_effective; /* caps we can actually use */kernel_cap_t cap_bset; /* capability bounding set */kernel_cap_t cap_ambient; /* Ambient capability set */
}
(1)Permitted:该权限集合是线程可以使用的权限的上限。它定义了线程能够拥有的最大权限。如果线程从允许的权限集合中删除了某个权限,那么除非它执行一个具有相应文件权限的程序,否则它将无法重新获取该权限。
(2)Inheritable:该权限集合中包含了在执行execve()系统调用时会保留的权限。可继承的权限在执行任何程序时都会被保留,并且如果某个程序的文件可继承权限集合中相应的位被设置了,那么这些权限将被添加到允许的权限集合中。然而,可继承的权限通常在以非root用户身份运行时不会被保留,因此需要以提升的权限运行辅助程序的应用程序应考虑使用环境权限(下面介绍)。
简而言之:cap_inheritable 表示当可执行文件的扩展属性设置了 inheritable 位时,调用 exec 执行该程序会继承调用者的 inheritable 集合,并将其加入到 permitted 集合。但在非 root 用户下执行 exec 时,通常不会保留 inheritable 集合,但是往往又是非 root 用户,才想保留权限,所以Inheritable没有什么作用,因此在Linux 4.3版本引入Ambient位。
(3)Effective:该权限集合包含了内核用于对线程进行权限检查的权限。内核会检查生效的权限集合,以确定线程是否被允许执行特定的特权操作。
(4)Bounding:capability bounding set 是一种机制,可用于限制execve()期间获取的能力。自Linux 2.6.25起,这是一个每个线程的能力集。在旧内核中,能力边界集是一个系统范围的属性,由系统上的所有线程共享。有关能力边界集的更多细节,请参考:Capability bounding set 这一章节。
(5)Ambient(自Linux 4.3版本引入):该权限集合包含了在执行非特权程序的execve()调用时会保留的权限。环境权限集合遵循一个原则,即只有同时在允许的和可继承的权限集合中的权限才能成为环境权限。可以使用prctl()系统调用直接修改环境权限集合。如果对应的允许的或可继承的权限被降低,环境权限也会被自动降低。当执行改变用户或组ID的程序(由于设置了set-user-ID或set-group-ID位)或具有设置了文件权限的程序时,环境权限集合会被清除。在执行execve()时,环境权限会被添加到允许的权限集合中,并赋予生效的权限集合。
“ambient"掩码的作用是满足大多数人对"inheritable”(可继承)掩码的期望。如果某个能力位在"inheritable"和"permitted"中没有设置,那么它永远也不会在"ambient"中设置。
如果你是非root用户但具有某种能力,你可以将其添加到"ambient"中。如果这样做,你的子进程将在"ambient"、"permitted"和"effective"中获得该能力。例如,你可以在"ambient"中设置CAP_NET_BIND_SERVICE,这样你的子进程就可以自动绑定低端口号。非特权用户可以创建用户命名空间,将自己映射到非零UID,并创建特权(相对于其命名空间而言)和非特权进程树。
通过fork()创建的子进程会继承其父进程的权限集合的副本。关于在execve()期间权限的处理,请参见:Transformation of capabilities during execve()。
使用capset(),线程可以操作自己的权限集合(请参见下面的说明)。
自Linux 3.2版本以来,文件/proc/sys/kernel/cap_last_cap公开了运行内核支持的最高权限的数值;这可以用于确定权限集合中可以设置的最高位。
# uname -r
3.10.0-1160.el7.x86_64
# cat /proc/sys/kernel/cap_last_cap
36
五、File capabilities
自内核版本2.6.24以来,内核支持使用setcap()将权限集合与可执行文件关联起来。文件权限集合存储在一个名为security.capability的扩展属性中(参见setxattr())。要写入该扩展属性,需要具有CAP_SETFCAP权限。文件权限集合与线程的权限集合一起确定了execve()后线程的权限。
文件权限集合分为三种:
(1)Permitted(以前称为 forced 的):无论线程的可继承权限如何,这些权限都会自动授予线程。
(2)Inheritable(以前称为 allowed 的):将此集合与线程的可继承集合进行逻辑与操作,确定在execve()后线程的允许集合中启用了哪些可继承权限。
(3)Effective:这不是一个集合,而只是一个单独的位。如果设置了该位,在execve()期间,线程的所有新允许的权限也会在生效集合中提升。如果未设置该位,在execve()之后,新的允许权限都不会出现在新的生效集合中。
启用文件的生效权限位意味着任何导致线程在execve()期间获取相应允许权限的文件允许或可继承权限(参见下面描述的转换规则),在其生效集合中也会获取该权限。因此,当为文件分配权限(使用setcap()、cap_set_file()、cap_set_fd())时,如果我们指定了任何权限的生效标志为启用状态,则对于所有其他启用了相应允许或可继承标志的权限,也必须指定生效标志为启用状态。
六、Transformation of capabilities during execve()
在execve()期间,内核使用以下算法计算进程的新权限:
P'(ambient) = (file is privileged) ? 0 : P(ambient)P'(permitted) = (P(inheritable) & F(inheritable)) |(F(permitted) & cap_bset) | P'(ambient)P'(effective) = F(effective) ? P'(permitted) : P'(ambient)P'(inheritable) = P(inheritable) [i.e., unchanged]
其中:
P表示`execve(2)`之前线程的权限集合的值P'表示`execve(2)`之后的权限集合的值F表示文件的权限集合cap_bset是权限限制集合的值(下面描述)
特权文件是具有权限或设置了set-user-ID或set-group-ID位的文件。
解释说明:
P’(ambient):如果文件是特权文件,则设置为0,否则设置为P(ambient)的值。P(ambient)是execve()之前线程的环境权限集合。
P’(permitted):通过将P(inheritable)和F(inheritable)进行逻辑与操作,将可继承权限与文件的可继承权限进行逻辑与操作。然后,通过将F(permitted)和cap_bset进行逻辑与操作,将文件的允许权限与权限限制集合进行逻辑与操作。最后,将上述结果与P’(ambient)进行逻辑或操作,得到新的允许权限集合。
P’(effective):如果文件的生效权限位(F(effective))被设置,则P’(effective)等于P’(permitted);否则,P’(effective)等于P’(ambient)。
P’(inheritable):保持不变,即等于P(inheritable),即execve()之前线程的可继承权限集合。
七、Capabilities and execution of programs by root
当进程执行具有设置了set-user-ID-root(SUID)权限的程序,或者有效用户ID为0(即root)的进程执行程序时,权限处理遵循特定的规则,使用权限集合提供全能的root权限语义:
(1)文件的可继承和允许权限集合:如果正在执行的程序具有SUID权限或者进程的真实用户ID为0(即root),则文件的可继承和允许权限集合被设置为全1,表示启用了所有权限。这允许进程继承并拥有文件定义的所有权限。
(2)文件的生效权限位:如果正在执行的程序具有SUID权限,则文件的生效权限位被设置为1,表示新的允许权限也会在生效集合中提升。这确保进程获得文件定义的生效权限。
通过将这些规则与之前描述的权限转换相结合,结果是当进程执行SUID-root程序或有效UID为0的进程执行程序时,它会获取其允许和生效权限集合中的所有权限,除了被权限限制集合屏蔽的权限。权限限制集合充当了可以获取的权限的限制或屏蔽。
这些规则提供了与传统UNIX系统相同的语义,在传统UNIX系统中,root用户具有完全的权限,当执行特权程序时,所有与root用户相关的权限都会被授予。
值得注意的是,使用权限集合相比传统的二进制root/non-root区分提供了更精细和灵活的特权管理方法。它允许对授予进程的权限进行更细粒度的控制,通过限制特权用户执行的各个程序的权限,增强了安全性。
八、Capability bounding set
权限限制集合(capability bounding set)是Linux中的一种安全机制,用于限制进程在执行execve()系统调用时获取的权限和特权。它通过限制进程执行新程序时可以获取的能力集,来限制进程所能获得的特权。
权限限制集合的使用方式如下:
(1)在execve()期间,权限限制集合与文件的允许权限集合进行按位与运算,并将运算结果赋值给线程的允许权限集合。因此,权限限制集合限制了可执行文件可能被授予的允许权限。
(2)(自Linux 2.6.25起)权限限制集合作为一个限制的超集,限制了线程可以使用capset()将哪些权限添加到其可继承权限集合中。这意味着,如果一个权限不在限制集合中,线程就无法将该权限添加到其可继承权限集合中,即使它在其允许的权限中,也无法在execve()执行具有该权限在其可继承权限集合中的文件时保留该权限在其允许权限集合中。
权限限制集合的主要作用是减少潜在的安全风险,防止未经授权的访问或滥用特权操作。
权限限制集合的功能依赖于内核的配置。如果内核编译时启用了文件权限功能,那么权限限制集合可以用于删除特权。如果未启用文件权限功能,权限限制集合仍然存在,但只能屏蔽CAP_SETPCAP特权。
在Linux 2.6.25及以上的内核版本中,权限限制集合是线程级别的属性。在fork()系统调用期间,线程会从父线程继承权限限制集合,并在execve()调用时保持不变。可以通过prctl()系统调用以及相应的操作来修改权限限制集合。例如,可以使用PR_CAPBSET_DROP操作从权限限制集合中删除特权。
在执行execve()系统调用时,权限限制集合中的特权与文件的允许特权进行交集运算。运算结果成为进程的允许特权集合。这样可以确保进程获取的特权不会超出权限限制集合所允许的范围。
权限限制集合不会影响进程继承的特权集合。如果一个特权在继承的集合中存在但不在权限限制集合中,仍然可以通过执行继承集合中包含该特权的文件来获得该特权。
需要注意的是,一旦特权从权限限制集合中删除,就无法重新添加该特权。权限限制集合是单向限制,无法逆转。
通过仔细配置和管理权限限制集合,系统管理员可以实施更严格的安全策略,控制进程所获得的特权。这有助于减少系统的攻击面,最小化被入侵进程的潜在影响。
九、Effect of user ID changes on capabilities
用户ID的更改对能力(capabilities)的影响如下:
(1)能力清除:当从一个或多个实际(real)、有效(effective)或保存(saved)用户ID为0的情况过渡到所有这些ID都为非零值的情况时,所有能力将从允许(permitted)和有效能力集中清除。这确保在进程的特权状态发生变化时,与根用户(UID 0)相关的能力不会被保留。
(2)有效能力集清除:如果将有效用户ID从0(root)更改为非零值,则所有能力将从有效能力集中清除。这样做可以防止在有效用户ID更改为普通用户时保留与根用户相关的任何能力。
(3)允许能力集复制:如果将有效用户ID从非零值更改为0(root),允许能力集将被复制到有效能力集中。这意味着即使以特权状态运行,进程只能使用显式允许的能力。
(4)文件系统用户ID变更:当文件系统用户ID(FSUID)从0更改为非零值时,与文件系统操作相关的某些能力将从有效能力集中清除。这些能力包括CAP_CHOWN、CAP_DAC_OVERRIDE、CAP_DAC_READ_SEARCH、CAP_FOWNER、CAP_FSETID、CAP_LINUX_IMMUTABLE、CAP_MAC_OVERRIDE和CAP_MKNOD。相反,如果FSUID从非零值更改为0,则在允许能力集中启用的任何这些能力都将在有效能力集中启用,允许进程在操作文件系统时运用这些能力。
(5)PR_SET_KEEPCAPS:如果线程希望在将所有用户ID重置为非零值时防止其允许能力集被清除,可以使用prctl()系统调用中的PR_SET_KEEPCAPS操作。这允许进程在从特权状态(UID 0)过渡到普通用户状态时保留其能力。
这些机制确保根据用户ID的变化调整能力,保持系统的安全性和特权分离。它们有助于防止进程保留不必要的特权,并减少特权提升攻击的潜在影响。
十、 Programmatically adjusting capability sets
可以通过使用capget()和capset()系统调用来检索和更改线程的能力集。然而,为此目的,推荐使用libcap软件包提供的cap_get_proc()和cap_set_proc()函数。以下规则适用于对线程能力集的更改:
(1)如果调用者没有CAP_SETPCAP能力,则新的可继承能力集必须是现有可继承能力集和可允许能力集的组合的子集。换句话说,调用者只能在现有可继承能力集和可允许能力集的基础上添加或保留能力。
(2)(自Linux 2.6.25起)新的可继承能力集必须是现有可继承能力集和能力边界集的组合的子集。能力边界集是一个系统范围的能力集,限制了任何进程可以拥有的最大能力。
(3)新的可允许能力集必须是现有可允许能力集的子集。也就是说,线程无法获取当前没有的可允许能力。可允许能力集表示线程当前可以获得的最大能力。
(4)新的有效能力集必须是新的可允许能力集的子集。有效能力集表示当前线程正在使用的能力。通过设置有效能力集,线程可以根据需要激活或禁用特定的能力。
参考资料
https://cloud.tencent.com/developer/article/1529342
相关文章:
Linux 安全 - Capabilities机制
文章目录 前言一、简介二、Capabilities list2.1 POSIX-draft defined capabilities2.2 Linux-specific capabilities 三、 Past and current implementation四、Thread capability sets五、File capabilities六、Transformation of capabilities during execve()七、Capabilit…...
分布式搜索引擎es-3
文章目录 数据聚合聚合的种类RestAPI实现聚合 数据聚合 什么是聚合? 聚合可以让我们极其方便的实现对数据的统计、分析、运算。例如: 什么品牌的手机最受欢迎?这些手机的平均价格、最高价格、最低价格?这些手机每月的销售情况如…...
Matlab坐标轴标签中文设置宋体
对y坐标输出中文宋体 新罗马字符 x[1,2,3,4,5,6,7]; plot(x) ylabel(\fontname{宋体}\fontsize{20}长度\fontname{Times New Roman}\fontsize{10} (μm))可以灵活设置字体和大小,其图片如下图所示 也可以对全图的文字设置同一个字体 set(gca,FontSize,9,Fontname, Times New…...
做一个贪吃蛇小游戏happy一下
直接Vue上代码 <template><div><div>贪吃蛇</div><canvas id"canvas" width"400" height"400"></canvas></div> </template><script> export default {data() {return {ctx: null,inter…...
opencv形态学-膨胀
opencv形态学-膨胀 膨胀就是取每一个位置结构元邻域内最大值作为该位置的输出灰度值; 膨胀是取邻域内最大值,那么显然膨胀后图像整体亮度会比原先要高,图像中亮的物体尺寸会变大,相反暗的尺寸会减小,甚至是消失 结构元…...
玄子Share 设计模式 GOF 全23种 + 七大设计原则
玄子Share 设计模式 GOF 全23种 七大设计原则 前言: 此文主要内容为 面向对象七大设计原则(OOD Principle)GOF(Gang Of Four)23种设计模式拓展的两个设计模式 简单工厂模式(Simple Factory Pattern&#x…...
单链表操作 C实现
struct LNode { //定义一个节点 int data; //数据域 struct LNode *next; //指针域 }; 0.初始化 typedef sturct LNode{ //定义单链表结点类型 int date ; //每个结点存放一个数据元素struct LNode *next; //指针指向下…...
WordPress主题网站首页添加好看的四格小工具教程
直接到网站根目录创建一个css文件(文件名:sige.css),文件名可自定义(注意文件名一致) <link rel"stylesheet" href"你的网站/sige.css" type"text/css" > 然后在header.php模板最上方添加引入代码 也可自定义HTML里添加css代码最上方写…...
unittest自动化测试框架讲解以及实战
为什么要学习unittest 按照测试阶段来划分,可以将测试分为单元测试、集成测试、系统测试和验收测试。单元测试是指对软件中的最小可测试单元在与程序其他部分相隔离的情况下进行检查和验证的工作,通常指函数或者类,一般是开发完成的。 单元…...
数学建模之Matlab基础操作
作者由于后续课程也要学习Matlab,并且之前也进行了一些数学建模的练习(虽然是论文手),所以花了几天零碎时间学习Matlab的基础操作,特此整理。 基本运算 a55 %加法,同理减法 b2^3 %立方 c5*2 %乘法 x 1; …...
【Nuxt】04 Nuxt2-SEO: sitemap.xml、seo优化、robots.txt
1 SiteMap设置 环境准备 注意生成sitemap依赖于nuxtjs/sitemap,并且需要用axios进行请求,不要使用nuxtjs/axios,不然会报错 sitemap.xml配置 在nuxt.config.js中配置下面的内容 npm install nuxtjs/sitemap npm install axios在static/s…...
VMware VSAN 入门
一、虚拟化的存储 1.1、对于数据中心来说最重要的是数据,而承载数据的设备就是存储设备(Storage) 1.2、物理服务器的本地存储阵列 与 虚拟化服务器的本地存储阵列 对比 1.3、避免单台服务器故障的虚拟化高级特性:vSphere HA技术 …...
【设计模式】备忘录模式
文章目录 1.备忘录模式定义2.备忘录模式的角色3.备忘录模式实现3.1.场景说明3.2.结构类图3.3.代码实现 4.备忘录模式优缺点5.备忘录模式适用场景6.备忘录模式总结 主页传送门:💁 传送 1.备忘录模式定义 备忘录(Memento Pattern)模…...
vue3+elementUiPlus表格导出功能
1.下载需要的组件包 npm install file-saver xlsx 2.页面中导入 import FileSaver from file-saver import * as XLSX from xlsx; 3.页面中的表格加一个id <el-table :data"tableData" ref"multipleTableRef" style"width…...
专题五:优先级队列
"你了解我,最干净的轮廓, 握住小小风车和放肆的梦~" 堆是一个不错的数据结构,而在计算机中,无法表示二叉分支结构,因此我们经常会看到使用线性表来作为堆的存储容器。在接触堆的时候,我们是把它…...
游戏设计模式专栏(一):工厂方法模式
引言 大家好,我是亿元程序员,一位有着8年游戏行业经验的主程。 本系列是《和8年游戏主程一起学习设计模式》,让糟糕的代码在潜移默化中升华,欢迎大家关注分享收藏订阅。 在游戏开发中,代码的组织和结构对于项目的可…...
element中使用el-steps 进度条效果demo(整理)
<template><div class"margin-top20"><!-- align-center 不要居中就去掉 --><!-- process-status 这几个参数值:改变颜色 wait / process / finish / error / --><!-- active 到第几个是绿色 --><el-steps :space&qu…...
038:mapboxGL 旋转地图(rotateTo)
第038个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中旋转地图。 直接复制下面的 vue+mapbox源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源代码(共68行)相关API参考:专栏目标示例效果 配置方式 1)查看基础设置:https://xiaozhuan…...
java遇到的问题
java遇到的问题 Tomcat与JDK版本问题 当使用Tomcat10的版本用于springmvc借用浏览器调试时,使用JDK8浏览器会报异常。 需要JDK17(可以配置多个JDK环境,切换使用)才可以使用,配置为JAVA_HOME路径,否则&a…...
LLM(二)| LIMA:在1k高质量数据上微调LLaMA1-65B,性能超越ChatGPT
本文将介绍在Lit-GPT上使用LoRA微调LLaMA模型,并介绍如何自定义数据集进行微调其他开源LLM 监督指令微调(Supervised Instruction Finetuning) 什么是监督指令微调?为什么关注它? 目前大部分LLM都是decoder-only&…...
Android AMS——创建Application(七)
与在 App 内部启动一个 Activity 的不同之处在于,点击桌面 Launcher 首次启动一个应用程序的时候,会先去创建一个该应用程序对应的进程,然后执行 ActivityThread 的 main() 方法去创建该应用对应的 Application,然后再去启动首页 Activity。前面已经分析了进程的创建和启动…...
html 边缘融合加载
html 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>边缘融合加载</title><style>* {margin: 0;padding: 0;box-sizing: border-box;}body {height: 100vh;padding-bottom: 80px;b…...
ElasticSearch - 在 微服务项目 中基于 RabbitMQ 实现 ES 和 MySQL 数据异步同步(考点)
目录 一、数据同步 1.1、什么是数据同步 1.2、解决数据同步面临的问题 1.3、解决办法 1.3.1、同步调用 1.3.2、异步通知(推荐) 1.3.3、监听 binlog 1.3、基于 RabbitMQ 实现数据同步 1.3.1、需求 1.3.2、在“酒店搜索服务”中 声明 exchange、…...
Springboot+vue的企业人事管理系统(有报告),Javaee项目,springboot vue前后端分离项目。
演示视频: Springbootvue的企业人事管理系统(有报告),Javaee项目,springboot vue前后端分离项目。 项目介绍: 本文设计了一个基于Springbootvue的前后端分离的企业人事管理系统,采用M(model&am…...
初识Java 11-1 函数式编程
目录 旧方式与新方式 lambda表达式 方法引用 Runnable 未绑定方法引用 构造器方法引用 函数式接口 带有更多参数的函数式接口 解决缺乏基本类型函数式接口的问题 本笔记参考自: 《On Java 中文版》 函数式编程语言的一个特点就是其处理代码片段的简易性&am…...
【Ambari】银河麒麟V10 ARM64架构_安装Ambari2.7.6HDP3.3.1问题总结
🍁 博主 "开着拖拉机回家"带您 Go to New World.✨🍁 🦄 个人主页——🎐开着拖拉机回家_大数据运维-CSDN博客 🎐✨🍁 🪁🍁 希望本文能够给您带来一定的帮助🌸文…...
李宏毅机器学习第一课(结尾附作业模型详细分析)
机器学习就是让机器找一个函数f,这个函数f是通过计算机找出来的 如果参数少的话,我们可以使用暴搜,但是如果参数特别多的话,我们就要使用Gradient Descent Regression (输出的是一个scalar数值) Classification (在…...
对日项目工作总结
从18年8月到23年中秋节,目前已经入职主营对日车载项目的公司满5年了,一般来说,在一家公司工作工作超过3年,如果是在比较大型以及流程规范的公司,那么该公司的工作流程,工作思维会深深地烙印在该员工的脑海中…...
设计模式探索:从理论到实践的编码示例 (软件设计师笔记)
😀前言 设计模式,作为软件工程领域的核心概念之一,向我们展示了开发过程中面对的典型问题的经典解决方案。这些模式不仅帮助开发者创建更加结构化、模块化和可维护的代码,而且也促进了代码的复用性。通过这篇文章,我们…...
【内网穿透】在Ubuntu搭建Web小游戏网站,并将其发布到公网访问
目录 前言 1. 本地环境服务搭建 2. 局域网测试访问 3. 内网穿透 3.1 ubuntu本地安装cpolar 3.2 创建隧道 3.3 测试公网访问 4. 配置固定二级子域名 4.1 保留一个二级子域名 4.2 配置二级子域名 4.3 测试访问公网固定二级子域名 前言 网:我们通常说的是互…...
网站开发的标准/seo排名推广工具
去年五六月在一台很老的mac机(2014)上安装过as和flutter环境,对于一个长期用win的安卓开发来说,第一次配置和使用mac真的痛苦。 今天,终于2014的8g机子报废了,公司配了一台2020新版mbp,32gi71t…...
有用织梦做的大网站吗/专门用来查找网址的网站
作者:Natasha The Robot,原文链接,原文日期:2016-07-25译者:Lanford3_3;校对:千叶知风;定稿:CMB上周我出席了 iOSDevCampDC,并有幸参加了 ayanonagon 关于测试…...
企业网站备案密码怎么找回/商丘网站推广公司
过山车 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 11520 Accepted Submission(s): 5072Problem DescriptionRPG girls今天和大家一起去游乐场玩。最终能够坐上梦寐以求的过山车了。但是,过山车…...
绿色农业网站模板/seo技术培训教程视频
一安装ROS 1设置ubuntu镜像源 安装好Ubuntu16.04之后发现,系统默认的软件源不能用,需要更改为国内的镜像源。国内有很多镜像源,这里选用清华大学开源软件镜像站:https://mirror.tuna.tsinghua.edu.cn/help/ubuntu/ a.备份系统默认…...
做mv主题网站/网站怎么优化关键词快速提升排名
https://zhuanlan.zhihu.com/p/29150809 一、数据库有锁机制的原因。 数据库锁定机制简单来说,就是数据库为了保证数据的一致性和有效性,而使各种共享资源在被并发访问变得有序所设计的一种规则。对于任何一种数据库来说都需要有相应的锁定机制ÿ…...
wordpress如何设置头像/2023年6月疫情恢复
1、安装VS Code 官网下载安装 2、配置python 安装插件 Python 插件 配置launch.json 配置tasks.json 关于tasks.json配置请参开官方文档 经过以上配置你就可以使用Vs code 来开发Python 程序了!! Vs code 这个开发工具真的是很好用,很多丰富…...