2013-03-02 21:52 3122人閱讀 評論(0) 收藏 舉報php
對於一箇中型或大型網站,有n個子項目在不一樣的服務器甚至不一樣的IDC部署和運行,SSO(單點登陸)和無SESSION已是必備的功能。在這種狀況下用戶登錄後的身份驗證就會是一個問題。一種簡單的解決辦法就是登錄時將用戶的身份寫入cookie,爲了安全再寫入一個cookie的校驗,防止cookie篡改。linux
1 <?php
2 $secretkey = '1234567890abcdefghi';
3 // …… 取出數據到 $data 的代碼略去
4 if( md5( sha1( $password ) ) == $data['passowrd'] ) { // 登錄成功
5 $_COOKIE['uid'] = 1234;
6 $_COOKIE['nickname'] = 'soga';
7 $_COOKIE['token'] = md5( "uid:1234&nickname:soga&secretkey:1234567890abcdefghi" );
8 }
9 ?>nginx
驗證登錄合法性:web
01 <?php
02 $secretkey = '1234567890abcdefghi';
03
04 if( $_COOKIE['token'] == md5( "uid:{$_COOKIE['uid']}&nickname:{$_COOKIE['nickname']}&secretkey:{$secretkey}" ) ) {
05 $login = true;
06 }
07 else {
08 $login = false;
09 }
10 ?>算法
這樣實現有一些問題存在,密鑰$secretkey會暴露在全部的程序內,存在安全隱患。全部產品的程序中都須要內置token校驗的算法。安全
若是能在webserver層進行校驗,直接告訴應用層校驗結果,就能夠避免上面的問題。找一種webserver上安全、穩定、高性能的實現,而且開發成本低的方案。我選擇的是Nginx + ngx_lua。Nginx的穩定性、高性能搭配Lua的高性能、低成本開發,簡直絕配。服務器
Nginx+ngx_lua的編譯安裝就不在這裏講了。cookie
Nginx 配置:app
1 access_by_lua_file '/dir/test.lua';curl
test.lua 代碼:
01 local secretkey='1234567890abcdefghi'
02 if ngx.var.cookie_uid == nil or ngx.var.cookie_nickname == nil or ngx.var.cookie_token== nil then
03 ngx.req.set_header("Check-Login", "NULL")
04 return
05 end
06
07 local ctoken = ngx.md5('uid:' .. ngx.var.cookie_uid .. '&nickname:' ..ngx.var.cookie_nickname .. '&secretkey:' .. secretkey)
08
09 if ctoken == ngx.var.cookie_token then
10 ngx.req.set_header("Check-Login", "Yes")
11 else
12 ngx.req.set_header("Check-Login", "No")
13 end
14
15 return
而後就能夠測試一下了:
無cookie登錄測試
01 [root@localhost soft]# curl -v "http://yuenshui.com:88/test.php"
02 * About to connect() to yuenshui.com port 88
03 * Trying 122.0.66.162… connected
04 * Connected to yuenshui.com (122.0.66.162) port 88
05 > GET /test.php HTTP/1.1
06 > User-Agent: curl/7.15.5 (x86_64-redhat-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5
07 > Host: yuenshui.com:88
08 > Accept: */*
09 >
10 < HTTP/1.1 200 OK
11 < Server: nginx
12 < Date: Sun, 24 Jun 2012 10:38:09 GMT
13 < Content-Type: application/octet-stream
14 < Transfer-Encoding: chunked
15 < Connection: keep-alive
16 nil
17 <pre>$_SERVER:
18 Array
19 (
20 [TMP] => /tmp
21 [TMPDIR] => /tmp
22 [TEMP] => /tmp
23 [OSTYPE] =>
24 [MACHTYPE] =>
25 [MALLOC_CHECK_] => 2
26 [USER] => www
27 [HOME] => /home/www
28 [FCGI_ROLE] => RESPONDER
29 [SERVER_SOFTWARE] => nginx
30 [QUERY_STRING] =>
31 [REQUEST_METHOD] => GET
32 [CONTENT_TYPE] =>
33 [CONTENT_LENGTH] =>
34 [SCRIPT_NAME] => /test.php
35 [REQUEST_URI] => /test.php
36 [DOCUMENT_URI] => /test.php
37 [SERVER_PROTOCOL] => HTTP/1.1
38 [REMOTE_ADDR] => 114.93.76.130
39 [REMOTE_PORT] => 1037
40 [SERVER_ADDR] => 122.0.66.162
41 [SERVER_PORT] => 88
42 [SERVER_NAME] => yuenshui.com
43 [REDIRECT_STATUS] => 200
44 [HTTP_USER_AGENT] => curl/7.15.5 (x86_64-redhat-linux-gnu) libcurl/7.15.5OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5
45 [HTTP_HOST] => yuenshui.com:88
46 [HTTP_ACCEPT] => */*
47 [HTTP_CHECK_LOGIN] => NULL
48 [PHP_SELF] => /test.php
49 [REQUEST_TIME] => 1340534289
50 [argv] => Array
51 (
52 )
53
54 [argc] => 0
55 )
56
57 $_COOKIE:
58 Array
59 (
60 )
token錯誤的測試:
01 [root@localhost soft]# curl -b "uid=12345;nickname=soga;token=aa6f21ec0fcf008aa5250904985a817b" "http://yuenshui.com:88/test.php"
02 <pre>$_SERVER:
03 Array
04 (
05 [TMP] => /tmp
06 [TMPDIR] => /tmp
07 [TEMP] => /tmp
08 [OSTYPE] =>
09 [MACHTYPE] =>
10 [MALLOC_CHECK_] => 2
11 [USER] => www
12 [HOME] => /home/www
13 [FCGI_ROLE] => RESPONDER
14 [SERVER_SOFTWARE] => nginx
15 [QUERY_STRING] =>
16 [REQUEST_METHOD] => GET
17 [CONTENT_TYPE] =>
18 [CONTENT_LENGTH] =>
19 [SCRIPT_NAME] => /test.php
20 [REQUEST_URI] => /test.php
21 [DOCUMENT_URI] => /test.php
22 [SERVER_PROTOCOL] => HTTP/1.1
23 [REMOTE_ADDR] => 114.93.76.130
24 [REMOTE_PORT] => 1059
25 [SERVER_ADDR] => 122.0.66.162
26 [SERVER_PORT] => 88
27 [SERVER_NAME] => yuenshui.com
28 [REDIRECT_STATUS] => 200
29 [HTTP_USER_AGENT] => curl/7.15.5 (x86_64-redhat-linux-gnu) libcurl/7.15.5OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5
30 [HTTP_HOST] => yuenshui.com:88
31 [HTTP_ACCEPT] => */*
32 [HTTP_COOKIE] => uid=12345;nickname=soga;token=aa6f21ec0fcf008aa5250904985a817b
33 [HTTP_CHECK_LOGIN] => No
34 [PHP_SELF] => /test.php
35 [REQUEST_TIME] => 1340537366
36 [argv] => Array
37 (
38 )
39
40 [argc] => 0
41 )
42
43 $_COOKIE:
44 Array
45 (
46 [uid] => 12345
47 [nickname] => soga
48 [token] => aa6f21ec0fcf008aa5250904985a817b
49 )
token正確的測試:
01 [root@localhost soft]# curl -b "uid=1234;nickname=soga;token=aa6f21ec0fcf008aa5250904985a817b" "http://yuenshui.com:88/test.php"
02 <pre>$_SERVER:
03 Array
04 (
05 [TMP] => /tmp
06 [TMPDIR] => /tmp
07 [TEMP] => /tmp
08 [OSTYPE] =>
09 [MACHTYPE] =>
10 [MALLOC_CHECK_] => 2
11 [USER] => www
12 [HOME] => /home/www
13 [FCGI_ROLE] => RESPONDER
14 [SERVER_SOFTWARE] => nginx
15 [QUERY_STRING] =>
16 [REQUEST_METHOD] => GET
17 [CONTENT_TYPE] =>
18 [CONTENT_LENGTH] =>
19 [SCRIPT_NAME] => /test.php
20 [REQUEST_URI] => /test.php
21 [DOCUMENT_URI] => /test.php
22 [SERVER_PROTOCOL] => HTTP/1.1
23 [REMOTE_ADDR] => 114.93.76.130
24 [REMOTE_PORT] => 1059
25 [SERVER_ADDR] => 122.0.66.162
26 [SERVER_PORT] => 88
27 [SERVER_NAME] => yuenshui.com
28 [REDIRECT_STATUS] => 200
29 [HTTP_USER_AGENT] => curl/7.15.5 (x86_64-redhat-linux-gnu) libcurl/7.15.5OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5
30 [HTTP_HOST] => yuenshui.com:88
31 [HTTP_ACCEPT] => */*
32 [HTTP_COOKIE] => uid=1234;nickname=soga;token=aa6f21ec0fcf008aa5250904985a817b
33 [HTTP_CHECK_LOGIN] => Yes
34 [PHP_SELF] => /test.php
35 [REQUEST_TIME] => 1340537463
36 [argv] => Array
37 (
38 )
39
40 [argc] => 0
41 )
42
43 $_COOKIE:
44 Array
45 (
46 [uid] => 12345
47 [nickname] => soga
48 [token] => aa6f21ec0fcf008aa5250904985a817b
49 )
http://yuenshui.com:88/test.php 打印信息的PHP代碼:
01 <pre><?php
02 echo "\$_SERVER:\r\n";
03 unset($_SERVER['SCRIPT_FILENAME']);
04 unset($_SERVER['DOCUMENT_ROOT']);
05 unset($_SERVER['PATH']);
06 unset($_SERVER['HOSTNAME']);
07 unset($_SERVER['GATEWAY_INTERFACE']);
08 print_r($_SERVER);
09 echo "\r\n\$_COOKIE:\r\n";
10 print_r($_COOKIE);
11 ?>
上面是全部的測試程序。你們也能夠經過curl進行測試http://yuenshui.com:88/test.php