
猜猜中间哪个是什么?
猜猜中间哪个是什么?
做web开发,必然会涉及到Session,这是由于http协议本身是无状态的(每次响应都是独立的,彼此间没有联系),所以如果需要在页面跳转间保持某个用户的身份,就要在每次连接时告诉服务器端你的唯一标示号,即Session ID。这样,服务器端便可通过Session ID得到所需的数据。
在PHP中,Session是通过$_SESSION这个全局变量来set/get的,不过在使用之前要先初始化。初始化是通过session_start函数(如果php.ini中将session.auto_start设为1,则会自动初始化),之后PHP会为request自动生成一个唯一随机数作为Session ID,生成算法默认提供了MD5 (128 bits) 和SHA-1 (160 bits),由php.ini中session.hash_function设定。其实也可以自定义,比如在随机数基础上将来访者的IP地址也加入到算法中,像CodeIgniter1.7.2中代码:
1 2 3 4 5 6 7 8 | $sessid = ''; while (strlen($sessid) < 32) { $sessid .= mt_rand(0, mt_getrandmax()); } // To make the session ID even more secure we'll combine it with the user's IP $sessid .= $this->CI->input->ip_address(); $sessid = md5(uniqid($sessid, TRUE)) |
生成的ID存放在服务器的某一目录下,这由php.ini中session.save_path配置。如果你选择默认的文件式session存储,那么可能会遇到大量session文件导致IO性能下降,这个问题可以通过调节save_path来优化,具体请看大量php session临时文件带来的服务器效率问题。如果要在多个服务器中同步session id,你可以将其存放在数据库或共享缓存中。这需要你自定义一系列Session的读写方法,并在调用session_start函数前先设定好,以下面代码为例(来自php document中的一段示例代码):
1 2 3 4 5 6 | CREATE TABLE `ws_sessions` ( `session_id` VARCHAR(255) BINARY NOT NULL DEFAULT '', `session_expires` INT(10) UNSIGNED NOT NULL DEFAULT '0', `session_data` text, PRIMARY KEY (`session_id`) ) TYPE=InnoDB; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | <?php class session { // session-lifetime var $lifeTime; // mysql-handle var $dbHandle; function open($savePath, $sessName) { // get session-lifetime $this->lifeTime = get_cfg_var("session.gc_maxlifetime"); // open database-connection $dbHandle = @mysql_connect("server","user","password"); $dbSel = @mysql_select_db("database",$dbHandle); // return success if(!$dbHandle || !$dbSel) return false; $this->dbHandle = $dbHandle; return true; } function close() { $this->gc(ini_get('session.gc_maxlifetime')); // close database-connection return @mysql_close($this->dbHandle); } function read($sessID) { // fetch session-data $res = mysql_query("SELECT session_data AS d FROM ws_sessions WHERE session_id = '$sessID' AND session_expires > ".time(),$this->dbHandle); // return data or an empty string at failure if($row = mysql_fetch_assoc($res)) return $row['d']; return ""; } function write($sessID,$sessData) { // new session-expire-time $newExp = time() + $this->lifeTime; // is a session with this id in the database? $res = mysql_query("SELECT * FROM ws_sessions WHERE session_id = '$sessID'",$this->dbHandle); // if yes, if(mysql_num_rows($res)) { // ...update session-data mysql_query("UPDATE ws_sessions SET session_expires = '$newExp', session_data = '$sessData' WHERE session_id = '$sessID'",$this->dbHandle); // if something happened, return true if(mysql_affected_rows($this->dbHandle)) return true; } // if no session-data was found, else { // create a new row mysql_query("INSERT INTO ws_sessions ( session_id, session_expires, session_data) VALUES( '$sessID', '$newExp', '$sessData')",$this->dbHandle); // if row was created, return true if(mysql_affected_rows($this->dbHandle)) return true; } // an unknown error occured return false; } function destroy($sessID) { // delete session-data mysql_query("DELETE FROM ws_sessions WHERE session_id = '$sessID'",$this->dbHandle); // if session was deleted, return true, if(mysql_affected_rows($this->dbHandle)) return true; // ...else return false return false; } function gc($sessMaxLifeTime) { // delete old sessions mysql_query("DELETE FROM ws_sessions WHERE session_expires < ".time(),$this->dbHandle); // return affected rows return mysql_affected_rows($this->dbHandle); } } $session = new session(); session_set_save_handler(array(&$session,"open"), array(&$session,"close"), array(&$session,"read"), array(&$session,"write"), array(&$session,"destroy"), array(&$session,"gc")); session_start(); // etc... ?> |
除了上述方法外还有其他办法可以保持Session的同步,可以参考PHP SESSION解惑一文中第四部分“session的同步”。
下面再谈谈Session ID的传递方式:Cookie和URL传递。
Cookie是比较常用的方式,在这种模式下,启动Session后服务器会在HTTP Response中自动加上header(‘Set-Cookie: session_name()=session_id(); path=/’),并在以后的请求中加上这个Cookie。当从该页跳转到的新页面并调用session_start()后,PHP将检查与给定ID相关联的服务器端存贮的session数据,如果没找到,则新建一个数据集。但是有一点,这种传递方式必须在用户浏览器开启Cookie的情况下才可用,如果万一用户关闭了Cookie,那么只好选择另外一种通过URL参数传递Session ID。
开启URL传递需要在php.ini中设置session.use_trans_sid(文档中提示使用这种方式会有安全风险,因为它显示地将Session ID放在url中,所以除非迫不得已不要选择此方式),并在代码中做如下修改:
1 2 3 4 5 6 | // 如果客户端使用cookie,可直接传递session到page2.php echo '<br /><a href="page2.php">page 2</a>'; // 如果客户端禁用cookie echo '<br /><a href="page2.php?' . SID . '">page 2</a>'; |
/*
默认php5.2.1下,SID只有在cookie被写入的同时才会有值,如果该session
对应的cookie已经存在,那么SID将为(未定义)空
*/
更新2010-12-28:
如果php使用默认的file方式存储session,还要注意lock问题。因为php会lock住session文件直到这个session关闭,所以如果你的应用中涉及iframe、下载、Comet或者用户在同一个浏览器打开多个tab等等多个并行请求都要操作session时,就可能会遇到由于lock影响用户操作的情况。一个简单的解决办法就是在操作完session时,及时调用session_commit()或session_write_close()来关闭session,从而释放锁。(注意在关闭session后不要再调用任何session相关的函数)
关于Session的内容还有很多,具体可查看官方手册,如果有新的总结会继续更新。
原文链接:http://imdonkey.com/blog/archives/255
题目写得好拗口啊:)
placeholder是HTML5的一个新特性,今天在考虑如何提示表单输入内容格式的时候,左思右想还是把提示内容放在input中最好。刚开始还不知道有placeholder这个东西,想要找一些js实现同样的效果,不久就发现原来HTML5中有placeholder这个标签属性,恰好支持这种效果。
高兴了没有一会,万恶的IE就把我拉回了现实。
方法就是比问题要多,找了N多用JS实现的placeholder的效果,最后发现一个相对完美的实现。
源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | // HTML5 placeholder plugin version 1.01 // Copyright (c) 2010-The End of Time, Mike Taylor, http://miketaylr.com // MIT Licensed: http://www.opensource.org/licenses/mit-license.php // // Enables cross-browser HTML5 placeholder for inputs, by first testing // for a native implementation before building one. // // // USAGE: //$('input[placeholder]').placeholder(); // <input type="text" placeholder="username"> (function($){ //feature detection var hasPlaceholder = 'placeholder' in document.createElement('input'); //sniffy sniff sniff -- just to give extra left padding for the older //graphics for type=email and type=url var isOldOpera = $.browser.opera && $.browser.version < 10.5; $.fn.placeholder = function(options) { //merge in passed in options, if any var options = $.extend({}, $.fn.placeholder.defaults, options), //cache the original 'left' value, for use by Opera later o_left = options.placeholderCSS.left; //first test for native placeholder support before continuing //feature detection inspired by ye olde jquery 1.4 hawtness, with paul irish return (hasPlaceholder) ? this : this.each(function() { //TODO: if this element already has a placeholder, exit //local vars var $this = $(this), inputVal = $.trim($this.val()), inputWidth = $this.width(), inputHeight = $this.height(), //grab the inputs id for the <label @for>, or make a new one from the Date inputId = (this.id) ? this.id : 'placeholder' + (+new Date()), placeholderText = $this.attr('placeholder'), placeholder = $('<label for='+ inputId +'>'+ placeholderText + '</label>'); //stuff in some calculated values into the placeholderCSS object options.placeholderCSS['width'] = inputWidth; options.placeholderCSS['height'] = inputHeight; // adjust position of placeholder options.placeholderCSS.left = (isOldOpera && (this.type == 'email' || this.type == 'url')) ? '11%' : o_left; placeholder.css(options.placeholderCSS); //place the placeholder $this.wrap(options.inputWrapper); $this.attr('id', inputId).after(placeholder); //if the input isn't empty if (inputVal){ placeholder.hide(); }; //hide placeholder on focus $this.focus(function(){ if (!$.trim($this.val())){ placeholder.hide(); }; }); //show placeholder if the input is empty $this.blur(function(){ if (!$.trim($this.val())){ placeholder.show(); }; }); }); }; //expose defaults $.fn.placeholder.defaults = { //you can pass in a custom wrapper inputWrapper: '<span style="position:relative"></span>', //more or less just emulating what webkit does here //tweak to your hearts content placeholderCSS: { 'font':'0.75em sans-serif', 'color':'#bababa', 'position': 'absolute', 'left':'5px', 'top':'3px', 'overflow-x': 'hidden' } }; })(jQuery); |
源码:https://github.com/miketaylr/jQuery-html5-placeholder/blob/master/html5placeholder.jquery.js
rename 函数和 copy函数都是尝试进行操作。
rename是尝试重命名文件,copy是尝试复制文件,两者都是成功返回TRUE,失败返回FALSE。
因为是尝试操作,所有当目录下已经存在同名的文件时并不会去执行操作,从而返回FALSE。
如果想要尽量执行操作,而忽略同名文件,那么之前可以unlink一下。
–END–
命令方式连接
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #1)安装vpnc sudo apt-get install vpnc #2) 添加配置文件(/etc/vpnc目录下有example.conf示例配置文件) #配置文件示例: #IPSec gateway 192.168.1.0 #IPSec ID groupname #IPSec secret group_password #Xauth username username #Xauth password userpassword sudo vim /etc/vpnc/myvpn.conf #3)启动 sudo vpnc --enable-1des vpnc/hvpn #4)断开连接 sudo vpnc-disconnect |
上面是通过配置文件连接VPN,当然也可以通过sudo vpnc –enable-1des直接启动,然后根据提示输入相关信息。
参考:http://www.linuxplanet.com/linuxplanet/tutorials/6773/1/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #Install SSH Client and Server (for my remote access) sudo apt-get install ssh #Install Database Server sudo apt-get install mysql-server-5.0 #Install Apache HTTP Server sudo apt-get install apache2 #Install PHP5 and Apache PHP5 module sudo apt-get install php5 libapache2-mod-php5 #Restart Apache sudo /etc/init.d/apache2 restart #Optionally, install phpMyAdmin sudo apt-get install phpmyadmin sudo /etc/init.d/apache2 restart (重启 apache) sudo gedit /etc/php5/apache2/php.ini (配置 php.ini) sudo gedit /etc/apache2/apache2.conf (配置 apache2.conf) /var/www/(主目录位置) |