搜尋
首頁後端開發php教程PHP的安全實例分享

PHP的安全實例分享

Mar 13, 2018 am 09:45 AM
php分享實例

一個有趣的請求已開啟針對PHP來作出bin2hex()一定的時間。這導致了一些關於郵件列表的有趣討論(甚至讓我回覆:-X)。 PHP在遠端計時攻擊方面的報告非常好,但他們談論了字串比較。我想談談其他類型的計時攻擊。

什麼是遠端定時攻擊?

好的,讓我們假設你有以下程式碼:

function containsTheLetterC($string) {
    for ($i = 0; $i < strlen($string); $i++) {
        if ($string[$i] == "c") {
            return true;
        }
        sleep(1);
    }
    return false;}var_dump(containsTheLetterC($_GET[&#39;query&#39;]));

說出它的作用應該很容易。它接受query來自URL 的參數,然後逐字逐句通過它,檢查它是否是小寫字母c。如果是,它會返回。如果不是,它睡一秒鐘。

所以讓我們想像我們通過了字串?query=abcdef。我們預計檢查將花費2秒鐘。

現在,讓我們想像一下,我們不知道要找哪封信。讓我們想像一下,這"c"是一個我們不知道的不同價值。你能想出如何弄清楚那封信是什麼嗎?

這很簡單。我們構造一個字串"abcdefghijklmnopqrstuvwxyzABCDEFGHIJ....",並將其傳入。然後我們可以計算返回需要多長時間。然後我們知道哪個角色不同!

這是定時攻擊的基礎。

但是我們沒有在現實世界中看起來像那樣的程式碼。讓我們來看一個真實的例子:

$secret = "thisismykey";if ($_GET[&#39;secret&#39;] !== $secret) {
    die("Not Allowed!");}

為了理解發生了什麼,我們需要is_identical_function從PHP的原始碼看到。如果你看看這個函數,你會發現結果是由以下情況定義的:

case IS_STRING:
    if (Z_STR_P(op1) == Z_STR_P(op2)) {
        ZVAL_BOOL(result, 1);
    } else {
        ZVAL_BOOL(result, (Z_STRLEN_P(op1) == Z_STRLEN_P(op2))
        && (!memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1))));
    }
    break;

該if如果兩個變數都相同的變數(如主要是要求$secret === $secret)。在我們的情況下,這是不可能的,所以我們只需要看else區塊。

Z_STRLEN_P(op1) == Z_STRLEN_P(op2)

所以如果字串長度不匹配,我們立即返回。

這意味著如果字串的長度相同,就可以完成更多的工作!

如果我們花費多長時間來執行不同的長度,我們會看到類似這樣的內容:

##平均時間70.012410.011520.011910.01194#0.011910.01194#80.011510.012120.011890.0118490.011140.012510.011750.01180100.012120.011710.011200.0119711#0.012100.012310.012100.012310.01211##0.01175 130.011420.011740.01251#0.01189#140.012510.011210.01141
長度 時間運行1 時間跑2 時間運行3
# #0.01216 0.01219 #12 0.01121
#0.01194
###0.01171############

如果您忽略平均列,您会注意到似乎没有多少模式。这些数字都在彼此的原因之内。

但是,如果您平均进行多次跑步,您就会注意到一种模式。你会注意到长度11需要更长的时间(略),然后是其他长度。

这个例子非常夸张。但它说明了这一点。它已经显示了可以使用约49000(所以49000次尝试,而不是在上述实施例3)的样品大小远程检测的差异在时间缩短到约15纳秒。

但是,我们发现了这个长度。那不会给我们太多的收入......但第二部分呢?那怎么样memcmp(...)?

如果我们看的执行memcmp()::

int memcmp(const void *s1, const void *s2, size_t n){
    unsigned char u1, u2;
    for ( ; n-- ; s1++, s2++) {
        u1 = * (unsigned char *) s1;
        u2 = * (unsigned char *) s2;
        if ( u1 != u2) {
            return (u1-u2);
        }
    }
    return 0;}

等一下!这返回两个字符串之间的第一个区别!

所以一旦我们确定了字符串的长度,我们可以尝试不同的字符串开始检测差异:

axxxxxxxxxxbxxxxxxxxxxcxxxxxxxxxxdxxxxxxxxxx...yxxxxxxxxxxzxxxxxxxxxx

并通过相同的技术,发现与“txxxxxxxxxx”的差异比其他时间略长。

为什么?

让我们看看在memcmp中一步一步发生的事情。

  1. 首先,它查看每个字符串的第一个字符。

    如果第一个字符不同,请立即返回。

  2. 接下来,看看每个字符串的第二个字符。

    如果它们不同,立即返回。

  3. 等等。

因此"axxxxxxxxxx",它只执行第一步(因为我们正在比较的字符串"thisismykey")。但是"txxxxxxxxxx",第一步和第二步相匹配。所以它做更多的工作,因此需要更长的时间。

所以一旦你看到了,你知道t是第一个字符。

那么这只是一个重复这个过程的问题:

taxxxxxxxxxtbxxxxxxxxxtcxxxxxxxxxtdxxxxxxxxx...tyxxxxxxxxxtzxxxxxxxxx

为每个角色做到这一点,你就完成了。你已经成功推断出一个秘密!

防止比较攻击

所以这是一个基本的比较攻击。==并且===在PHP中都容易受到攻击。

有两种基本的防御方法。

首先是手动比较两个字符串,并且总是比较每个字符(这是我以前的博客文章中的函数:

/**
 * A timing safe equals comparison
 *
 * @param string $safe The internal (safe) value to be checked
 * @param string $user The user submitted (unsafe) value
 *
 * @return boolean True if the two strings are identical.
 */function timingSafeEquals($safe, $user) {
    $safeLen = strlen($safe);
    $userLen = strlen($user);
    if ($userLen != $safeLen) {
        return false;
    }
    $result = 0;
    for ($i = 0; $i < $userLen; $i++) {
        $result |= (ord($safe[$i]) ^ ord($user[$i]));
    }
    // They are only identical strings if $result is exactly 0...
    return $result === 0;}

第二个是使用内置的PHP hash_equals() function。这是在5.6中添加的,与上面的代码做同样的事情。

注:一般情况下,它是不是能够防止长度泄漏。所以可以泄漏这个长度。重要的部分是它不会泄漏关于两个字符串的差异的信息。

其他类型的计时攻击 - 索引查找

那就是比较。这是相当好的覆盖。但是让我们来谈谈索引查找:

如果您有一个数组(或字符串),并且使用秘密信息作为索引(键),则可能会泄漏有关该键的信息。

为了理解为什么,我们需要了解一下CPU如何处理内存。

通常,CPU具有固定宽度的寄存器。把这些想象成小变量。在现代处理器上,这些寄存器可能是64位(8字节)宽。这意味着CPU可以在一次处理的最大变量是8个字节。(注意:这是不正确的,因为大多数处理器都有基于向量的操作,例如SIMD,它允许它与更多的数据交互。对于这个讨论来说,尽管这并不重要)。

那么当你想读一个长度为16字节的字符串时会发生什么呢?

那么,CPU需要加载它块。根据操作的不同,它可能一次加载8个字节的字符串,并且一次对它操作8个字节。或者更常见的是,它一次处理一个字节。

所以这意味着它需要从某处获取字符串的其余部分。这个“某处”是主存(RAM)。但记忆非常缓慢。像真的很慢。大约100ns。这是我们的15纳秒阈值。

而且由于主内存非常慢,所以CPU在CPU本身上只有很少的内存空间来充当缓存。实际上,它们通常有两种类型的缓存。它们具有特定于每个核心(每个核心都有自己的L1高速缓存)的L1高速缓存,也是特定于核心的L2高速缓存,以及经常在单个芯片上的所有核心之间共享的L3高速缓存。为什么3层?由于速度:

#60 - 100奈秒
記憶體類型 尺寸 潛伏
L1快取 32KB 0.5奈秒
L2快取 256KB 2.5 ns
L3快取 4-16MB 10-20奈秒
記憶體
####

所以我们来看看在string[index]C字符串(char \*字符数组)上做了什么。想象一下你有这样的代码:

char character_at_offset(const char *string, size_t offset) {
    return string[offset]}

编译器会将其编译为:

character_at_offset:
    pushq   %rbp    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp    .cfi_def_cfa_register 6
    movq    %rdi, -8(%rbp)
    movq    %rsi, -16(%rbp)
    movq    -16(%rbp), %rax
    movq    -8(%rbp), %rdx
    addq    %rdx, %rax    movzbl  (%rax), %eax
    popq    %rbp    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc

虽然有很多噪音。让我们把它缩小到一个非功能性但更合适的尺寸:

character_at_offset:
    addq    %rdx, %rax    movzbl  (%rax), %eax
    popq    %rbp
    ret

该函数有两个参数,其中一个是指针(字符串的第一个元素),第二个是整数偏移量。它将两者相加以获得我们想要的字符的内存地址。然后,movzbl从该地址移动一个字节并将其存储%eax(其余零也为零)。

那么,CPU如何知道在哪里可以找到那个内存地址呢?

那么,它会遍历高速缓存链,直到找到它。

因此,如果它在L1缓存中,整体操作大约需要0.5 ns。如果它在L2,2.5ns。等等。因此,通过仔细计算信息的时间,我们可以推断出该项目被缓存的位置(或者它是否被缓存)。

值得注意的是,CPU不会缓存单个字节。他们缓存称为线的内存块。现代处理器通常具有64字节宽的高速缓存行。这意味着缓存中的每个条目都是连续的64字节的内存块。

所以,当你进行内存提取时,CPU会将一个64字节的内存块写入缓存行。因此,如果您的movzbl调用需要打到主内存,整个块将被复制到较低的缓存行中。(请注意,这是一个非常简单的事情,但它是为了演示下一步会发生什么)。

现在,这里是真正有趣的地方。

假设我们正在处理一个大字符串。一个不适合二级缓存。所以1MB。

现在,让我们设想一下,我们从基于数字的秘密序列的字符串中提取字节。

通过观察获取字节需要多长时间,我们实际上可以确定关于秘密的信息!

让我们想象我们获取以下偏移量:

  • offset 10

  • offset 1

第一次提取会导致缓存未命中,将从主内存加载到缓存中。

但是第二个fetch(offset 1)将从L1缓存中获取,因为它可能与原来的缓存行(内存块)相同offset 10。所以它很可能是缓存命中。

如果我们然后提取offset 2048,它很可能不在缓存中。

因此,通过仔细观察延迟模式,您可以确定有关偏移序列关系的一些信息。通过多次使用正确的信息来做到这一点,你可以推断出这个秘密。

这被称为缓存时间攻击。

现在看起来真的很牵强,对吧?我的意思是,你有多频繁地获取完美的信息?这怎么可能是实际的。那么,这是100%的实际,并发生在现实世界中。

针对缓存时间攻击的防御:

只有一种防御这种风格攻击的实用方法:

  1. 不要通过秘密索引数组(或字符串)。

这真的很简单。

基于分支的计时攻击

你看过几次类似下面的代码?

$query = "SELECT * FROM users WHERE id = ?";$stmt = $pdo->prepare($query);$stmt->execute([$_POST[&#39;id&#39;]]);$user = $stmt->fetchObject();if ($user && password_verify($_POST[&#39;password&#39;], $user->password)) {
    return true;}return false;

当然,这是安全的?

那里有信息泄漏。

如果您尝试使用不同的用户名,则根据用户名是否存在需要不同的时间。如果password_verify需要0.1秒,您可以简单地测量该差异来确定用户名是否有效。平均而言,对使用用户名的请求将花费比可用用户名更长的时间。

现在,这是一个问题吗?我不知道,这取决于你的要求。许多网站希望保留用户名的秘密,并尽量不公开他们的信息(例如:不说用户名或密码在登录表单中是否无效)。

如果你想保持用户名的秘密,你就不会。

防御基于分支的计时攻击

做到这一点的唯一方法是不分支。但那里有问题。如果你不分支,你如何获得像上面那样的功能?

那么,一个想法是执行以下操作:

$query = "SELECT * FROM users WHERE id = ?";$stmt = $pdo->prepare($query);$stmt->execute([$_POST[&#39;id&#39;]]);$user = $stmt->fetchObject();if ($user) {
    return password_verify($_POST[&#39;password&#39;], $user->password);} else {
    password_verify("", DUMMY_HASH);}return false;

这意味着你password_verify在两种情况下运行。这削减了0.1第二个区别。

但核心计时攻击依然存在。原因在于数据库将返回查询的时间稍微有点不同,以查找找到该用户的查询,以及查找不到的查询。这是因为它在内部执行大量分支和条件逻辑,最终需要通过线路将数据传输回程序。

所以防御这种风格攻击的唯一方法就是不要将您的用户名视为秘密!

关于“随机延迟”的一个注记

许多人在听到定时攻击时,都会想:“呃,我只是随意添加一个延迟!这将工作!“。而事实并非如此。

要理解为什么,让我们来谈谈添加随机延迟时实际发生的情况:

整体执行时间是work + sleep(rand(1, 10))。如果兰德行为良好(这是随机的),那么随着时间的推移,我们可以将其平均。

让我们说这是rand(1, 10)。那么,这意味着当我们平均运行时,平均延迟约为5.相同的平均值加到所有情况下。所以我们需要做的就是每运行一次运行一次以平均噪音。我们运行的次数越多,随机值越倾向于平均。所以我们的信号仍然存在,它只需要稍微更多的数据来对抗噪声。

因此,如果我们需要运行49,000次测试以获得15ns的准确度,那么我们需要大概100,000或1,000,000次测试来获得相同的准确度和随机延迟。或者可能达到100,000,000。但数据仍然存在。

修复漏洞,不要仅仅在它周围增加噪音。

有效的实际延迟

随机延迟不起作用。但我们可以通过两种方式有效地使用延迟。第一个是更有效的,也是我唯一“依靠”的一个。

  1. 延迟取决于用户输入。

    因此,在这种情况下,您可以使用本地密钥对用户输入进行哈希处理,以确定要使用的延迟:

    function delay($input, $secret_key) {
        $hash = crc32(serialize($secret_key . $input . $secret_key));
        // make it take a maximum of 0.1 milliseconds
        time_nanosleep(0, abs($hash % 100000));}

    然后只需将用户输入用于延迟功能。这样,随着用户改变他们的输入,延迟也会改变。但它会以同样的方式改变,使他们无法用统计技术来平均它。

    请注意,我使用过crc32()。这不需要是加密散列函数。由于我们只是派生一个整数,所以我们不需要担心碰撞。如果您希望更安全,您可以用SHA-2功能替换它,但我不确定这是否值得速度损失。

  2. 使操作花费最少时间(夹紧)

    因此,许多人浮现的想法是将操作“夹”到特定的运行时(或者更准确地说,使其至少需要一定的运行时间)。

    function clamp(callable $op, array $args, $time = 100) {
        $start = microtime(true);
        $return = call_user_func_array($op, $args);
        $end = microtime(true);
        // convert float seconds to integer nanoseconds
        $diff = floor((($end - $start) * 1000000000) % 1000000000);
        $sleep = $diff - $time;
        if ($sleep > 0) {
            time_nanosleep(0, $sleep);
        }
        return $return;}

    所以你可以说比较必须花费最少的时间。因此,不要试图比较一直持续的时间,你只需要花时间。

    所以,你可以钳住等于100纳秒(clamp("strcmp", [$secret, $user], 100))。

    这样做,你保护了字符串的第一部分。如果前20个字符花费了100纳秒,那么通过钳位到100纳秒,可以防止那些泄漏的差异。

    但是有一些问题:

  • 它非常脆弱。如果你时间太短,你会失去所有的保护。如果时间过长,可能会在应用程序中增加不必要的延迟(如果不小心,可能会暴露DOS风险)。

  • 它实际上并没有保护任何东西。它只是掩盖了这个问题。我认为这是一种通过默默无闻的安全形式。这并不意味着它没有用或无效。这只是意味着风险。很难知道它是否确实有效地让你更安全,或者让你在夜晚更好地睡觉。当在图层中使用时,它可能是好的。

  • 它不能防止本地攻击者。如果攻击者可以在服务器上获得代码(甚至是未经授权的,在不同的用户帐户上,如共享服务器上),则他们可以查看CPU使用情况,从而可以看到过去的睡眠状况。这是一个延伸,在这种情况下可能会有更有效的攻击,但至少值得注意。

防御DOS攻击

所有这些技术都需要很多请求。它们基于依靠大量数据有效“平均”噪声的统计技术。

这意味着要获得足够的数据来实际执行攻击,攻击者可能需要制造数千,数十万甚至数百万的请求。

如果你正在练习好的DOS保护技术(基于IP的速率限制等),那么你将能够绕过很多这些风格的攻击。

但是DDOS保护难以防范。通过分配流量,防范难度更大。但对攻击者来说也更难,因为他们有更多的噪音需要处理(而不仅仅是本地网段)。所以这并不太实际。

但是就像安全的任何事情一样,纵深防御。即使我们认为这次攻击是不可能的,但如果我们原来的保护失败,仍然值得保护它。深度使用防御,我们可以让自己在各种规模的攻击中更具弹性。

回到点

目前有关PHP内部的一个关于是否使某些核心功能的时序安全与否的线索。正在讨论的具体功能是:

  • bin2hex

  • hex2bin

  • base64_encode

  • base64_decode

  • mcrypt_encrypt

  • mcrypt_decrypt

现在,为什么这些功能?井,bin2hex和base64_encode编码输出到浏览器(编码会话参数例如)当经常使用。然而,更重要的是hex2bin和base64_decode,因为它们可以用于解密秘密信息(就像在将密钥用于加密之前的密钥)。

到目前为止,大多数受访者的共识是,为了获得更多的安全,不值得让它们变得更慢。我同意这一点。

但是,我不同意的是,它会让它们“变慢”。更改比较(从)==到hash_equals较慢是因为它将函数的复杂性(最佳,平均,最差)从O(1, n/2, n)更改为O(n, n, n)。这意味着它将对平均情况下的性能产生重大影响。

但改变编码功能不会影响复杂性。他们将继续O(n)。所以问题是,速度差是多少?那么,我用PHP算法和一个时间安全的标准对bin2hex和hex2bin进行了基准测试,差异不是太显着。编码(bin2hex)大致相同(误差范围),并且解码的差异(hex2bin)大约为0.5μs。对于大约40个字符的字符串,这是5e-10秒多。

对我而言,这足够小,根本不用担心。平均应用程序调用其中一个受影响的函数多少次?也许每一次执行可能?但有什么潜在的好处?这可能是一个漏洞被阻止?

也许吧。我认为没有充足的理由去做这件事,一般而言,这些漏洞在用PHP编写的应用程序类型中将非常困难。但有了这个说法,如果实施过程足够快速(对我来说,0.5μs足够快),那么我认为没有一个重要的理由不去做这个改变。即使它有助于防止所有数百万PHP用户的单一攻击,这是否值得?是。它会阻止单一攻击吗?我不知道(可能不)。

但是,我认为有几项功能必须不断进行时间安全审计:

  • mcrypt_\*

  • hash_\*

  • password_\*

  • openssl_\*

  • md5()

  • sha1()

  • strlen()

  • substr()

基本上,我们所知道的任何东西都会与敏感信息一起使用,或者将在敏感操作中用作原语。

至于字符串函数的其余部分,或者没有必要让它们的时间安全(像lcfirst或strpos),或者它不可能(像trim)或已经完成(像strlen),或者它没有任何业务在PHP(如hebrev)...

跟进

因此,HackerNews和Reddit发布了这篇文章。评论有几个共同的主题,所以我会在这里跟进。我还编辑了帖子内联来解决这些问题。

不可能使代码保持恒定时间

那么,我应该澄清“不变”的含义。在绝对意义上,我并不是指不变的。我的意思是不变的相对于秘密。这意味着时间不会依赖于我们试图保护的数据而改变。因此总体而言,绝对时间可能由于许多原因而波动。但我们不希望我们试图保护的价值影响它。

这是区别:

for ($i = 0; $i < strlen($_GET[&#39;input&#39;]); $i++) {
    $input .= $_GET[&#39;input&#39;][$i];}

这是可变的时间,但泄漏什么是秘密,

$time = 0;for ($i = 0; $i < strlen($_GET[&#39;input&#39;]); $i++) {
    $time += abs(ord($_GET[&#39;input&#39;][$i]) - ord($secret[$i]));}sleep($time);

现在,这是一个荒谬的例子。但它表明,两者都会根据投入改变时间,但也会因我们试图保护的秘密而有所不同。这就是我们说“恒定时间”时的意思,而不是基于秘密的价值而变化。

怎样钳制一个特定的运行时间?

我已经在帖子的主体中解决了上述问题。

不保护DOS的工作?

是。我已经将其添加到防御列表中。但考虑到它对DDOS不起作用(虽然时间差异很难识别),但我不会因为这个原因而忽略它。

这不实用

那么,事实并非如此。有视频和文件和工具以及更多工具和更多论文以及更多视频。

所以如果攻击者一直在谈论这件事情,那肯定是有好处的。

但是,成功利用计时攻击需要很多工作。因此,攻击者通常会寻找更容易和更常见的攻击,例如SQLi,XSS,远程代码执行等,但这实际上取决于更多因素。如果您正在保护博客网站的会话标识符,那么您可能不必担心它。但是,如果您保护用于加密信用卡号码的加密密钥......

从实际的角度来看,我不会担心定时攻击,除非我确信其他潜在的媒介是安全的。就这样说,我认为这很有趣,值得了解。但是像安全和编程中的其他一切一样,这都是关于权衡的。

相关推荐:

对php一些服务器端特性配置,加强php的安全

php安全实例详解

整理了一些关于PHP安全性的知识

以上是PHP的安全實例分享的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
哪些常見問題會導致PHP會話失敗?哪些常見問題會導致PHP會話失敗?Apr 25, 2025 am 12:16 AM

PHPSession失效的原因包括配置錯誤、Cookie問題和Session過期。 1.配置錯誤:檢查並設置正確的session.save_path。 2.Cookie問題:確保Cookie設置正確。 3.Session過期:調整session.gc_maxlifetime值以延長會話時間。

您如何在PHP中調試與會話相關的問題?您如何在PHP中調試與會話相關的問題?Apr 25, 2025 am 12:12 AM

在PHP中調試會話問題的方法包括:1.檢查會話是否正確啟動;2.驗證會話ID的傳遞;3.檢查會話數據的存儲和讀取;4.查看服務器配置。通過輸出會話ID和數據、查看會話文件內容等方法,可以有效診斷和解決會話相關的問題。

如果session_start()被多次調用會發生什麼?如果session_start()被多次調用會發生什麼?Apr 25, 2025 am 12:06 AM

多次調用session_start()會導致警告信息和可能的數據覆蓋。 1)PHP會發出警告,提示session已啟動。 2)可能導致session數據意外覆蓋。 3)使用session_status()檢查session狀態,避免重複調用。

您如何在PHP中配置會話壽命?您如何在PHP中配置會話壽命?Apr 25, 2025 am 12:05 AM

在PHP中配置會話生命週期可以通過設置session.gc_maxlifetime和session.cookie_lifetime來實現。 1)session.gc_maxlifetime控制服務器端會話數據的存活時間,2)session.cookie_lifetime控制客戶端cookie的生命週期,設置為0時cookie在瀏覽器關閉時過期。

使用數據庫存儲會話的優點是什麼?使用數據庫存儲會話的優點是什麼?Apr 24, 2025 am 12:16 AM

使用數據庫存儲會話的主要優勢包括持久性、可擴展性和安全性。 1.持久性:即使服務器重啟,會話數據也能保持不變。 2.可擴展性:適用於分佈式系統,確保會話數據在多服務器間同步。 3.安全性:數據庫提供加密存儲,保護敏感信息。

您如何在PHP中實現自定義會話處理?您如何在PHP中實現自定義會話處理?Apr 24, 2025 am 12:16 AM

在PHP中實現自定義會話處理可以通過實現SessionHandlerInterface接口來完成。具體步驟包括:1)創建實現SessionHandlerInterface的類,如CustomSessionHandler;2)重寫接口中的方法(如open,close,read,write,destroy,gc)來定義會話數據的生命週期和存儲方式;3)在PHP腳本中註冊自定義會話處理器並啟動會話。這樣可以將數據存儲在MySQL、Redis等介質中,提升性能、安全性和可擴展性。

什麼是會話ID?什麼是會話ID?Apr 24, 2025 am 12:13 AM

SessionID是網絡應用程序中用來跟踪用戶會話狀態的機制。 1.它是一個隨機生成的字符串,用於在用戶與服務器之間的多次交互中保持用戶的身份信息。 2.服務器生成並通過cookie或URL參數發送給客戶端,幫助在用戶的多次請求中識別和關聯這些請求。 3.生成通常使用隨機算法保證唯一性和不可預測性。 4.在實際開發中,可以使用內存數據庫如Redis來存儲session數據,提升性能和安全性。

您如何在無狀態環境(例如API)中處理會議?您如何在無狀態環境(例如API)中處理會議?Apr 24, 2025 am 12:12 AM

在無狀態環境如API中管理會話可以通過使用JWT或cookies來實現。 1.JWT適合無狀態和可擴展性,但大數據時體積大。 2.Cookies更傳統且易實現,但需謹慎配置以確保安全性。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中