>php教程 >php手册 >用户登录之cookie信息安全一二事,cookie信息安全

用户登录之cookie信息安全一二事,cookie信息安全

WBOY
WBOY원래의
2016-06-13 09:16:141204검색

用户登录之cookie信息安全一二事,cookie信息安全

大家都知道用户登陆后,用户信息一般会选择保存在cookie里面,因为cookie是保存客户端,
并且cookie可以在客户端用浏览器自由更改,这样将会造成用户cookie存在伪造的危险,从而可能使伪造cookie者登录任意用户的账户。

下面就说说平常一些防止用户登录cookie信息安全的方法:

一、cookie信息加密法
cookie信息加密法即用一种加密方法,加密用户信息,然后在存入cookie,这样伪造者即使得到cookie也只能在cookie有效期内对这个cookie利用,无法另外伪造cookie信息。

这里附上一个加密函数: 

<!--?<span>php

</span><span>function</span> authcode(<span>$string</span>, <span>$operation</span> = 'DECODE', <span>$key</span> = '', <span>$expiry</span> = 0<span>) {   

    </span><span>//</span><span> 动态密匙长度,相同的明文会生成不同密文就是依靠动态密匙   </span>

    <span>$ckey_length</span> = 4<span>;   

       

    </span><span>//</span><span> 密匙   </span>

    <span>$key</span> = <span>md5</span>(<span>$key</span> ? <span>$key</span> : <span>$GLOBALS</span>['discuz_auth_key'<span>]);   

       

    </span><span>//</span><span> 密匙a会参与加解密   </span>

    <span>$keya</span> = <span>md5</span>(<span>substr</span>(<span>$key</span>, 0, 16<span>));   

    </span><span>//</span><span> 密匙b会用来做数据完整性验证   </span>

    <span>$keyb</span> = <span>md5</span>(<span>substr</span>(<span>$key</span>, 16, 16<span>));   

    </span><span>//</span><span> 密匙c用于变化生成的密文   </span>

    <span>$keyc</span> = <span>$ckey_length</span> ? (<span>$operation</span> == 'DECODE' ? <span>substr</span>(<span>$string</span>, 0, <span>$ckey_length</span>): 

<span>substr</span>(<span>md5</span>(<span>microtime</span>()), -<span>$ckey_length</span>)) : ''<span>;   

    </span><span>//</span><span> 参与运算的密匙   </span>

    <span>$cryptkey</span> = <span>$keya</span>.<span>md5</span>(<span>$keya</span>.<span>$keyc</span><span>);   

    </span><span>$key_length</span> = <span>strlen</span>(<span>$cryptkey</span><span>);   

    </span><span>//</span><span> 明文,前10位用来保存时间戳,解密时验证数据有效性,10到26位用来保存$keyb(密匙b), 

//解密时会通过这个密匙验证数据完整性   

    // 如果是解码的话,会从第$ckey_length位开始,因为密文前$ckey_length位保存 动态密匙,以保证解密正确   </span>

    <span>$string</span> = <span>$operation</span> == 'DECODE' ? <span>base64_decode</span>(<span>substr</span>(<span>$string</span>, <span>$ckey_length</span>)) :  

<span>sprintf</span>('%010d', <span>$expiry</span> ? <span>$expiry</span> + <span>time</span>() : 0).<span>substr</span>(<span>md5</span>(<span>$string</span>.<span>$keyb</span>), 0, 16).<span>$string</span><span>;   

    </span><span>$string_length</span> = <span>strlen</span>(<span>$string</span><span>);   

    </span><span>$result</span> = ''<span>;   

    </span><span>$box</span> = <span>range</span>(0, 255<span>);   

    </span><span>$rndkey</span> = <span>array</span><span>();   

    </span><span>//</span><span> 产生密匙簿   </span>

    <span>for</span>(<span>$i</span> = 0; <span>$i</span> <= 255; <span>$i</span>++<span>) {   

        </span><span>$rndkey</span>[<span>$i</span>] = <span>ord</span>(<span>$cryptkey</span>[<span>$i</span> % <span>$key_length</span><span>]);   

    }   

    </span><span>//</span><span> 用固定的算法,打乱密匙簿,增加随机性,好像很复杂,实际上对并不会增加密文的强度   </span>

    <span>for</span>(<span>$j</span> = <span>$i</span> = 0; <span>$i</span> < 256; <span>$i</span>++<span>) {   

        </span><span>$j</span> = (<span>$j</span> + <span>$box</span>[<span>$i</span>] + <span>$rndkey</span>[<span>$i</span>]) % 256<span>;   

        </span><span>$tmp</span> = <span>$box</span>[<span>$i</span><span>];   

        </span><span>$box</span>[<span>$i</span>] = <span>$box</span>[<span>$j</span><span>];   

        </span><span>$box</span>[<span>$j</span>] = <span>$tmp</span><span>;   

    }   

    </span><span>//</span><span> 核心加解密部分   </span>

    <span>for</span>(<span>$a</span> = <span>$j</span> = <span>$i</span> = 0; <span>$i</span> < <span>$string_length</span>; <span>$i</span>++<span>) {   

        </span><span>$a</span> = (<span>$a</span> + 1) % 256<span>;   

        </span><span>$j</span> = (<span>$j</span> + <span>$box</span>[<span>$a</span>]) % 256<span>;   

        </span><span>$tmp</span> = <span>$box</span>[<span>$a</span><span>];   

        </span><span>$box</span>[<span>$a</span>] = <span>$box</span>[<span>$j</span><span>];   

        </span><span>$box</span>[<span>$j</span>] = <span>$tmp</span><span>;   

        </span><span>//</span><span> 从密匙簿得出密匙进行异或,再转成字符   </span>

        <span>$result</span> .= <span>chr</span>(<span>ord</span>(<span>$string</span>[<span>$i</span>]) ^ (<span>$box</span>[(<span>$box</span>[<span>$a</span>] + <span>$box</span>[<span>$j</span>]) % 256<span>]));   

    }   

    </span><span>if</span>(<span>$operation</span> == 'DECODE'<span>) {  

        </span><span>//</span><span> 验证数据有效性,请看未加密明文的格式   </span>

        <span>if</span>((<span>substr</span>(<span>$result</span>, 0, 10) == 0 || <span>substr</span>(<span>$result</span>, 0, 10) - <span>time</span>() --> 0) &&  

<span>substr</span>(<span>$result</span>, 10, 16) == <span>substr</span>(<span>md5</span>(<span>substr</span>(<span>$result</span>, 26).<span>$keyb</span>), 0, 16<span>)) {   

            </span><span>return</span> <span>substr</span>(<span>$result</span>, 26<span>);   

        } </span><span>else</span><span> {   

            </span><span>return</span> ''<span>;   

        }   

    } </span><span>else</span><span> {   

        </span><span>//</span><span> 把动态密匙保存在密文里,这也是为什么同样的明文,生产不同密文后能解密的原因   

        // 因为加密后的密文可能是一些特殊字符,复制过程可能会丢失,所以用base64编码   </span>

        <span>return</span> <span>$keyc</span>.<span>str_replace</span>('=', '', <span>base64_encode</span>(<span>$result</span><span>));   

    }   

} 


 

</span><span>$str</span> = 'abcdef'<span>; 

</span><span>$key</span> = 'www.phpskill.com'<span>; 

</span><span>echo</span> <span>$jm</span> = authcode(<span>$str</span>,'ENCODE',<span>$key</span>,0); <span>//</span><span>加密 </span>
<span>echo</span> "
"<span>;

</span><span>echo</span> authcode(<span>$jm</span> ,'DECODE',<span>$key</span>,0); <span>//</span><span>解密</span>

?>

这样当设置用户信息的cookie时,就无法对其进行伪造:

<!--?<span>php

</span><span>$user</span> = <span>array</span>("uid"=--><span>$uid</span>,"username"=><span>$username</span><span>);

</span><span>$user</span> = <span>base64_encode</span>(<span>serialize</span>(<span>$user</span><span>));
</span><span>$user</span> =  authcode(<span>$user</span>,'ENCODE','www.phpskill.com',0); <span>//</span><span>加密 </span>
<span>setcookie</span>("user",<span>$user</span>,<span>time</span>()+3600*24<span>);

</span>?>

二、用加密令牌对cookie进行保护

<span>$hash</span> = <span>md5</span>(<span>$uid</span>.<span>time</span>());<span>//</span><span>加密令牌值</span>
<span>$hash_expire</span> =<span>time</span>()+3600*24;<span>//</span><span>加密令牌值为一天有效期</span>
<span>$user</span> = <span>array</span>("uid"=><span>$uid</span>,"username"=><span>$username</span>,"hash"=><span>$hash</span><span>);

</span><span>$user</span> = <span>base64_encode</span>(<span>serialize</span>(<span>$user</span><span>));

</span><span>setcookie</span>("user",<span>$user</span>,<span>$hash_expr</span><span>);

然后把</span><span>$hash和$hash_expire</span> 存入member表中hash和hash_expire对应字段中,<span>也可以存入nosql,session

用户伪造cookie时,hash无法伪造</span>,<span>伪造的hash和数据库中的不一致

用户每次登陆,这个hash_expire有效期内不更新hash值,过期则更新</span>

 

php纯技术交流群: 323899029

原文转载于:http://www.phpskill.com/html/show-1-4424-1.html

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.