【Windows安全】授权初探:访问控制基础及应用

news2024/12/26 7:33:58

▒ 目录 ▒

    • 🛫 导读
      • 需求
      • 开发环境
    • 1️⃣ 常见名词及缩写汇总
      • 主体
      • 对象
      • 权限(规则)
    • 2️⃣ 常见概念
      • 访问控制及安全级别
      • 访问令牌(Access tokens)
      • 特权 (Privilege) - 线程相关的
      • 安全描述符(Security Descriptors,SD)
      • 访问控制列表(Access Control List,ACL)
      • 授权参数为空 (NULL DACL && 空 DACL)
      • DACL|SACL 列表显示顺序
      • 访问掩码
      • 文件安全和访问权限
      • AccessCheck 的工作原理
      • 安全描述符定义语言(SDDL)
    • 3️⃣ 常见工具及用法
      • whoami
      • runas
      • icacls
      • Repacls
    • 4️⃣ C++实战
      • 修改对象的ACL(访问控制列表)
      • 为新对象创建安全描述符
    • 🛬 文章小结
    • 📖 参考资料

🛫 导读

需求

授权是授予个人使用系统及其上存储的数据的权利。 授权通常由系统管理员设置,并由计算机根据某种形式的用户标识(如代码号或密码)进行验证。

今天我们将对windows授权相关知识进行简单的介绍,通过C++对其进行控制。

开发环境

版本号描述
文章日期2023-05-30
操作系统Win11 - 21H2 - 22000.1335

1️⃣ 常见名词及缩写汇总

以下是常见的 Windows 权限关键名词及它们之间的关系:

主体

主体可以是用户、组或应用程序。

  1. 用户账户: Windows 中,每个用户都必须有一个账户才能登录系统。每个帐户都有一个唯一的名称和密码来标识该用户。

  2. :组是一组用户账户的集合,它们通常具有相似的访问需求。将用户分配到组中,可以更方便地为它们分配权限和访问控制。

  3. 权限:权限是授予特定用户或组进行某些操作或访问某些资源的权利。在 Windows 中,权限可以授予给文件、文件夹、注册表项和其他资源。

  4. 访问令牌(Access tokens):描述进程或线程的安全上下文的对象。令牌中的信息包括与进程或线程关联的用户帐户的标识和特权信息。

  5. 安全标识符(SID):安全标识符是一种唯一标识符,用于表示用户、组和计算机对象。SID 也用于授权和访问控制。

对象

对象可以是文件、文件夹、注册表项等资源。

  1. 安全描述符(SD):安全描述符是一个数据结构,用于描述对象的安全性。SD 通常包含对象的安全标识符、ACL 和其他安全相关信息。
  2. 安全对象(SO)

权限(规则)

权限则代表对这些资源的操作,例如读取、写入、删除等。

  1. 访问控制列表(ACL):ACL 是一组权限,用于定义谁可以访问资源以及他们可以执行哪些操作。ACL 通常与文件、文件夹、注册表项和其他资源相关联。

  2. 访问控制项(ACE):ACL 是一组权限,用于定义谁可以访问资源以及他们可以执行哪些操作。ACL 通常与文件、文件夹、注册表项和其他资源相关联。

  3. 访问控制项(AES):ACE复数形式。

  4. 访问控制模型(Access Control Model)

  5. 用户帐户控制(UAC):通过此功能,用户可以以非管理程序、称为标准用户和管理员身份执行常见任务,而无需切换用户、注销或使用 运行方式。

2️⃣ 常见概念

访问控制及安全级别

Windows访问控制模型(Windows Access Control Model)是Windows操作系统中实现访问控制的一种机制。它基于对象主体权限的概念来管理资源的访问权限。

  • 主体可以是用户、组或应用程序。
  • 对象可以是文件、文件夹、注册表项等资源。
  • 权限则代表对这些资源的操作,例如读取、写入、删除等。
    在这里插入图片描述

Windows访问控制模型采用一种称为访问控制列表(Access Control List,ACL)的数据结构来存储对象的权限信息。ACL包含了一组访问控制条目(Access Control Entry,ACE),每个ACE描述了一种访问权限以及被授予该权限的主体。

当主体试图访问一个对象时,Windows会检查该主体的身份以及该主体被授予的权限。如果主体拥有足够的权限,它则可以访问该对象,否则就会被拒绝访问。

总体来说,Windows访问控制模型提供了一个可扩展、灵活、精细的访问控制机制,可以满足不同场景下对资源的安全性需求。

  • 更多关于访问控制的内容,可以参考视频《计算机安全-第4章 访问控制 https://www.bilibili.com/video/BV1wy4y1Y7fo/》。
    在这里插入图片描述

安全级别被定义为ABCD四个级别,如下图:
在这里插入图片描述
WindowsNT系列属于C2 级,满足下面要求:

  • 必须通过授予或拒绝对单个用户或命名用户组的访问权限来控制对资源的访问。
  • 内存必须受到保护,以便在 进程 释放内存后无法读取其内容。 同样,安全文件系统(如 NTFS)必须保护已删除的文件不被读取。
  • 用户登录时必须以唯一的方式(例如按密码)标识自己。 所有可审核操作都必须标识执行该操作的用户。
  • 系统管理员必须能够审核与安全相关的事件。 但是,访问安全相关事件审核数据必须仅限于授权管理员。
  • 必须保护系统免受外部干扰或篡改,例如修改正在运行的系统或存储在磁盘上的系统文件。

访问令牌(Access tokens)

访问令牌是描述进程或线程的安全上下文的对象。
令牌中的信息包括与进程线程关联的用户帐户的标识和特权信息。
当用户登录时,系统通过将用户密码与安全数据库(如域认证中的NTDS或本地认证中的SAM文件)中存储的信息进行比较来验证用户密码。
如果密码经过验证,则系统将生成访问令牌。代表该用户执行的每个进程都有此访问令牌的副本。(通常我们在输入密码登陆进入Windows界面时就是一个生成访问令牌的过程)
当线程与安全对象进行交互或尝试执行需要特权的系统任务时,系统使用访问令牌来标识用户。

访问令牌包含以下信息:
在这里插入图片描述

Windows下有两种类型的Token令牌:授权令牌和模拟令牌。

  • 授权令牌(Delegation Token)
    也叫主令牌,是由windows内核创建并分配给进程的默认访问令牌,每一个进程有一个主令牌,它描述了与当前进程相关的用户帐户的安全上下文。用于交互式登录(如rdp登录访问)。

  • 模拟令牌(Impersonation Token)
    所在进程的主令牌会自动附加到当前的线程上,作为线程的安全上下文。而线程可以运行在另一个非主令牌的访问令牌下执行,而这个令牌被称为模拟令牌。用于非交互式的会话(利用WMI进行远程访问)。

特权 (Privilege) - 线程相关的

特权是帐户(如用户或组帐户)在本地计算机上执行各种系统相关操作的权限,例如关闭系统、加载设备驱动程序或更改系统时间。

系统有一个帐户数据库,存储了用户或用户群的特权。当用户登录后,系统产生一个访问令牌(access token)包含了用户的特权清单,这包含用户所在群的特权。注意特权仅限于本地计算机,域帐户在不同计算机上有不同特权。

当用户试图执行一个特权操作,系统检查用户的访问令牌以确定使用是否具有必要的特权。调用GetTokenInformation函数可以检查特权。

另外,还有令牌中的权限列表,权限与对象访问无关,所以与安全描述符,SID等无关。
线程执行一些管理相关的操作时,系统会检查该线程的令牌中是否含有特定的权限,如果有,则允许线程执行该操作,否则拒绝。

安全描述符(Security Descriptors,SD)

安全描述符包含与安全对象关联的安全信息。 安全描述符由 SECURITY_DESCRIPTOR 结构和关联的安全信息组成。 安全描述符可以包含以下安全信息:

  • 对象所有者主组的安全标识符 (SID) 。
  • DACL :指定允许或拒绝特定用户或组的访问权限的。
  • SACL:指定为对象生成审核记录的访问尝试的类型。
  • 一组控制位:用于限定安全描述符或其单个成员的含义。

访问控制列表(Access Control List,ACL)

ACL 中的每个 ACE 标识一个受信者,并指定该受信者访问规则。
安全对象的安全描述符可以包含两种类型的 ACL:DACL 和 SACL。

DACL:自主访问控制列表(DACL),是安全描述符中最重要的,它里面包含零个或多个访问控制项(ACE,Access Control Entry),每个访问控制项的内容描述了允许或拒绝特定账户对这个对象执行特定操作。
在这里插入图片描述

SACL:系统访问控制列表(SACL), 主要是用于系统审计的,它的内容指定了当特定账户对这个对象执行特定操作时,记录到系统日志中。
在这里插入图片描述

授权参数为空 (NULL DACL && 空 DACL)

如果属于对象安全描述符 (DACL) 自由访问控制列表设置为 NULL, 则创建 null DACL。
NULL DACL 向请求它的用户授予完全访问权限;不会对 对象执行正常的安全检查。

空 DACL 是正确分配和初始化的 DACL,它不包含AES (访问控制) 。 空 DACL 不授予对它所分配到的对象的访问权限。

null DACL 不应与空的 DACL 混淆。

DACL|SACL 列表显示顺序

1、拒绝(deny)有优先排在允许(allow)前面
2、继承的ACE会排在程序或者手动的添加ACE顺序之后;
在这里插入图片描述

访问掩码

所有安全对象都使用下图所示的访问掩码格式来安排其访问权限。
在这里插入图片描述

文件安全和访问权限

由于文件是安全对象,因此对它们的访问由访问控制模型控制,该控制模型对 Windows 中所有其他安全对象的访问。

  • 文件或目录的默认安全描述符中的访问控制列表 (ACL) 继承自其父目录
  • 默认安全描述符仅在新创建文件或目录时分配,而不是在重命名或移动文件或目录时分配。

FileSystemRights映射到访问掩码上
在这里插入图片描述

参考资料:

  • https://learn.microsoft.com/en-us/windows/win32/fileio/file-security-and-access-rights

AccessCheck 的工作原理

当一个线程想访问一个安全对象时候,系统要么允许访问,要拒绝访问

系统现成序列中的每个ACE,直到下面的情况发生:

  • 拒绝访问的 ACE 显式拒绝对线程的访问令牌中列出的受信者之一的任何请求访问权限。
  • 线程访问令牌中列出的受信者允许访问的一个或多个 AES 显式授予所有请求的访问权限。
  • 已检查所有 AES,并且仍有至少一个请求的访问权限未显式允许,在这种情况下,将隐式拒绝访问。

示例:
下图描述一个DACL对象允许访问一个线程而拒绝访问另一个线程。
  在这里插入图片描述

  • 对于线程A,系统读ACE1并且立即拒绝访问,因为访问拒绝ACE应用到线程访问标记中的用户。这种情况下,系统并没有检查ACE2和3。
  • 对于线程B,ACE1没有应用,因此系统处理ACE2,其允许写操作,并且ACE3允许读和执行操作。

因为系统在请求访问并显式允许或拒绝的时候停止检查,DACL中的ACE顺序非常重要。注意,如果ACE顺序与例子中的不同,系统可能分配访问权限给A。对于系统对象,操作系统定义一个首选的DACL中ACE的顺序。

附赠一张Window权限控制如何运行的流程图:
请添加图片描述

安全描述符定义语言(SDDL)

安全描述符定义语言(SDDL)定义了ConvertSecurityDescriptorToStringSecurityDescriptor和ConvertStringSecurityDescriptorToSecurityDescriptor函数用来将安全描述符描述为文本字符串的字符串格式。该语言还定义了字符串元素,用于描述安全描述符的组成部分中的信息。

AccessChk工具可以直接展示出指定对象的权限信息,并且能从SDDL到已解析的权限全面覆盖。
请添加图片描述

3️⃣ 常见工具及用法

whoami

获取 当前登录的用户的访问令牌信息:whoami /all
在这里插入图片描述

runas

  • 创建一个名为foo的账号
  • 执行runas /user:foo cmd,并输入密码
  • 新的cmd窗口标题变了,而且执行whoam /user显示信息为账号foo
    在这里插入图片描述

icacls

  1. 查看指定文件的ACL
    icacls C:\Windows\SYSVOL\sysvol\test.com
    在这里插入图片描述
    2、备份指定文件(包括当前目录及其子目录中的文件)的ACL

icacls C:\Windows\SYSVOL\sysvol\test.com /save AclFile /t

3、还原指定文件(包括当前目录及其子目录中的文件)的ACL

icacls C:\Windows\SYSVOL\sysvol\ /restore AclFile /t
注:还原时,路径需要设置为上级目录。

4、添加用户test1对指定文件(包括当前目录及其子目录中的文件)的完全访问权限

icacls C:\Windows\SYSVOL\sysvol\test.com /grant test1:(OI)(CI)(F) /t
注:(OI)代表对象继承 (CI)代表容器继承 (F)代表完全访问。

5、移除用户test1对指定文件(包括当前目录及其子目录中的文件)的完全访问权限

icacls C:\Windows\SYSVOL\sysvol\test.com /remove test1 /t

Repacls

开源的文件安全工具,代码写的挺好的,效率很高。

  • github地址:https://github.com/NoMoreFood/Repacls
  • 文档: https://nomorefood.github.io/Repacls/
- Replace all instances of DOM\jack to DOM\jill in C:\test:
  repacls.exe /Path C:\Test /ReplaceAccount "DOM\jack:DOM\jill"

- Migrate all permissions for all accounts with matching
  names in DOMA with DOMB:
  repacls.exe /Path C:\Test /MoveDomain DOMA:DOMB

- Update old SID references, remove any explicit permissions that are already
  granted by inherited permissions, and compact all ACLs if not compacted:
  repacls.exe /Path C:\Test /UpdateHistoricalSids /RemoveRedundant /Compact

4️⃣ C++实战

修改对象的ACL(访问控制列表)

以下示例将 访问控制项 (ACE) 添加到对象的 任意访问控制列表 (DACL) 。主要流程为:

  • GetNamedSecurityInfo:获取DACL(pOldDACL)
  • EXPLICIT_ACCESS:创建并初始化一个ACE(ea)
  • SetEntriesInAcl:将ea和pOldDACL,合并成新的DACL(pNewDACL)
  • SetNamedSecurityInfo:将pNewDACL设置到对象上
#include <windows.h>
#include <stdio.h>

DWORD AddAceToObjectsSecurityDescriptor (
    LPTSTR pszObjName,          // name of object
    SE_OBJECT_TYPE ObjectType,  // type of object
    LPTSTR pszTrustee,          // trustee for new ACE
    TRUSTEE_FORM TrusteeForm,   // format of trustee structure
    DWORD dwAccessRights,       // access mask for new ACE
    ACCESS_MODE AccessMode,     // type of ACE
    DWORD dwInheritance         // inheritance flags for new ACE
) 
{
    DWORD dwRes = 0;
    PACL pOldDACL = NULL, pNewDACL = NULL;
    PSECURITY_DESCRIPTOR pSD = NULL;
    EXPLICIT_ACCESS ea;

    if (NULL == pszObjName) 
        return ERROR_INVALID_PARAMETER;

    // Get a pointer to the existing DACL.
    dwRes = GetNamedSecurityInfo(pszObjName, ObjectType, 
          DACL_SECURITY_INFORMATION,
          NULL, NULL, &pOldDACL, NULL, &pSD);
    if (ERROR_SUCCESS != dwRes) {
        printf( "GetNamedSecurityInfo Error %u\n", dwRes );
        goto Cleanup; 
    }  

    // Initialize an EXPLICIT_ACCESS structure for the new ACE. 
    ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
    ea.grfAccessPermissions = dwAccessRights;
    ea.grfAccessMode = AccessMode;
    ea.grfInheritance= dwInheritance;
    ea.Trustee.TrusteeForm = TrusteeForm;
    ea.Trustee.ptstrName = pszTrustee;

    // Create a new ACL that merges the new ACE
    // into the existing DACL.
    dwRes = SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL);
    if (ERROR_SUCCESS != dwRes)  {
        printf( "SetEntriesInAcl Error %u\n", dwRes );
        goto Cleanup; 
    }  

    // Attach the new ACL as the object's DACL.
    dwRes = SetNamedSecurityInfo(pszObjName, ObjectType, 
          DACL_SECURITY_INFORMATION,
          NULL, NULL, pNewDACL, NULL);
    if (ERROR_SUCCESS != dwRes)  {
        printf( "SetNamedSecurityInfo Error %u\n", dwRes );
        goto Cleanup; 
    }  

    Cleanup:
        if(pSD != NULL) 
            LocalFree((HLOCAL) pSD); 
        if(pNewDACL != NULL) 
            LocalFree((HLOCAL) pNewDACL); 

        return dwRes;
}

为新对象创建安全描述符

以下示例使用以下过程为新注册表项创建 安全描述符 。 类似的代码可用于为其他对象类型创建安全描述符。主要流程为:

  • GetNamedSecurityInfo:获取DACL(pOldDACL)
  • AllocateAndInitializeSid:创建两个sid(Everyone && Administrators group)
  • EXPLICIT_ACCESS:创建并初始化两个个ACE(ea)
  • SetEntriesInAcl:根据ea创建DACL(pACL)
  • InitializeSecurityDescriptorSetSecurityDescriptorDacl:根据pACL创建并初始化SD(pSD)
  • SECURITY_ATTRIBUTES:根据pSD创建安全属性(sa)
  • RegCreateKeyEx:根据sa调用注册表创建接口,这样得到的注册表就是我们指定的权限的注册表项了。

效果图:
在这里插入图片描述

#pragma comment(lib, "advapi32.lib")

#include <windows.h>
#include <stdio.h>
#include <aclapi.h>
#include <tchar.h>

void main()
{

    DWORD dwRes, dwDisposition;
    PSID pEveryoneSID = NULL, pAdminSID = NULL;
    PACL pACL = NULL;
    PSECURITY_DESCRIPTOR pSD = NULL;
    EXPLICIT_ACCESS ea[2];
    SID_IDENTIFIER_AUTHORITY SIDAuthWorld =
            SECURITY_WORLD_SID_AUTHORITY;
    SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
    SECURITY_ATTRIBUTES sa;
    LONG lRes;
    HKEY hkSub = NULL;

    // Create a well-known SID for the Everyone group.
    if(!AllocateAndInitializeSid(&SIDAuthWorld, 1,
                     SECURITY_WORLD_RID,
                     0, 0, 0, 0, 0, 0, 0,
                     &pEveryoneSID))
    {
        _tprintf(_T("AllocateAndInitializeSid Error %u\n"), GetLastError());
        goto Cleanup;
    }

    // Initialize an EXPLICIT_ACCESS structure for an ACE.
    // The ACE will allow Everyone read access to the key.
    ZeroMemory(&ea, 2 * sizeof(EXPLICIT_ACCESS));
    ea[0].grfAccessPermissions = KEY_READ;
    ea[0].grfAccessMode = SET_ACCESS;
    ea[0].grfInheritance= NO_INHERITANCE;
    ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
    ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
    ea[0].Trustee.ptstrName  = (LPTSTR) pEveryoneSID;

    // Create a SID for the BUILTIN\Administrators group.
    if(! AllocateAndInitializeSid(&SIDAuthNT, 2,
                     SECURITY_BUILTIN_DOMAIN_RID,
                     DOMAIN_ALIAS_RID_ADMINS,
                     0, 0, 0, 0, 0, 0,
                     &pAdminSID)) 
    {
        _tprintf(_T("AllocateAndInitializeSid Error %u\n"), GetLastError());
        goto Cleanup; 
    }

    // Initialize an EXPLICIT_ACCESS structure for an ACE.
    // The ACE will allow the Administrators group full access to
    // the key.
    ea[1].grfAccessPermissions = KEY_ALL_ACCESS;
    ea[1].grfAccessMode = SET_ACCESS;
    ea[1].grfInheritance= NO_INHERITANCE;
    ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
    ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
    ea[1].Trustee.ptstrName  = (LPTSTR) pAdminSID;

    // Create a new ACL that contains the new ACEs.
    dwRes = SetEntriesInAcl(2, ea, NULL, &pACL);
    if (ERROR_SUCCESS != dwRes) 
    {
        _tprintf(_T("SetEntriesInAcl Error %u\n"), GetLastError());
        goto Cleanup;
    }

    // Initialize a security descriptor.  
    pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, 
                             SECURITY_DESCRIPTOR_MIN_LENGTH); 
    if (NULL == pSD) 
    { 
        _tprintf(_T("LocalAlloc Error %u\n"), GetLastError());
        goto Cleanup; 
    } 
 
    if (!InitializeSecurityDescriptor(pSD,
            SECURITY_DESCRIPTOR_REVISION)) 
    {  
        _tprintf(_T("InitializeSecurityDescriptor Error %u\n"),
                                GetLastError());
        goto Cleanup; 
    } 
 
    // Add the ACL to the security descriptor. 
    if (!SetSecurityDescriptorDacl(pSD, 
            TRUE,     // bDaclPresent flag   
            pACL, 
            FALSE))   // not a default DACL 
    {  
        _tprintf(_T("SetSecurityDescriptorDacl Error %u\n"),
                GetLastError());
        goto Cleanup; 
    } 

    // Initialize a security attributes structure.
    sa.nLength = sizeof (SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = pSD;
    sa.bInheritHandle = FALSE;

    // Use the security attributes to set the security descriptor 
    // when you create a key.
    lRes = RegCreateKeyEx(HKEY_CURRENT_USER, _T("mykey"), 0, _T(""), 0, 
            KEY_READ | KEY_WRITE, &sa, &hkSub, &dwDisposition); 
    _tprintf(_T("RegCreateKeyEx result %u\n"), lRes );

Cleanup:

    if (pEveryoneSID) 
        FreeSid(pEveryoneSID);
    if (pAdminSID) 
        FreeSid(pAdminSID);
    if (pACL) 
        LocalFree(pACL);
    if (pSD) 
        LocalFree(pSD);
    if (hkSub) 
        RegCloseKey(hkSub);

    return;

}

🛬 文章小结

以上只是对Windows权限的简单总结,其内容无比庞杂,资料又相对匮乏。
小编花了一周时间,反复看《参考资料》中的各个资料,尤其是微软官网资料,看的多了,略有体会,故记录下来,为以后学习做个阶段性的总结。

📖 参考资料

  • 微软官网资料:授权 https://learn.microsoft.com/zh-cn/windows/win32/secauthz/authorization-portal
  • Windows访问控制系列文章 https://github.com/rootclay/Windows-Access-Control.git
  • 【windows安全性 之访问控制】 访问控制 详细解说 https://www.cnblogs.com/cdaniu/p/15582260.html
  • 【windows 访问控制】系列文章 https://www.cnblogs.com/cdaniu/p/15630322.html
  • 第七章:访问控制技术原理和应用 https://blog.csdn.net/xjc2998310890/article/details/112809763
  • 渗透技巧——Windows下的Access Control List https://zhuanlan.zhihu.com/p/54426112

ps: 文章中内容仅用于技术交流,请勿用于违规违法行为。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

批判马斯洛需求层次模型

再次批判马斯洛需求层次模型&#xff0c;有啥缺陷&#xff1f; 趣讲大白话&#xff1a;文化不同&#xff0c;心理不同 【趣讲信息科技182期】 **************************** 每个民族的文化心理结构都不一样 常常低估文化对人的影响 有一门心理学分支&#xff0c;文化心理学 专…

(转载)免疫优化算法在物流配送中心选址中的应用(matlab实现)

12.1 理论基础 12.1.1 物流中心选址问题 随着世界经济的快速发展以及现代科学技术的进步&#xff0c;物流业作为国民经济的一个新兴服务部门&#xff0c;正在全球范围内迅速发展。物流业的发展给社会的生产和管理、人们的生活和就业乃至政府的职能以及社会的法律制度等都带来…

Vue前端压缩图片后上传,拍照上传最佳实践

文章目录 一、前言二、使用shrinkpng进行图片压缩2.1 安装依赖包2.2 引入包2.3 开始编码 总结 一、前言 最近有一个需求&#xff0c;通过手机拍照后上传图片到服务器&#xff0c;大家应该都知道&#xff0c;现在的手机像素实在是太高了&#xff0c;随便拍一张都是10M以上&…

移动应用架构同React Native、Flutter有什么关系?

移动应用架构描述了设计和构建应用的模式与技术。 该架构可以提供构建应用时应遵循的路线图和最佳实践&#xff0c;构建一个结构合理的应用。 移动应用的常见层次结构包括用户界面层、业务逻辑层、数据访问层&#xff0c;但是随着跨平台开发框架的不断发展&#xff0c;以React…

从TCP协议到TCP通信的各种异常现象和分析

很多人总觉得学习TCP/IP协议没什么用&#xff0c;觉得日常编程开发只需要知道socket接口怎么用就可以了。如果大家定位过线上问题就会知道&#xff0c;实际上并非如此。如果应用在局域网内&#xff0c;且设备一切正常的情况下可能确实如此&#xff0c;但如果一旦出现诸如中间交…

Zigbee Install code的使用和CRC的计算

Zigbee Install code的使用和CRC的计算 前言什么是Install codes&#xff1f;Zigbee install codes的格式CRC算法信息&#xff1a;python演示&#xff1a;Install Code的使用&#xff1a;烧录Install codes到Silicon labs EFR32设备中去安装代码文件格式烧录Install codes:核查…

【学习笔记】【万字长文】linux三剑客学习笔记

前言 ​ 上班以后用到的服务器大多数是centos的&#xff0c;很多命令会用一部分但稍微复杂一点的只能问度娘了。 ​ 时间长了&#xff0c;还是没积攒下什么本事&#xff0c;每次都需要百度查找。 ​ 终于有时间整理一篇关于linux三剑客的笔记&#xff0c;作为记录方便以后查…

项目经验分享:LVGL编程举例

本文介绍如何在成功移植LVGL的基础之上&#xff0c;编写自己的LVGL GUI程序。 文章目录 1. LVGL组件简介与LVGL仿真1.1 LVGL组件1.2 LVGL仿真 2. 代码结构3. 编程目标4. 编程前的准备5. LVGL编程基础5.1 简单示例代码5.2 设置组件位置5.3 图片的显示5.4 组件的事件响应5.5 设置…

【P46】JMeter 响应断言(Response Assertion)

文章目录 一、响应断言&#xff08;Response Assertion&#xff09; 参数说明二、准备工作三、测试计划设计3.1、包括3.2、匹配3.3、相等3.4、字符串3.5、字符串3.6、或者 一、响应断言&#xff08;Response Assertion&#xff09; 参数说明 可以对 Jmeter 取样器的响应消息进…

0x10 会话服务 DiagnosticSessionControl

0x10 会话服务 相当是一种分类&#xff0c;通过控制会话模式&#xff0c;使用不同的服务。应始终只有一个诊断会话在服务器中处于活动状态。 服务器应在启动时始终启动默认的诊断会话。 如果没有启动其他诊断会话&#xff0c;则只要服务器通电&#xff0c;默认诊断会话就应该运…

Hudi(五)集成Flink(3)

12、离线compaction MOR表的compaction默认是自动打开的&#xff0c;策略是5个commits执行一次压缩。因为压缩操作比较耗费内存&#xff0c;和写流程放在同一个pipeline&#xff0c;在数据量比较大的时候&#xff08;10w/sqps&#xff09;&#xff0c;容易干扰写流程&#xff0…

LLM:LoRA: Low-Rank Adaptation of Large Language Models

随着模型规模的不断扩大&#xff0c;微调模型的所有参数&#xff08;所谓full fine-tuning&#xff09;的可行性变得越来越低。以GPT-3的175B参数为例&#xff0c;每增加一个新领域就需要完整微调一个新模型&#xff0c;代价和成本很高。 为解决微调大规模语言模型到不同领域和…

西南交通大学智能监测 培训课程练习3

2023.05.31培训 task1&#xff1a;MybatisPlus的使用 task2&#xff1a;SpringMVC常用接口开发 task3&#xff1a;JSON、接口测试 task4&#xff1a;SpringMVC拦截器与过滤器 目录 一、MybatisPlus 1.1DO类 1.2Mapper接口 1.3编写测试类测试 1.4Mybatis和MybatisPlus 二、…

Verilog学习笔记(串口RS232,基于野火教程)

目录 一、串口简介 二、设计与实现 串口数据回环顶层模块设计 串口接收模块uart_rx 串口发送模块uart_tx 顶层模块rs32_top 三、上板验证 一、串口简介 其中SPI和I2C为同步通信接口&#xff0c;双方时钟频率相同。而UART属于异步通信接口&#xff0c;没有统一时钟&…

旅游网项目(SpringBoot2.7.1 + SpringMVC + Mybatis-Plus3.5.0)

技术选型 JAVA版本&#xff1a;JDK17 数据库&#xff1a;Mysql5.7Navicat 后端框架&#xff1a;SpringBoot3.0.6 SpringMVC Mybatis-Plus3.5.0 权限控制&#xff1a;SpringSecurity 前端框架&#xff1a;AdminLTE2 模板引擎&#xff1a;Thymeleaf 工具类&#xff1a;发…

WIN10系统解决IDEA动不动就卡顿一下

1、前言 不知为啥&#xff0c;最近idea一直在卡顿&#xff0c;输入几个代码都会卡两秒&#xff0c;鼠标滚动文件卡两秒&#xff0c;点击打开文件卡两秒&#xff0c;就算是点击上方的工具栏&#xff0c;它也要等两秒才会出来菜单&#xff01; 卡顿的时候整个idea直接无响应&a…

Java性能权威指南-总结3

Java性能权威指南-总结3 性能测试方法原则4:尽早频繁测试小结 Java性能调优工具箱操作系统的工具和分析CPU使用率 性能测试方法 原则4:尽早频繁测试 这是最后的原则。性能测试应该作为开发周期不可或缺的一部分。理想情况下&#xff0c;在代码提交到中心源代码仓库前&#xf…

【数据分享】1929-2022年全球站点的逐月最高气温(Shp\Excel\12000个站点)

气象数据是在各项研究中都经常使用的数据&#xff0c;气象指标包括气温、风速、降水、湿度等指标&#xff0c;其中又以气温指标最为常用&#xff01;说到气温数据&#xff0c;最详细的气温数据是具体到气象监测站点的气温数据&#xff01; 之前我们分享过1929-2022年全球气象站…

Win10搭建Nacos2.2.3集群版

Nacos是Alibaba提供的服务注册发现的管理平台&#xff0c;其优异的性能越来越受到广大开发者的喜爱&#xff0c;在构建分布式微服务项目中通常会首选Nacos作为注册/配置中心&#xff0c;在实际开发中为了提升服务的可用性和稳定性&#xff0c;通常都会搭建集群版&#xff0c;有…