存档

作者存档

美时办公家具有限公司

2009年8月5日

美时Lamex自1977年成立以来已发展成为中国最大的家具生产商,代理世界各地著名品牌如Frezza, Forma, Sedus, Dauphin, Girsberger等。另外,美时亦致力设计,研发及生产美时的家具,提供过千种产品。美时现时拥有超过50多家特许经营商及分行遍布中国、香港、澳门 及台湾。

美时已发展为首屈一指的家具生产商。生产厂房位于东莞,面积超过十万平方米,为国内最大型的生产厂房。主要生产线分为四种,包括屏风家具系列,办公桌, 文件储存系统及办公室座椅。LAMEX厂房为一所综合大楼,集生产厂房,品质测试中心,设计及发展,货仓,行政中心,培训中心及陈列室等,使公 司运作更有效率。

公司大事记:

1977-美时公司成立

1978-首家香港办公室家具公司提供5年产品保用

1989-首家香港办公室家具引入本地屏风系统生产线

1990-开始进入中国市场

1991-首家香港办公室家具公司提供电脑绘图和电脑生产线

1992-所有座椅产品采用不助燃海绵

1996-自行研发革命性的支柱式屏风系统 – 338屏风系统

1997-首家办公室家具公司在国内引入特许经营方式

美时创办人林正华先生获颁香港青年工业家奖

1998-338屏风系统于广州国际家具展获得金奖

1999-美时获得国际ISO9002品质认证

2001-美时投资二百五十万美元引入CNC Combima先进生产技术

美时为APEC会议的指定会议家具供应商

2002-美时荣获香港十大名牌

2003-美时荣获广东十大名牌,ISO9001及IQ Net

2004-美时荣获ISO14025 III 型环境认证。

美时获香港社会服务联会颁发“商界展关怀”。

2005-美时再度荣获“香港名牌”的奖项以及“商界展关怀”的嘉许状。

美时的销售员荣获“杰出推销员奖”。

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

家居生活

Zend Framework 1.8 中的Model

2009年8月1日

在ZF1.8以后Module的问题得以完善,但是仍然有很多领域需要改进,Model就是其中一个

Model的类型用DbTable<->Mapper<->Model的DataMapper Pattern (同时参照IdentityMapUnitOfWork)来调用,其中对象Model用于导入对象,导入后就由UOW拥有的Identity对象来跟踪,以此来保持数据的同步。比如一个Users表,我们有如下类:

Model_User是业务域模型(domain Model),关于domain design的模式可以参见domain driven design一书

Model_UserMapper来完成Model对象和数据库的映射关系

Model_DbTable_Users extends Zend_Db_Table_Abstract类负责数据库方面的设定

以上pattern的使用在这篇帖子Zend 的proposal中有讨论到。这个Pattern的好处是,如果你将来不用数据库来保存数据,而换用文件或者Memcached,那么你就不用修改你的Controller了;从来引来的一个缺点是几乎每个调用都需要来定义Mapper,从而导致复杂度提高。通常情况下对于不是比较复杂的情况,1:1的应用来说,Table Gatewy, Row, Rowset的Pattern已经足够使用。

关于DataMapper的Model使用模型还在更新过程中,同时还有个datashuffler在ZF上的实现目前也在研究中。

VN:F [1.9.22_1171]
Rating: 8.0/10 (1 vote cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

程序开发

ZF1.8 快速上手

2009年7月30日

ZF有段时间没有弄了,自从ZF1.8出来之后改动比较大,把一些东西整理一下,温故而知新。

首先是下载ZendFramework,由于ZF的版本更新很快,一些小版本基本是2周出一次下载最新的ZF,下载后将ZF放到系统类库目录,我们假设是/usr/local/lib/,

其次,将ZF添加到系统目录中去,可以修改php.ini(如果不确定php.ini所在目录,可以通过phpinfo查看),在include_path中增加如下目录:include_path=”.:/path/to/zf:/usr/share/php:/usr/share/pear”,对于以ZF为主的系统,将ZF包含目录放在最前面有助提高效率,详细请看这篇文章。在进行下一步之前,我们需要先确定目录构造,请参见ZF所推荐的Zend Framework的目录结构

开始工作,首先index.php比较简单:

<?php

// Define path to application directory
defined('APPLICATION_PATH')
 || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));

// Define application environment
defined('APPLICATION_ENV')
 || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production'));

// Ensure library/ is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
 realpath(APPLICATION_PATH . '/../library'),
 get_include_path(),
)));

/** Zend_Application */
require_once 'Zend/Application.php';  

// Create application, bootstrap, and run
$application = new Zend_Application(
 APPLICATION_ENV,
 APPLICATION_PATH . '/configs/config.ini'
);

$application->bootstrap()
 ->run();

接下来是bootstrap.php我最开始写ZF的时候最麻烦的部分就是bootstrap,花了不少时间调试。Bootstrap,顾名思义就是系鞋带,指出发之前做的准备工作。自从Zend Framework 1.8以后,ZF出了Zend_tool和Zend_Application,因此Bootstrap有了比较大的调整,基本来讲,只需要在index.php中调用Zend_Application,就可以直接免去过去设定config文件,DB,view等。如果需要对这些做特别设置,可以在Bootstrap中扩展Zend_Application_Bootstrap_Bootstrap,用_init*资源函数来设定,BootStrap将依顺序逐个调用这些_init*资源函数,然后执行dispatch。用这里有篇是介绍如何将老的Bootstrap迁移到ZF1.8上。需要注意的有几点,

1.  在initView的时候尽量不要标注Response属性,这样这个Bootstrap不会在layout之前实例化Response;

2.  可以判断ajax的request头,用以去除layout, ViewRender,errorHandler和Exception的输出,这样就免除在ajax页面里面单独进行设定了。

3. ZF1.8之后可以通过设定driver option的方式对ZF的DB charset进行lazy load方式的设定了。

<?php

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
 protected $_config;
 protected $_cache;
 protected $_requesttype;

 public function run() {
 $frontController = Zend_Controller_Front::getInstance();
 $frontController->dispatch();
 }

 protected function _initAutoload(){
 $autoloader = new Zend_Application_Module_Autoloader(array(
 'namespace' => '',
 'basePath'  => APPLICATION_PATH,
 ));
 return $autoloader;
 }

 protected function _initConfig(){
 // config
 $this->_config = new Zend_Config_Ini(APPLICATION_PATH . '/configs/config.ini', APPLICATION_ENV);
 Zend_Registry::set('config', $this->_config);
 Zend_Registry::set('env', APPLICATION_ENV);

 //Load Application Level configure
 $appconf = new Zend_Config_Ini(APPLICATION_PATH . '/configs/app.conf', APPLICATION_ENV);
 Zend_Registry::set('appconf', $appconf);

 if (1 == (int)$this->_config->debug->showpageinfo){
 Zend_Registry::set('PageStartTime', microtime(true));
 }
 }

 protected function _initDB(){
 if($this->_config->db) {
 $db = Zend_Db::factory($this->_config->db);
 if($this->_config->cache->tablemeta && isset($this->_cache)) //setup Metacache to speed up
 Zend_Db_Table::setDefaultMetadataCache($this->_cache);
 Zend_Db_Table_Abstract::setDefaultAdapter($db);
 Zend_Registry::set('db', $db);
 }
 }

 protected function _initView(){
 // view and layout setup
 $view = new Zend_View(array('encoding'=>'UTF-8'));
 $view->addHelperPath(APPLICATION_PATH.'/default/views/helpers/');
 //$viewRendered = new Zend_Controller_Action_Helper_ViewRenderer($view);
 //Zend_Controller_Action_HelperBroker::addHelper($viewRendered);

 Zend_Dojo::enableView($view);
 $view->dojo()->setDjConfigOption('parseOnLoad', true)
 ->requireModule('dijit.form.FilteringSelect')
 ->requireModule('custom.PairedStore');
 //$view->addBasePath(realpath('./templates/default/'));

 //if ajax submit
 if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'){
 $this->_requesttype="ajax";
 }else{
 $this->_requesttype="html";
 Zend_Layout::startMvc(array(
 'layoutPath'=>APPLICATION_PATH . '/layouts',
 'layout'=>'layout'
 ));
 }
 $view->doctype('XHTML1_STRICT');
 Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer')->setView($view);
 }

 protected function _initFrontController(){
 $frontController = Zend_Controller_Front::getInstance();
 $frontController->setControllerDirectory(APPLICATION_PATH .'/controllers');
 $frontController->setParam('env', APPLICATION_ENV);
 if ("ajax" == $this->_requesttype){
 // Disable the ErrorHandler plugin
 $frontController->setParam('noErrorHandler', true);
 // Disable the ViewRenderer helper
 $frontController->setParam('noViewRenderer', true);
 }
 $frontController->throwExceptions(false);
 $frontController->setBaseUrl('/');
 // action helpers
 Zend_Controller_Action_HelperBroker::addPath(APPLICATION_PATH .'/controllers/helpers');
 }

 protected function _initSession(){
 if (isset($this->_config->session)){
 $session = $this->_config->session;
 if (empty($session->save_path))
 $session->save_path = APPLICATION_PATH. "/../data/sessions/";
 }
 Zend_Session::setOptions($this->_config->session->toarray());
 }

 protected function _initCache(){
 /**
 * Setup Core Cache
 */
 if ('true' == $this->_config->cache->caching){
 $CacheFrontendOptions = array(
 'lifeTime' => $this->_config->cache->lifetime,  // cache lifetime of half a minute
 'caching' => $this->_config->cache->caching,
 'automatic_serialization' => $this->_config->cache->automatic_serialization,  // this is default anyway
 'automatic_cleaning_factor'=>$this->_config->cache->automatic_cleaning_factor,
 'logging' => $this->_config->cache->logging,
 );
 switch($this->_config->cache->backend){
 case 'memcached':
 $MemcachedBackendOptions = array(
 'servers'=>array(array(
 'host' => $this->_config->cache->memcached->host,
 'port' => $this->_config->cache->memcached->port,
 'persistent' => $this->_config->cache->memcached->persistent
 )));
 $this->_cache = Zend_Cache::factory('Core', 'Memcached', $CacheFrontendOptions, $MemcachedBackendOptions);
 break;
 case 'file':
 default:
 $FileBackendOptions = array(
 'cache_dir' => APPLICATION_PATH.'/../data/cache/',
 'read_control'=>true,
 'read_control_type'=>'md5',
 'hashed_directory_level'=>'1'
 );
 $this->_cache = Zend_Cache::factory('Core', 'File', $CacheFrontendOptions, $FileBackendOptions);
 break;
 }//End of switch
 Zend_Registry::set('cache', $this->_cache);
 }
 /**
 * Setup Page cache
 */
 if($this->_config->cache->page->caching){
 $pageCacheRegexpsConfig = array(
 'cache_with_get_variables'=>true,
 'cache_with_post_variables'=>true,
 'cache_with_session_variables'=>true,
 'cache_with_files_variables'=>true,
 'cache_with_cookie_variables'=>true,);
 $pageCacheFrontendOptions = array(
 'lifetime' => $this->_config->cache->lifetime,
 'debug_header' => $this->_config->cache->page->debug, // for debugging
 'regexps' => array(
 // cache the whole IndexController
 '^(.+)-lc-(.*).html' => array_merge($pageCacheRegexpsConfig,array('tags'=>array('lc'))),
 )
 );

 if (empty($FileBackendOptions)){
 $FileBackendOptions = array(
 'cache_dir' => APPLICATION_PATH.'/../data/cache/',
 'read_control'=>true,
 'read_control_type'=>'md5',
 'hashed_directory_level'=>'1'
 );
 }

 // getting a Zend_Cache_Frontend_Page object
 $page_cache = Zend_Cache::factory('Page',
 'File',
 $pageCacheFrontendOptions,
 $FileBackendOptions);
 $page_cache->start();
 }
 }

 protected function _initTranslation(){
 //Setup Locale
 Zend_Locale::setDefault('en');   //fallback locale
 $locale = new Zend_Locale('auto'); //auto detection for user locale
 if (isset($this->_cache)) Zend_Locale::setCache($this->_cache); //cache locale to speed up
 Zend_Registry::set('Zend_Locale', $locale); //set up application-wide locale
 //Setup Zend Translate

 //$this->_cache = Zend_Cache::factory('Page','File',$frontendOptions,$backendOptions);
 //Zend_Translate::setCache($this->_cache);
 $translate = new Zend_Translate('gettext','../data/locales/',NULL,array(
 'scan' =>Zend_Translate::LOCALE_DIRECTORY,
 'disableNotices' => true
 ));
 Zend_Registry::set('Zend_Translate', $translate);
 //Zend_Validate_Abstract::setDefaultTranslator($translate);
 Zend_Form::setDefaultTranslator($translate);
 }

 protected function _initRoutes(){
 //$router = new Zend_Controller_Router_Rewrite();
 //$router->addConfig($appconf, 'routes');
 }
}
VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

程序开发

nginx绑定独立IP

2009年5月25日

对于多个域名多个IP的服务器,有时候我们需要用户不能通过的IP直接访问网站。这有的时候是因为IDC机房的需要,有的时候是我们为了将网站直接隔绝开的需要。本文是想讨论Nginx下如何实现这样的设置。

如果是Apache的话比较好设定,可以用NameVirtualHost来指定哪个IP绑定哪个域名,但是nginx应该如何把ip绑定到域名商呢?Slicehost论坛上也有人讨论过如何绑定ip的问题。核心的问题就是,如果直接输入ip,nginx会把这个ip对应到哪个域名上呢?答案是随机的。如果想要在某个域名做为catchall的,可以设定如下规则:

server{
listen  80 default;
....
}

那么如何绑定独立IP呢?由于ip信息其实是在在NGINX官方HTTPcore Listen的说明文档上也提到了这个是用方法,可以比较方便的是使用如下

server{
listen  99.69.16.3:80;
server_name www.abe.com
....
}

也可以直接这样写:

server{
listen  114.163.186.110;
server_name www.jefflei.com
....
}
server{
listen  99.69.16.3;
server_name www.abe.com
....
}

这样独立的ip就被绑定到固定的域名上去了。

VN:F [1.9.22_1171]
Rating: 10.0/10 (2 votes cast)
VN:F [1.9.22_1171]
Rating: +2 (from 2 votes)

系统管理

thinkvantage中没创建恢复介质(Create Recovery Media)的解决方法

2009年5月8日

享受了一个多月碧波帮我带回来的新的ibmT500(2242CTO)到手,感觉速度真是比台式机还快。不过这两天发现两个问题,足见ibm易主lenovo后服务是越来越差。其一是一项以商务服务著称的thinkpad从4月开始停止了自动system update服务,用户更新驱动程序需要手动到联想网站上查询后下载。联想的thinkpad笔记本论坛里面是议论纷纷
另外一件不太方便的事情是我的think vantage中没有创建系统恢复盘的功能,于是查了下美国的lenovo论坛中有篇说明是由于选择的Vista downgradable to XP造成的, 无奈只能按坛子里面的指示直接调用”C:\Program Files\Common Files\Lenovo\spi\RRMedia.exe”, 看来lenovo的走向也越来越不是面向商业用户,而是走向低端化了。另外创建恢复盘的话,XP是1CD+1DVD or 7CD, vista是1CD+2DVD, 必须要CD的。

配置如下:

Core2 Duo T9400 2.5Hz(6M L2)/2G DDR3/160G SATA2 7200/LED backlight/集成显卡ATI X4500HD/Vista downgradable to XP Professional/Displayport

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

软件和工具

Adwords否定关键词的匹配选项

2009年4月25日

虽然很多人可能使用过关键字匹配类型(match type),但是有多少人正在使用否定关键字匹配类型呢?作为一名早期的AdWords用户,下面介绍下否定关键词(negative keywords)的匹配类型,希望有助于提高关键字质量。 有三种类型的负面关键字:精确否定(negative exact),词组否定(negative phrase),否定(negative,实际是negative broad)。

精确否定当整个查询正好就是这个关键词才不会显示。词组否定将不会出现在任何含顺序显示该词组的查询中。否定(negative broad)只需要查询短语中含有了否定中所有的单词,即不会显示,和否定单词是否顺序出现以及是否相邻无关。

假设你购买了关键字“蓝色奔驰车的广泛匹配”。以下是如何将否定关键字“蓝色快”的不同匹配类型的,将如何影响此广告是否显示。

1)快速蓝(负)
可能的搜索关键词:
蓝色奔驰车 – 将显示
蓝色的快速奔驰车 – 不显
奔驰车快 – 将显示
蓝色奔驰车快 – 不显
快蓝色 – 不显
蓝色快 – 不显
快速蓝色奔驰车 – 不显

2) – “快蓝色”(负短语)
可能的搜索关键词:
蓝色奔驰车 – 将显示
蓝色的快速奔驰车 – 将显示
奔驰车快 – 将显示
蓝色奔驰车快 – 将显示
快蓝色 – 不显
蓝色快 – 将显示
快速蓝色奔驰车 – 不显

3) – [快(负精确蓝色])
可能的搜索关键词:
蓝色奔驰车 – 将显示
蓝色的快速奔驰车 – 将显示
奔驰车快 – 将显示
蓝色奔驰车快 – 将显示
快蓝色 – 不显
蓝色快 – 将显示

当含有10个以上单字时,exact match不再有效,因为只会读取前10个单字,然后进行包含运算。

VN:F [1.9.22_1171]
Rating: 10.0/10 (1 vote cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

搜索引擎

XSS攻击防范

2009年4月22日

最近一个朋友找我帮忙修复一个XSS注入漏洞,其实网站也是某上市互联网公司的中国站。现在XSS和CSRF攻击成为一个WEB软件工作者不得不重视的一个问题,很有必要深入研究下。

XSS漏洞很容易在大型网站中发现,在黑客圈内它非常流行。最著名的是2005年黑客Sammy Kamkar在myspace网站发布蠕虫病毒后,XSS就开始大行其道。FBI.gov、CNN.com、Time.com、Ebay、 Yahoo、Apple、Microsoft、Zdnet、Wired、Newsbytes,twitter都有这样那样的XSS漏洞。国内出现过XSS漏洞的网站有sohu,网易邮箱,校内网等,百度和著名电商网站淘宝也曾出现过XSS漏洞。

在商业产品中,平均每个月能够发现10-25个XSS漏洞。

假设你已经了解XSS的基本概念和类型,这里看看如何进行防范。先总结一下常见的XSS攻击手法:

依赖跨站漏洞,需要在被攻击网站的页面种入XSS脚本的手法

Cookie 盗取,通过javascript 获取被攻击网站种下的cookie,并发送给攻击者。
1.从cookie 中提取密码等隐私
2. 利用cookie 伪造session,发起重放攻击
Ajex 信息盗取,通过javascript 发起ajex 请求。
1. 从ajex 结果中获取隐私。
2. 模拟用户完成多页表单。

不依赖跨站漏洞的XSS攻击手法

1. 单向HTTP 动作,通过img.src 等方法发起跨站访问,冒充被攻击者执行特权操作。但是很难拿到服务器的返回值。
2. 双向HTTP 动作,如果服务器产生一段动态的script,那么可以用script.src 的方法发起跨站访问并拿到服务器的返回值。

XSS防范方法

XSS攻击防范主要是有程序漏洞造成的,要完全防止XSS安全漏洞主要依靠程序员较高的编程能力和安全意识,当然一些编程安全原则可以帮助大大减少XSS安全漏洞:

  1. 不信任用户提交的任何内容,对所有用户提交内容进行可靠的输入验证,包括对URL、查询关键字、HTTP头、REFER、POST数据等,仅接受指定长度范围内、采用适当格式、采用所预期的字符的内容提交,对其他的一律过滤。尽量采用POST 而非GET 提交表单;对”<”,”>”,”;”,”’”等字符做过滤;任何内容输出到页面之前都必须加以encode,避免不小心把html tag 弄出来。
  2. 实现Session标记(session tokens)、CAPTCHA系统或者HTTP引用头检查,以防功能被第三方网站所执行,对于用户提交信息的中的img 等link,检查是否有重定向回本站、不是真的图片等可疑操作。
  3. Cookie 防盗。避免直接在cookie 中泄露用户隐私,例如email、密码等等;通过使cookie 和系统ip 绑定来降低cookie 泄露后的危险。这样攻击者得到的cookie 没有实际价值,不可能拿来重放。
  4. 确认接收的的内容被妥善的规范化,仅包含最小的、安全的Tag(没有javascript),去掉任何对远程内容的引用(尤其是样式表和javascript),使用HTTP only的cookie。

PHP方面请参见PHP的安全防范工作

ASP.Net的可以用VS自带的XSSDetect来检测。

要更好的防范XSS和CSRF攻击等,除了加强程序开发的严谨度之外,还需要重视测试工作,通过专业的测试来减少问题发生的可能性,我们看到淘宝QA也重视XSS攻击测试了。

VN:F [1.9.22_1171]
Rating: 6.0/10 (4 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

程序开发

正确设置邮件发送的域名记录和STMP

2009年4月15日

域名配置

需要配置的域名应该是发送接收邮件@后面的部分。我们需要设置的有MX记录,PTR记录和SPF记录.

MX记录

规范的MX记录应当由主域解析出一个主机名(如mta.jefflei.com),再由此主机名解析出一个或多个IP地址(如 211.99.189.87和211.99.189.88),而不能直接由主域解析出一个IP地址,直接由MX记录解析出IP会被一些MTA认为是垃圾邮件。而且,主域解析出的主机名不应当同主域名相同。

PTR记录

配置IP反向解析,即PTR记录. 一条被AntiSPAM策略看成是绝对有效的PTR记录,其实包含2个内容:
A 找ISP做的 1.2.3.4 PTR记录指向到 a.b.com
B 域名的DNS设置(一般是域名注册商的域名控制面板)的 a.b.com. 的A记录也要指向到 1.2.3.4
设置完成后,可以用IP反向解析查询工具测试一下PTR设置是否成功。

SPF(TXT)记录

详细参照SPF记录的设置案例说明

主机与软件配置

首先,如果你使用的不是第三方邮件服务商,而是使用自己搭建的SMTP, 那么你还有很多设置工作。首先,邮件系统一般使用操作系统的Hostname作为SMTP会话中HELO指令后面的内容,而某些比较严格的过滤系统会要求HELO内容是有A记录的域名,且与来源IP匹配。打开命令行界面,输入:

#telnet xxx.com 25
#ehlo

其次,在你的程序在外发邮件时,需要注意from和reply-to需要保持一致,某些MTA会block不一致的邮件。

另外,给出的from地址<support@jefflei.com> ,必须要在服务器上建立相应的电子邮件账号。因为有些收信服务商AntiSPAM策略会去校验其中包含的support@jefflei.com是否是有效的地址,一般过程是收件方AntiSPAM 连接到 jefflei.com 对应的 EMail Server,即203.96.209.88 的SMTP (TCP 25 )端口上,用VRFY support@jefflei.com ,或RCPT TO:<support@jefflei.com>来校验,如果命令返回得到250的结果,AntiSPAM策略会认为这是一个确 实存在的EMAIL地址。

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

系统管理

PayPal黑帮

2009年4月8日

不知从哪里挖出一篇老文章,才发现很多Web2.0公司和PayPal的前员工脱不开关系,那些鼎鼎大名的公司如Facebook, youtube, flickr,linkedIn,Digg,Technorati,Xoom,Mozilla,Yelp不是由这些PayPal前员工的创建,就是由他们的投资公司所投资的, 文章还把他们的照片都拍成黑帮老大的样子,还真是蛮八卦搞笑的。另中文介绍可参见这里

PayPal mafia

PayPal mafia

虽然PayPal帮现在枝繁叶茂,不过想当年他们可是头痛的事情一大堆,被黑客攻击,推广费用被利用以及内部矛盾,在上市之前他们足足烧了1.8亿美金,创业公司的劳苦困顿,我想大约是拉近创业者团队之间关系的重要原因吧,不经历风雨,何见黑帮?

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: -1 (from 1 vote)

互联网圈

nginx防盗链设置

2009年3月31日
nginx防盗链设置已关闭评论

防止盗链不仅能保护版权,又节约了不少流量。最近和bsdmap交流了下,听说他们通过防盗链节约了近1/3的图片流量。nginx的防盗链设置还是比较简单的,可以分为普通防盗链和ip/cookie based防盗链。其中ip based防盗链需要安装nginx的module,所以相对麻烦一些。

nginx最简单的防盗链设置如下

location ~* .(gif|jpg|png|swf|flv)$ {
valid_referers none blocked www.jefflei.com;
if ($invalid_referer) {
return 403;
}
}

通过nginx的重定向方式返回403错误。

NginxHttpAccessKeyModule实现防盗链

需要先安装nginx的NginxHttpAccessKeyModule模块。其运行方式是:如我的nginx目录下有一个file.gz 的文件。对应的URI 是http://www.jefflei.com/nginx/file.gz
若用ngx_http_accesskey_module 后则根据用户的IP生成一个key值,如下的链接来访问http://www.jefflei.com/download/file.zip?key=23497sdf897. 只有给定的key值正确了,才能够下载nginx目录下的file.gz,这样就可以避免被盗链了。

VN:F [1.9.22_1171]
Rating: 7.0/10 (3 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

系统管理 ,