zend server试用分析

news2025/3/17 1:40:58

文件:ZendServer-2021.4.1-multi-php-Windows_x86.exe

安装后可以试用30天,想分析下限制原理, 根据安装日志,发现了2个关键的文件:

ZendServer\gui\module\Configuration\src\Configuration\License\Wrapper.php

ZendServer\gui\module\Configuration\src\Configuration\License\License.php

Wrapper.php里面有一个关键的函数:

    public function getSerialNumberInfo($serialNumber, $userName)
    {
        $method = 'zem_serial_number_info';

        try {
            $this->validateMethod($method);
            $licenseInfo = $method($serialNumber, $userName);
            if (!is_array($licenseInfo)) {
                throw new ZSException('unexpected response received');
            }
        } catch (\Exception $e) {
            Log::err("method {$method} invocation failed with the following error: ".$e->getMessage());
            throw new ZSException("method {$method} invocation failed with the following error: ".$e->getMessage());
        }

        return new License($licenseInfo);
    }

根据$licenseInfo = $method($serialNumber, $userName);这行代码可以知道,调用了函数:zem_serial_number_info来获取许可证信息,试用期限制应该就在这个函数里面了。

知道了函数名称,我们如何找到这个函数呢?想了下PHP程序的执行流程:

1、客户端请求PHP

2、PHP服务端收到请求 php.exe or php-cgi.exe

3、PHP加载zend server扩展插件,检测是否过期了

思路很清晰了,去PHP扩展目录看下:zendserver\ZendServer\php\7.4\lib\ext

发现了可疑文件:ZendUtils.dll 

使用IDA分析ZendUtils.dll的导出函数get_module,找到了函数zem_serial_number_info的地址

get_module IDA代码如下:

void *get_module()
{
  return get_module_0();
}

void *get_module_0()
{
  return &unk_10061230;
}

函数代码很简单,返回了一个地址10061230,到这里需要了解PHP扩展模块的编写方法和导出函数原理,我们在IDA跳到地址10061230:

data:10061230 unk_10061230    db  5Ch ; \             ; DATA XREF: sub_10006E20↑o
.data:10061230                                         ; get_module_0↑o
.data:10061231                 db    0
.data:10061232                 db    0
.data:10061233                 db    0
.data:10061234                 db 0B6h
.data:10061235                 db  16h
.data:10061236                 db  34h ; 4
.data:10061237                 db    1
.data:10061238                 db    0
.data:10061239                 db    0
.data:1006123A                 db    0
.data:1006123B                 db    0
.data:1006123C                 db    0
.data:1006123D                 db    0
.data:1006123E                 db    0
.data:1006123F                 db    0
.data:10061240                 db    0
.data:10061241                 db    0
.data:10061242                 db    0
.data:10061243                 db    0
.data:10061244                 dd offset aZendUtils    ; "Zend Utils"
.data:10061248                 dd offset off_100610A0 //这里就是PHP扩展模块的导出函数表了
.data:1006124C                 dd offset sub_10001EF6
.data:10061250                 dd offset sub_1000239C

再跳到地址:off_100610A0

.data:100610A0 off_100610A0    dd offset aZemGetExtensio
.data:100610A0                                         ; DATA XREF: .data:10061248↓o
.data:100610A0                                         ; "zem_get_extension_info_by_id"
.data:100610A4                 dd offset sub_10002973
.data:100610A8                 db    0
.data:100610A9                 db    0
.data:100610AA                 db    0
.data:100610AB                 db    0
.data:100610AC                 db 0FFh
.data:100610AD                 db 0FFh
.data:100610AE                 db 0FFh
.data:100610AF                 db 0FFh
.data:100610B0                 db    0
.data:100610B1                 db    0
.data:100610B2                 db    0
.data:100610B3                 db    0
.data:100610B4                 dd offset aZemGetExtensio_0 ; "zem_get_extension_info_by_name"
.data:100610B8                 dd offset sub_100013D9
.data:100610BC                 align 10h
.data:100610C0                 db 0FFh
.data:100610C1                 db 0FFh
.data:100610C2                 db 0FFh
.data:100610C3                 db 0FFh
.data:100610C4                 db    0
.data:100610C5                 db    0
.data:100610C6                 db    0
.data:100610C7                 db    0
.data:100610C8                 dd offset aZemGetExtensio_1 ; "zem_get_extensions_info"
.data:100610CC                 dd offset sub_10002432
.data:100610D0                 db    0
.data:100610D1                 db    0
.data:100610D2                 db    0
.data:100610D3                 db    0
.data:100610D4                 db 0FFh
.data:100610D5                 db 0FFh
.data:100610D6                 db 0FFh
.data:100610D7                 db 0FFh
.data:100610D8                 db    0
.data:100610D9                 db    0
.data:100610DA                 db    0
.data:100610DB                 db    0
.data:100610DC                 dd offset aZemGetLicenseI ; "zem_get_license_info"
.data:100610E0                 dd offset zem_get_license_info_sub_10002455
.data:100610E4                 align 8
.data:100610E8                 db 0FFh
.data:100610E9                 db 0FFh
.data:100610EA                 db 0FFh
.data:100610EB                 db 0FFh
.data:100610EC                 db    0
.data:100610ED                 db    0
.data:100610EE                 db    0
.data:100610EF                 db    0
.data:100610F0                 dd offset aZendIsConfigur ; "zend_is_configuration_changed"
.data:100610F4                 dd offset sub_10001A78
.data:100610F8                 db    0
.data:100610F9                 db    0
.data:100610FA                 db    0
.data:100610FB                 db    0
.data:100610FC                 db 0FFh
.data:100610FD                 db 0FFh
.data:100610FE                 db 0FFh
.data:100610FF                 db 0FFh
.data:10061100                 db    0
.data:10061101                 db    0
.data:10061102                 db    0
.data:10061103                 db    0
.data:10061104                 dd offset aZendSetConfigu ; "zend_set_configuration_changed"
.data:10061108                 dd offset sub_10001262
.data:1006110C                 align 10h
.data:10061110                 db 0FFh
.data:10061111                 db 0FFh
.data:10061112                 db 0FFh
.data:10061113                 db 0FFh
.data:10061114                 db    0
.data:10061115                 db    0
.data:10061116                 db    0
.data:10061117                 db    0
.data:10061118                 dd offset aZendGetCfgVar ; "zend_get_cfg_var"
.data:1006111C                 dd offset sub_10001604
.data:10061120                 db    0
.data:10061121                 db    0
.data:10061122                 db    0
.data:10061123                 db    0
.data:10061124                 db 0FFh
.data:10061125                 db 0FFh
.data:10061126                 db 0FFh
.data:10061127                 db 0FFh
.data:10061128                 db    0
.data:10061129                 db    0
.data:1006112A                 db    0
.data:1006112B                 db    0
.data:1006112C                 dd offset aZendRestartPhp ; "zend_restart_php"
.data:10061130                 dd offset sub_100026A3
.data:10061134                 align 8
.data:10061138                 db 0FFh
.data:10061139                 db 0FFh
.data:1006113A                 db 0FFh
.data:1006113B                 db 0FFh
.data:1006113C                 db    0
.data:1006113D                 db    0
.data:1006113E                 db    0
.data:1006113F                 db    0
.data:10061140                 dd offset aZendGetFileSiz ; "zend_get_file_size"
.data:10061144                 dd offset sub_1000146F
.data:10061148                 db    0
.data:10061149                 db    0
.data:1006114A                 db    0
.data:1006114B                 db    0
.data:1006114C                 db 0FFh
.data:1006114D                 db 0FFh
.data:1006114E                 db 0FFh
.data:1006114F                 db 0FFh
.data:10061150                 db    0
.data:10061151                 db    0
.data:10061152                 db    0
.data:10061153                 db    0
.data:10061154                 dd offset aZendGetCpuArch ; "zend_get_cpu_arch"
.data:10061158                 dd offset sub_10002D6F
.data:1006115C                 align 10h
.data:10061160                 db 0FFh
.data:10061161                 db 0FFh
.data:10061162                 db 0FFh
.data:10061163                 db 0FFh
.data:10061164                 db    0
.data:10061165                 db    0
.data:10061166                 db    0
.data:10061167                 db    0
.data:10061168                 dd offset aZemSerialNumbe ; "zem_serial_number_info"
.data:1006116C                 dd offset sub_100015B9
.data:10061170                 db    0
.data:10061171                 db    0
.data:10061172                 db    0
.data:10061173                 db    0
.data:10061174                 db 0FFh
.data:10061175                 db 0FFh
.data:10061176                 db 0FFh
.data:10061177                 db 0FFh
.data:10061178                 db    0
.data:10061179                 db    0
.data:1006117A                 db    0
.data:1006117B                 db    0

看到了函数zem_serial_number_info:

.data:10061168                 dd offset aZemSerialNumbe ; "zem_serial_number_info"
.data:1006116C                 dd offset sub_100015B9

跟进sub_100015B9看下:

int __fastcall sub_100015B9(int a1, int *a2)
{
  return sub_1000A730(a1, a2);
}

int __fastcall sub_1000A730(int a1, int *a2)
{
  int *v2; // edi
  int result; // eax
  unsigned int v4; // ecx
  const struct QString *v5; // esi
  int v6; // eax
  int v7; // eax
  volatile signed __int32 *v8; // [esp+Ch] [ebp-30h]
  volatile signed __int32 *v9; // [esp+10h] [ebp-2Ch]
  char v10; // [esp+14h] [ebp-28h]
  char v11; // [esp+18h] [ebp-24h]
  char v12; // [esp+1Ch] [ebp-20h]
  char v13; // [esp+20h] [ebp-1Ch]
  int v14; // [esp+24h] [ebp-18h]
  const char *v15; // [esp+28h] [ebp-14h]
  int v16; // [esp+2Ch] [ebp-10h]
  int v17; // [esp+38h] [ebp-4h]

  v2 = a2;
  result = zend_parse_parameters(*(_DWORD *)(a1 + 28), "ss", &v15, &v12, &v14, &v13);
  if ( result == -1 )
  {
    *v2 = -1;
    v2[2] = 4;
  }
  else
  {
    if ( v15 )
      v4 = strlen(v15);
    else
      v4 = -1;
    v16 = QString::fromAscii_helper(v15, v4);
    sub_10001267((int)&v8);
    sub_10002306(&v8, (int)&v16);
    v5 = (const struct QString *)sub_1000272F((int)&v16);// allocate_license_db
    sub_10011270(v2, v5);                       // 许可证各个字段解析
    j_free_license_db(v5);
    QString::~QString((QString *)&v11);
    QString::~QString((QString *)&v10);
    v17 = 0;
    v6 = *((_DWORD *)v9 + 2);
    if ( !v6 || v6 != -1 && _InterlockedExchangeAdd(v9 + 2, 0xFFFFFFFF) == 1 )
      QHashData::free_helper((QHashData *)v9, (void (__cdecl *)(struct Node *))sub_100026B2);
    v17 = 1;
    v7 = *((_DWORD *)v8 + 2);
    if ( !v7 || v7 != -1 && _InterlockedExchangeAdd(v8 + 2, 0xFFFFFFFF) == 1 )
      QHashData::free_helper((QHashData *)v8, (void (__cdecl *)(struct Node *))sub_10001109);
    result = QString::~QString((QString *)&v16);
  }
  return result;
}

发现了,两个关键的函数:

v5 = (const struct QString *)sub_1000272F((int)&v16);// allocate_license_db
sub_10011270(v2, v5);                       // 许可证各个字段解析

最关键的是:sub_1000272F调用了allocate_license_db,看函数名字就知道了

经分析allocate_license_db在ZendExtensionManager.dll文件里面,我们转去分析ZendExtensionManager.dll的导出函数, 看到了get_license_db ,应该就是它了

void *get_license_db()
{
  return get_license_db_0();
}

void *get_license_db_0()
{
  return Memory;
}

IDA分析很简单,只是返回了一个内存地址:Memory,那就是计算好的许可证信息了。

交叉引用Memory看看哪些地方写了Memory,找到了关键函数sub_10014FC0

QString *__thiscall sub_10014FC0(QString *this, const struct QString *Memory, unsigned int a3, int pUserName)
{
  QString *pThis; // ebx
  unsigned int v5; // ecx
  const struct QString *v6; // eax
  QHashData **v7; // eax
  bool v8; // al
  int v9; // ecx
  char v10; // al
  int v11; // ecx
  int v12; // ecx
  QDate *v13; // eax
  bool v14; // al
  int v15; // ecx
  int v16; // eax
  int v17; // ecx
  const struct QString *v18; // edi
  int v19; // ecx
  char v20; // bl
  int v21; // esi
  int *v22; // edi
  int v23; // esi
  int v24; // ebx
  int *v25; // eax
  int v26; // eax
  _DWORD *v27; // edi
  int v28; // ecx
  int v29; // ecx
  int v30; // esi
  struct QListData::Data *v31; // ebx
  int v32; // edi
  void **i; // esi
  struct QListData::Data *v34; // ebx
  int v35; // edi
  void **j; // esi
  int v38; // [esp-8h] [ebp-54h]
  const struct ZPrintable *v39; // [esp-4h] [ebp-50h]
  void **v40; // [esp+10h] [ebp-3Ch]
  const struct QString *v41; // [esp+14h] [ebp-38h]
  int v42; // [esp+18h] [ebp-34h]
  char v43; // [esp+1Ch] [ebp-30h]
  char v44; // [esp+20h] [ebp-2Ch]
  char v45; // [esp+28h] [ebp-24h]
  const struct QString *v46; // [esp+30h] [ebp-1Ch]
  int *v47; // [esp+34h] [ebp-18h]
  QString *v48; // [esp+38h] [ebp-14h]
  int v49; // [esp+3Ch] [ebp-10h]
  int v50; // [esp+48h] [ebp-4h]

  pThis = this;
  v48 = this;
  QString::QString(this, Memory);
  v50 = 0;
  if ( pUserName )
    v5 = strlen((const char *)pUserName);
  else
    v5 = -1;
  *((_DWORD *)pThis + 1) = QString::fromAscii_helper(pUserName, v5);// 用户名
  v6 = (const struct QString *)operator new(0x10u);// 分配16个字节
  Memory = v6;
  LOBYTE(v50) = 2;
  if ( v6 )
    v7 = sub_100010FA((int)v6);
  else
    v7 = 0;
  *((_DWORD *)pThis + 2) = v7;
  *((_WORD *)pThis + 6) = 0;
  *((_BYTE *)pThis + 14) = 0;
  *((_DWORD *)pThis + 4) = 4;
  *((_DWORD *)pThis + 5) = 1;
  QDate::QDate((QString *)((char *)pThis + 24));// 时间?
  v47 = (int *)((char *)pThis + 32);
  *v47 = QHashData::shared_null;
  v49 = QListData::shared_null;
  v39 = (QString *)((char *)pThis + 4);
  v38 = (int)pThis + 32;
  LOBYTE(v50) = 4;
  sub_10001974((QListData *)&v38, (int)&v49);
  v8 = sub_10001479(*((char **)pThis + 2), (int)pThis, a3, v38, (int)v39);
  *((_BYTE *)pThis + 12) = v8;
  if ( v8 )
  {
    *((_BYTE *)pThis + 14) = 1;
  }
  else
  {
    v9 = *((_DWORD *)pThis + 2);
    v10 = sub_1000105A(pThis);
    *((_BYTE *)pThis + 14) = v10;
    if ( v10 && (v11 = *((_DWORD *)pThis + 2), (unsigned __int8)sub_100015D7(pThis, 6)) )
    {
      v12 = *((_DWORD *)pThis + 2);
      *((_BYTE *)pThis + 13) = sub_100010DC(pThis);
    }
    else
    {
      *((_BYTE *)pThis + 13) = 0;
    }
  }
  v13 = sub_1000169F(*((_DWORD **)pThis + 2), (int)&v45, (int)pThis);// 计算过期时间
  *((_DWORD *)pThis + 6) = *(_DWORD *)v13;      // date_lock 0是永不过期
  *((_DWORD *)pThis + 7) = *((_DWORD *)v13 + 1);// version_lock
  v14 = *((_QWORD *)pThis + 3) < *(_QWORD *)QDate::currentDate(&v44);// 判断许可证是否过期
  *((_BYTE *)pThis + 13) = v14;
  if ( v14 )
    *((_BYTE *)pThis + 12) = 0;                 // license_ok赋值false了
  v15 = *((_DWORD *)pThis + 2);
  v16 = sub_1000185C(pThis);
  v17 = *((_DWORD *)pThis + 2);
  v39 = pThis;
  *((_DWORD *)pThis + 5) = v16;
  v18 = 0;
  *((_DWORD *)pThis + 4) = sub_1000182A(v39);
  Memory = 0;
  a3 = 0;
  do
  {
    pUserName = QListData::shared_null;
    LOBYTE(v50) = 5;
    v46 = v18;
    sub_1000160E(&v46);
    v19 = *((_DWORD *)pThis + 2);
    v20 = sub_100015D7(pThis, v18);
    v21 = sub_1000150F(v18);
    ZPrintable::ZPrintable((ZPrintable *)&v40);
    v40 = &FeatureDescriptor::`vftable';
    v41 = v18;
    v42 = v21;
    v43 = v20;
    v22 = v47;
    LOBYTE(v50) = 6;
    sub_100017A3(v47);
    v23 = *v22;
    v24 = a3 ^ *(_DWORD *)(*v22 + 28);
    v39 = (const struct ZPrintable *)(a3 ^ *(_DWORD *)(*v22 + 28));
    v25 = sub_10001032(v22, (int)&Memory, (int)v39);
    a3 = (unsigned int)v25;
    v26 = *v25;
    if ( v26 == v23 )
    {
      if ( *(_DWORD *)(v23 + 12) >= *(_DWORD *)(v23 + 24) )
      {
        QHashData::rehash((QHashData *)v23, *(signed __int16 *)(v23 + 22) + 1);
        v23 = *v22;
        a3 = (unsigned int)sub_10001032(v22, (int)&Memory, v24);
      }
      v27 = QHashData::allocateNode((QHashData *)v23, 4);
      v28 = *(_DWORD *)a3;
      v27[2] = Memory;
      *v27 = v28;
      v39 = (const struct ZPrintable *)&v40;
      v27[1] = v24;
      ZPrintable::ZPrintable((ZPrintable *)(v27 + 3), v39);
      v29 = (int)v47;
      v27[3] = &FeatureDescriptor::`vftable';
      v27[4] = v41;
      v27[5] = v42;
      *((_BYTE *)v27 + 24) = v43;
      *(_DWORD *)a3 = v27;
      ++*(_DWORD *)(*(_DWORD *)v29 + 12);
    }
    else
    {
      v30 = v26 + 12;
      ZPrintable::ZPrintable((ZPrintable *)(v26 + 12), (const struct ZPrintable *)&v40);
      *(_DWORD *)v30 = &FeatureDescriptor::`vftable';
      *(_DWORD *)(v30 + 4) = v41;
      *(_DWORD *)(v30 + 8) = v42;
      *(_BYTE *)(v30 + 12) = v43;
    }
    ZPrintable::~ZPrintable((ZPrintable *)&v40);
    LOBYTE(v50) = 7;
    if ( !*(_DWORD *)pUserName
      || *(_DWORD *)pUserName != -1 && _InterlockedExchangeAdd((volatile signed __int32 *)pUserName, 0xFFFFFFFF) == 1 )
    {
      v31 = (struct QListData::Data *)pUserName;
      v32 = pUserName + 4 * (*(_DWORD *)(pUserName + 8) + 4);
      for ( i = (void **)(pUserName + 4 * (*(_DWORD *)(pUserName + 12) + 4)); i != (void **)v32; sub_10001807(*i) )
      {
        --i;
        v39 = (const struct ZPrintable *)4;
      }
      QListData::dispose(v31);
    }
    pThis = v48;
    v18 = (const struct QString *)((char *)Memory + 1);
    Memory = v18;
    a3 = (unsigned int)v18;
  }
  while ( (signed int)v18 < 15 );
  LOBYTE(v50) = 8;
  if ( !*(_DWORD *)v49
    || *(_DWORD *)v49 != -1 && _InterlockedExchangeAdd((volatile signed __int32 *)v49, 0xFFFFFFFF) == 1 )
  {
    v34 = (struct QListData::Data *)v49;
    v35 = v49 + 4 * (*(_DWORD *)(v49 + 8) + 4);
    for ( j = (void **)(v49 + 4 * (*(_DWORD *)(v49 + 12) + 4)); j != (void **)v35; sub_10001807(*j) )
    {
      --j;
      v39 = (const struct ZPrintable *)4;
    }
    QListData::dispose(v34);
  }
  return v48;
}
QDate *__thiscall sub_1000169F(_DWORD *this, int a1, int a2)
{
  return sub_1001D510(this, (QDate *)a1, a2);
}

QDate *__thiscall sub_1001D510(_DWORD *this, QDate *a2, int a3)
{
  _DWORD *v3; // edi
  int v4; // esi
  QString *v5; // eax
  int v6; // eax
  int v7; // eax
  int expiredDay; // ebx
  int v9; // eax
  int v10; // eax
  int expiredMonth; // edi
  int v12; // eax
  int v13; // eax
  int expiredYear; // esi
  char v16; // [esp+10h] [ebp-1Ch]
  _DWORD *v17; // [esp+14h] [ebp-18h]
  char v18; // [esp+18h] [ebp-14h]
  char v19; // [esp+1Ch] [ebp-10h]
  int v20; // [esp+28h] [ebp-4h]

  v3 = this;
  v17 = this;
  v4 = a3;
  QString::operator=(this + 2, a3);
  v5 = sub_10001C2B(v3, (int)&v18, v4);
  QString::operator=(v3 + 3, v5);
  QString::~QString((QString *)&v18);
  sub_10001C2B(v3, (int)&v19, v4);
  v20 = 0;
  QString::mid(&v19, &a3, 10, 16);
  LOBYTE(v20) = 1;
  v6 = QString::mid(&a3, &v18, 0, 5);
  LOBYTE(v20) = 2;
  v7 = sub_10001604(v6);                        // 计算过期时间 日
  LOBYTE(v20) = 1;
  expiredDay = v7;
  QString::~QString((QString *)&v18);
  v9 = QString::mid(&a3, &v18, 5, 4);
  LOBYTE(v20) = 3;
  v10 = sub_10001604(v9);                       // 计算过期时间 月
  LOBYTE(v20) = 1;
  expiredMonth = v10;
  QString::~QString((QString *)&v18);
  v12 = QString::mid(&a3, &v16, 9, 7);
  LOBYTE(v20) = 4;
  v13 = sub_10001604(v12);                      // 计算过期时间 年
  LOBYTE(v20) = 1;
  expiredYear = v13 + 2000;
  QString::~QString((QString *)&v16);
  QDate::QDate(a2, expiredYear, expiredMonth, expiredDay);// 过期时间
  QString::~QString((QString *)&a3);
  QString::~QString((QString *)&v19);
  return a2;
}

到此真相大白了,我本想改成9999年,但是32位程序最大日期是:2038年01月19日

因此我改成了2038年01月01日,还有种修改方法,在判断是否过期的地方,我们改成永不过期就行。

注:OD分析时,分析zendserver\ZendServer\php\7.4\bin\php-cgi.exe就好

为了关闭zend server替换文件,可以关闭服务:ZendApache

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

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

相关文章

C# NX二次开发:在多个体的模型中如何实现拉伸操作布尔减

大家好&#xff0c;今天接着上一篇拉伸文章去讲。 UF_MODL_create_extruded1 (view source) uf_list_p_tobjectsInputList of objects to be extruded.char *taper_angleInputTaper angle (in degrees).char *limit [ 2 ]InputLimit of extrusion. This is declared as: char …

15 | 定义简洁架构 Store 层的数据类型

提示&#xff1a; 所有体系课见专栏&#xff1a;Go 项目开发极速入门实战课&#xff1b;欢迎加入 云原生 AI 实战 星球&#xff0c;12 高质量体系课、20 高质量实战项目助你在 AI 时代建立技术竞争力&#xff08;聚焦于 Go、云原生、AI Infra&#xff09;&#xff1b;本节课最终…

2.3 滑动窗口专题:最大连续1的个数 III(LeetCode 1004)

1. ​题目链接 1004. 最大连续1的个数 III - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/max-consecutive-ones-iii/ 2. ​题目描述 给定一个二进制数组 nums 和一个整数 k&#xff0c;允许将最多 k 个 0 翻转为 1&#xff0c;求翻转后最长的连续 1 …

【微服务】Nacos 配置动态刷新(简易版)(附配置)

文章目录 1、实现方法2、配置依赖 yaml3、验证效果 1、实现方法 环境&#xff1a;Nacos、Java、SpringBoot等 主要是在boostrap.yaml中的data-id属性下配置refresh:true来实现动态更新 2、配置依赖 yaml 具体的版本参考官方的说明&#xff1a;官方版本说明 <!--读取boo…

六十天前端强化训练之第二十天React Router 基础详解

欢迎来到编程星辰海的博客讲解 看完可以给一个免费的三连吗&#xff0c;谢谢大佬&#xff01; 目录 一、核心概念 1.1 核心组件 1.2 路由模式对比 二、核心代码示例 2.1 基础路由配置 2.2 动态路由示例 2.3 嵌套路由实现 2.4 完整示例代码 三、关键功能实现效果 四、…

用 DeepSeek 构建 Vue.js 底层架构:高效协作与问题解决实践

文章目录 1. **DeepSeek 与 Vue.js 的完美协作**2. **问题背景**3. **问题分析与解决**3.1 **动态路由未正确生成**3.2 **路由路径配置错误**3.3 **路由嵌套问题**3.4 **通配符路由未配置** 4. **DeepSeek 的核心价值** 在现代前端开发中&#xff0c;Vue.js 以其简洁的语法和灵…

深入探讨RAID 5的性能与容错能力:实验与分析(磁盘阵列)

前言—— 本实验旨在探讨 RAID 5 的性能和容错能力。通过创建 RAID 5 阵列并进行一系列读写性能测试及故障模拟&#xff0c;我们将观察 RAID 5 在数据冗余和故障恢复方面的表现&#xff0c;以验证其在实际应用中的可靠性和效率。 首先说明&#xff1a;最少三块硬盘, 使用 4 块…

蓝桥杯备赛-二分-技能升级

问题描述 小蓝最近正在玩一款 RPG 游戏。他的角色一共有 NN 个可以加攻击力的技能。 其中第 ii 个技能首次升级可以提升 AiAi​ 点攻击力, 以后每次升级增加的点数 都会减少 Bi。「AiBi⌉Bi​。「Bi​Ai​​⌉ (上取整) 次之后, 再升级该技能将不会改变攻击力。 现在小蓝可以…

电子招采软件系统,如何实现10年可追溯审计

一、在当前经济环境下&#xff0c;中小企业面临着巨大的生存压力&#xff0c;传统产业的数字化转型迫在眉睫。AI技术为企业的低成本高效发展提供了新机会&#xff0c;混合办公成为新常态&#xff0c;数据安全法的深入落实则进一步推动企业重视数据安全。区块链存证技术凭借独特…

Ubuntu从源代码编译安装QT

1. 下载源码 wget https://download.qt.io/official_releases/qt/5.15/5.15.2/single/qt-everywhere-src-5.15.2.tar.xz tar xf qt-everywhere-src-5.15.2.tar.xz cd qt-everywhere-src-5.15.22. 安装依赖库 sudo apt update sudo apt install build-essential libgl1-mesa-d…

X86 RouterOS 7.18 设置笔记七:不使用Upnp的映射方法

X86 j4125 4网口小主机折腾笔记五&#xff1a;PVE安装ROS RouterOS X86 RouterOS 7.18 设置笔记一&#xff1a;基础设置 X86 RouterOS 7.18 设置笔记二&#xff1a;网络基础设置(IPV4) X86 RouterOS 7.18 设置笔记三&#xff1a;防火墙设置(IPV4) X86 RouterOS 7.18 设置笔记四…

数字隔离器,如何提升储能系统的安全与效能?

随着全球对光伏、风电等可再生能源需求的持续增长&#xff0c;在全球能源转型的浪潮中&#xff0c;储能技术凭借着可平衡能源供需、提高能源利用效率等优势&#xff0c;已成为实现 “双碳” 目标的核心支撑。据国家能源局公布数据显示&#xff0c;截至2024年底&#xff0c;我国…

基于UniApp + Vue3开发的智能汉字转拼音工具

基于UniApp Vue3开发的智能汉字转拼音工具 项目简介 这是一个基于 UniApp Vue3 开发的智能汉字转拼音工具&#xff0c;前端使用 Vue3 构建界面&#xff0c;后端采用 Classic ASP 提供接口支持&#xff0c;通过 pinyin-pro 库实现精准的中文转拼音功能。本工具支持以下特性&…

PyTorch 深度学习实战(14):Deep Deterministic Policy Gradient (DDPG) 算法

在上一篇文章中&#xff0c;我们介绍了 Proximal Policy Optimization (PPO) 算法&#xff0c;并使用它解决了 CartPole 问题。本文将深入探讨 Deep Deterministic Policy Gradient (DDPG) 算法&#xff0c;这是一种用于连续动作空间的强化学习算法。我们将使用 PyTorch 实现 D…

Angular由一个bug说起之十四:SCSS @import 警告与解决⽅案

SCSS import 警告与解决⽅案 ⚠ 警告信息 在 SCSS 中&#xff0c;使⽤ import 可能会产⽣以下警告&#xff1a; Deprecation Warning: Sass import rules are deprecated and will be removed in Dart Sass 3.0.0. ? 为什么会有这个警告&#xff1f; Sass 官⽅已经废弃 imp…

PyTorch系列教程:基于LSTM构建情感分析模型

情感分析是一种强大的自然语言处理&#xff08;NLP&#xff09;技术&#xff0c;用于确定文本背后的情绪基调。它常用于理解客户对产品或服务的意见和反馈。本文将介绍如何使用PyTorch和长短期记忆网络&#xff08;LSTMs&#xff09;创建一个情感分析管道&#xff0c;LSTMs在处…

SEO新手基础优化三步法

内容概要 在网站优化的初始阶段&#xff0c;新手常因缺乏系统性认知而陷入技术细节的误区。本文以“三步法”为核心框架&#xff0c;系统梳理从关键词定位到内容布局、再到外链构建的完整优化链路。通过拆解搜索引擎工作原理&#xff0c;重点阐明基础操作中容易被忽视的底层逻…

Tcp网络通信的基本流程梳理

先来一张经典的流程图 接下介绍一下大概流程&#xff0c;各个函数的参数大家自己去了解加深一下印象 服务端流程 1.创建套接字&#xff1a;使用 socket 函数创建一个套接字&#xff0c;这个套接字后续会被用于监听客户端的连接请求。 需要注意的是&#xff0c;服务端一般有俩…

PHP函数缺陷详解

无问社区-官网&#xff1a;http://www.wwlib.cn 本期无人投稿&#xff0c;欢迎大家投稿&#xff0c;投稿可获得无问社区AI大模型的使用红包哦&#xff01; 无问社区&#xff1a;网安文章沉浸式免费看&#xff01; 无问AI大模型不懂的问题随意问&#xff01; 全网网安资源智…

深度学习GRU模型原理

一、介绍 门控循环单元&#xff08;Gated Recurrent Unit, GRU&#xff09; 是一种改进的循环神经网络&#xff08;RNN&#xff09;&#xff0c;专为解决传统RNN的长期依赖问题&#xff08;梯度消失/爆炸&#xff09;而设计。其核心是通过门控机制动态控制信息的流动。与LSTM相…