博客

  • 北京一瞥

    [imagebrowser id=3]

  • 远程API POST/GET的oauth验证的PHP实现 (适用于Dena的モバゲー)

    前几日的PHP方法有点小问题。现在针对Post JSON Data这种方式做了一些整合。

    无论是Post还是Get,在做Base String的时候是没有区别的。如果确实要说区别,就在于POST的时候,Parameter是NULL。所以做成oauth_signature的时候,规则也是一致的。

    区别的地方在于用Curl向外发送Request的时候,Curl的curl_setopt的参数是有区别。显然,Post的时候,要打开Post,而且吧PostData传给CURLOPT_POSTFIELDS。我这边特殊的是要传送JSON数据。习惯上是先做好数组形式的Post Data,然后再用PHP json_encode方法,转换成标准的JSON格式。调用公函最后做成如下

    [sourcecode language=’php’]
    reqOrg = OAuthRequest::from_request(NULL, NULL, NULL);
    $this->debugFlg = $debugFlg;

    if($mode == ‘Trusted’) {
    $this->xoauth_requestor_id = ‘1111111111’;
    }else {
    $this->xoauth_requestor_id = $this->reqOrg->get_parameter(‘opensocial_viewer_id’);
    }
    }

    public function makeHeaders($url,$method) {
    $consumer = new OAuthConsumer($this->consumer_key, $this->consumer_secret, NULL);
    $token = new OAuthToken(
    $this->reqOrg->get_parameter(‘oauth_token’),
    $this->reqOrg->get_parameter(‘oauth_token_secret’));

    parse_str(parse_url($url, PHP_URL_QUERY), $params);

    $request = OAuthRequest::from_consumer_and_token($consumer, $token, $method, $url, $params);

    $request->sign_request(new OAuthSignatureMethod_HMAC_SHA1(),$consumer, $token,$this->xoauth_requestor_id);
    $auth_header = $request->to_header(“”,$this->xoauth_requestor_id);
    $headers = array(“Content-Type: application/json; charset=utf-8”,$auth_header);
    return $headers;
    }

    public function fetchAPI($url,$method,$headers,$fields) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);

    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    if($this->debugFlg) {
    curl_setopt($ch, CURLOPT_HEADER, true);
    }else {
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    }

    if($method == ‘POST’) {
    curl_setopt($ch,CURLOPT_POST,true);
    curl_setopt($ch,CURLOPT_POSTFIELDS,json_encode($fields));
    }

    $ch_data=curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if($status < 400) { return $ch_data; }else { return null; } } public function callAPI($url,$method,$fields=null) { $headers = $this->makeHeaders($url,$method);
    $res = $this->fetchAPI($url,$method,$headers,$fields);
    return $res;
    }
    }
    ?>
    [/sourcecode]

  • 京城归来

    终于完成了自己的梦想,在伟大的天安门前留下一个倩影。

    整个四天,相当丰富。

    我们有去明清留存——故宫,恭王府,颐和园,圆明园,

    有去自然名胜——八达岭长城,香山,

    有去老北京文化——胡同文化,天桥茶馆,

    有去政治象征——天安门广场,英雄纪念碑,毛主席纪念堂,人民大会堂,

    有去特产风味——全聚德的烤鸭,王府井大街,

    有去现代城市的发展——鸟巢水立方,北京地铁,公交车。。。

    和文化教育的巅峰——北大,清华,中关村

    也去了大学故友的家里体会了现代北京白领的生活。

    今天报纸上看到一个切客的名词,才发觉自己也是一个切客。到一个地方,都用Google纵横定位自己的位置。最后回到南京的时候,就可以看到一个自己的行程图。这就是所谓的Checkin客。展示一下这次的战利品。

  • OpenSocial中2-legged OAuth的PHP实现

    oAuth介绍

    简单介绍一下oAuth,它是一个开发的授权标准。它允许用户让第三方网站访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方网站。

    标准的流程是

    在认证和授权的过程中涉及的三方包括:
    
    • 服务提供方,用户使用服务提供方来存储受保护的资源,如照片,视频,联系人列表。
    • 用户,存放在服务提供方的受保护的资源的拥有者
    • 客户端,要访问服务提供方资源的第三方应用,通常是网站,如提供照片打印服务的网站。在认证过程之前,客户端要向服务提供者申请客户端标识。
    使用OAuth进行认证和授权的过程如下所示:
    
    1. 用户访问客户端的网站,想操作用户存放在服务提供方的资源。
    2. 客户端向服务提供方请求一个临时令牌。
    3. 服务提供方验证客户端的身份后,授予一个临时令牌。
    4. 客户端获得临时令牌后,将用户引导至服务提供方的授权页面请求用户授权。在这个过程中将临时令牌和客户端的回调连接发送给服务提供方。
    5. 用户在服务提供方的网页上输入用户名和密码,然后授权该客户端访问所请求的资源。
    6. 授权成功后,服务提供方引导用户返回客户端的网页。
    7. 客户端根据临时令牌从服务提供方那里获取访问令牌。
    8. 服务提供方根据临时令牌和用户的授权情况授予客户端访问令牌。
    9. 客户端使用获取的访问令牌访问存放在服务提供方上的受保护的资源。

    有一点复杂,回到我们的应用。就是我们网站(第三方的服务提供方)想要访问当前用户(客户端)存放在Dena网络(用户)上的资源。真实流程又如何呢。在第 一次GadgetServer给我们请求的时候,就已经发给我们了访问令牌,而我们再次发API请求的时候,必须把这个令牌和请求内容一并发给 APIServer,这时候Server一看到我们令牌和当初一致,就返回信息给我们的网站。

    oAuth通讯的实现方法(PHP)

    oAuth自己官方网站上有一个PHP实现的Lib类。

    [sourcecode language=’php’]get_parameter(‘oauth_token’),
    $reqOrg->get_parameter(‘oauth_token_secret’));

    //建立API Request。除了刚才所说的令牌,还需要提供API REST URL,Mehtod等
    $url=”http://xxx.com/api/restful/v1/people/@me/@self”;
    $method = ‘GET’;
    parse_str(parse_url($url, PHP_URL_QUERY), $params);
    $request = OAuthRequest::from_consumer_and_token($consumer, $token, $method, $url, $params);

    //光有Request还不行,还要把原始Request的Base信息做一次加密,

    //成为密钥放到header里面去。这里用的是HMAC_SHA1方式
    $request->sign_request(new OAuthSignatureMethod_HMAC_SHA1(),$consumer, $token,$reqOrg->get_parameter(‘opensocial_viewer_id’));

    //哈哈,现在可以把做成header输出来了,准备发送
    $auth_header = $request->to_header(“”,$reqOrg->get_parameter(‘opensocial_viewer_id’));

    //以下就是用php的curl方法发送一个请求,并取得返回值,

    //显然这种REST必须是同步调用,也就是等待返回的。
    $headers = array($auth_header,”Content-Type: application/json; charset=utf-8″);
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_HEADER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    $res=curl_exec($ch);
    curl_close($ch);

    //把返回值打出来
    print “OpenSocial test


    “;
    print_r($res);
    print ““;

    ?>[/sourcecode]

  • 多一些个人爱好

    最近LP喜欢上了烘焙,从淘宝上拉回来好些专门材料和专业设备。

    上周第一次作小饼干,还是蛮成功的。味道很不错,外脆里酥。颇为得意,还带了些给同事们品尝。

    她每次烘培前都会仔细翻阅做法手册,然后摆好配料,有板有眼地和面粉,搅拌奶油,制作成形到烤箱出炉。看到她的投入那样儿,感觉她真的是在享受这个事情。当然,她的成果也是我的口福,我也如此的享受。

    生活中,多一些爱好,平凡的日子也会变得多彩。

  • QQ和360

    今天看到腾讯的声明

    我们刚刚作出了一个非常艰难的决定。在360公司停止对QQ进行外挂侵犯和恶意诋毁之前,我们决定将在装有360软件的电脑上停止运行QQ软件。我们深知这样会给您造成一定的不便,我们诚恳的向您致歉。

    这两个软件我都用过。也都有一点不愉快的经历。

    QQ,接触的还是很久远的,不过进入工作后,主要使用MSN,很少用QQ。记得有一次,偶尔上了次QQ,被一些90后开玩笑说,怎么一个太阳都没有啊。才知道已经落伍很久了。现在如果是自己装机器,我一般只装QQ Game,因为我喜欢玩欢乐斗地主。但是,有时候亲戚家的孩子过来,会装一些QQ软件。这个时候我就会特别小心,因为如果你什么都不干预,QQ装完了,你的机器绝对彻底变样了。下载的时候,不再是你熟悉的flashget,打开网页不在是熟悉的firefox,输入法变了,杀毒的变了,主页变了,无数的右键菜单变了。。。。所以每次我都要盯着看,确保只能留下QQ聊天工具。最近听说QQ空间什么很流行,我也不想去碰的。

    360,最开始下载安装,完全是因为免费,后来发现能帮我扫描启动项目,更新软件。还能按照分类方便得找到流行的软件,可以说是一站服务,感觉很不错。家里的笔记本每次重新安装系统后,第一个必安装360。可是,就在前不久,发现360导致蓝屏,我对它的印象就很差了。虽然是个个例,但从一个程序员的知识来看,360肯定访问或使用了系统底层的一些数据,从而导致在一定的硬件和软件的环境下,触发了WindowsXP意料外的错误,导致蓝屏。

    所以,我现在多半对他们的互掐也漠不关心了。

    以前是充斥盗版软件,发展到现在是大量的带有广告的免费应用。似乎是进步了,再也不用偷偷摸摸去破解什么的了。可是和以前相比,现在的电脑用户却是越来越被绑架,“被”安装。先不说,QQ凭什么要限制我的机器装什么,不装什么的无理蛮横,就看看现在装上的那些软件,哪一个不是把一次安装,作为桥头堡,步步为营,不断融入不相干的功能。



  • 金牛湖烧烤祭

    周六和一帮同事一起去了金牛湖。天气特别的好,空气也特别的清新。我们搭起炉灶,享受了别样的烧烤快乐。最后环金牛山,作了一次氧吧自行车游。三人自行车骑到上坡,有种高峡出平湖的感叹。人多了,推荐去玩玩!

  • 负载平衡(3)–CentOS 5 之 Apache

    负载平衡(1)中的构想是,3台Server,一个作为LoadBalance的Nginx,将请求转发给另外两台Server。不过这次并不适合我们。因为三台机器并不是在物理上一个局域网上,数据传输依然是使用WAN,所以这种阵列并不一定能解决负荷问题。

    于是重新考虑布局。首先,决定这次使用DNSラウンドロビン(Round robin DNS)来实现轮叫调度,基本原理就是将一个域名解析到多个IP地址,这样每次访问的时候就会返回多个IP地址,会选择第一个IP作为返回地址。当然,这个负载平衡有一些局限性,一方面并不是完全均衡,是针对每个域名服务器的,有些域名服务器访问的机器明显比其他多,也不能分给其他IP,另外一方面会有一定的缓存影响,使得在一定时间内对于同一域名服务器,返回的地址都是相同。如果一台机器坏了,既是修改了域名解析,因为延时的原因,也会在一段时间返回瘫痪的机器给客户端。

    不过话说回来,它还是适合我们的。一来他的平衡来自域名解析阶段,所以我们的机器都在WAN上,也不会受影响。另外,预想的用户相当庞大和平均,也不会出现某几台机器负荷过大的情况。

    那么首先把昨天的推倒重来。这次准备先将三台中的一个较弱的(Intel Xeon E5520 @ 2.27GHz * 16 内存32G)作为我们的图片服务器(Nginx),svn服务器,rsync源文件管理服务器,后台管理网站的服务器(apache)。另外两台组成Round Robin DNS。今后如果需要增加Web Server,也可以很容易加入Round Robin DNS.

    安装图片服务器(xxx.xx.xx.29)

    之所以选在Ngix 0.8.53,因为在巨量静态访问响应上,它占用的资源要远远小于Apache。安装过程如昨日。另外这台机器还要作为后台管理网站的服务器,所以还是需要安装Apache的。之所以没有直接选用Ngix 的Fast CGI,主要还是考虑到,后台管理网站的负载不会很高,更多要求的是稳定性和扩张性。而这次后台还准备使用Symfony 1.4框架。综合考虑使用Ngix转发模式,把PHP请求转发给8080端口的Apache。

    为了把Apache的DocumentRoot移到home底下(因为硬盘是home所在盘为1T,其他都较小),足足花了我2小时。

    事情是这样的,按照Apache的httpd.conf的清晰说明,很容易地把原来的/var/www/html改为 /home/xxxx/vhdocs。可结果就一直是403 Forbidden画面。

    网上说了各种可能,包括SELinux的设置种种都考虑了。权限也是设得不能再大。还是不行。当然我也知道,把Aapche的http.conf的启动User/Group改为那个/home/xxx的User是可以正常访问的。可是谁都知道这种丑陋的改发只是在回避问题。在最后,自己精疲力竭的时候,发现日本的一个网站做出了最好得解释。原来adduser的用户的/home/xxx目录竟然是770的,改成775就立马解决问题了。不过其实很早就知道这个信息“http.conf中设定用户必须能够访问DocumentRoot的从根目录开始的所有目录”,稍微想想,就不难得到775的结论。

    Ngix和Apache的转发设定很简单(注意第二行,因为我的后台apache是有两个virtualhost的,所以要把header传过去

    location ~ \.php$ {
    proxy_pass   http://127.0.0.1:8080;
    proxy_set_header Host $host;
    }

    安装Web服务器(xxx.xx.xx.30 xxx.xx.xx.31)

    接着把其他两台的Apache也如法炮制就可以了。

    设定Rsync

    考虑到多台Web Server,更新程序会比较麻烦。故考虑在29上,建立一个svn client,将svn的最新程序Download到29的本地。然后在29的Apache上通过Dena的Sandbox进行Staging测试。测试完毕后,使用rsync通过ssh方式传送的几台WebServer上。

    安装svn客户端非常简单,让后checkout一下就可以了。

    至于rsync,其实是有一种Server/Client设置模式的,我用不了那么复杂的,简单点的ssh就可以了

    rsync  -r -a -v -e  ssh /home/mbga/vhdocs root@xxx.xx.xxx.30:/home/xxx/

    为了方便,做一个shell就可以了。不过每次都要手输入密码。不知道可以不可以解决。

    完毕

    基本环境就可以了。今后memcached,syslogd,squid等等也会渐渐导入

  • 负载平衡(2)–CentOS 5 之 SVN

    其实SVN环境和负载平衡没有什么关系,只是team开发环境的一个准备

    1. 安装SVN

      # yum install subversion

    2. 建立Repos

      # mkdir -p /home/svn/repos/battlegame
      #svnadmin create /home/svn/repos/battlegame

    3. 建立trunk,braches,tags

      #svn mkdir file://localhost/home/svn/repos/battlegame/trunk -m “create”
      #svn mkdir file://localhost/home/svn/repos/battlegame/branches -m “create”
      #svn mkdir file://localhost/home/svn/repos/battlegame/tags -m “create”

    4. 安装mod_dav_svn

      #yum install mod_dav_svn

    5. 设定mod_dav_svn,修改 /etc/httpd/conf.d/subversion.conf

      LoadModule dav_svn_module     modules/mod_dav_svn.so
      LoadModule authz_svn_module   modules/mod_authz_svn.so

      <Location /svn>
      DAV svn
      # SVNPath /home/svn/repos/battlegame
      # any “/svn/foo” URL will map to a repository /var/svn/foo
      SVNParentPath /home/svn/repos
      # our access control policy
      AuthzSVNAccessFile /home/svn/repos/authzsvn.conf

      # only authenticated users may access the repository
      Require valid-user

      # how to authenticate a user
      AuthType Basic
      AuthName “Subversion repository(sample)”
      AuthUserFile /home/svn/repos/.htpasswd
      </Location>

    6. 设定apache认证,新建.htpasswd文件,输入用户名和密码。网上可以搜索到很多帮你设定密码的网站,比如http://www.luft.co.jp/cgi/htpasswd.php。最后文件如

      admin:xF4v98bL1ZGos

    7. 设定svn认证,新建authzsvn.conf,内容如

      [groups]
      #開発者
      developers = rex
      #管理者
      manager = admin
      #[/]
      #すべての人が読み込み可能
      #* = r
      [battlegame:/trunk]
      #開発者は読み書き可能
      @developers = rw
      [battlegame:/branches]
      #管理者は書き込みも可能
      @manager = rw
      [battlegame:/tags]
      #管理者は書き込みも可能
      @manager = rw

    8. 将/home/svn/repos/battlegame的权限设为775

      #chmod 775 -R /home/svn/repos/battlegame

    9. 将/home/svn/repos/battlegame的权限设为Apache可读
    10. #chown -R apache:apache /home/svn/repos/battlegame
    11. OK,重启Apache,在客户端CheckOut就可以了
  • 负载平衡(1) –CentOS 5 之 Nginx

    目标,另用一台机器(Nginx服务)实现LoadBalance,另外两台为Web Server(apache)

    1. 使用ssh登陆

      #ssh root@111.111.111.111

    2. 确认Linux 版本

      #lsb_release -a

      原来这次是 CentOS 5.5(Final),如果命令找不到,可以用

      #cat /etc/redhat-release

    3. 确认PHP安装

      #yum list | grep php

    4. 如果不能肯定PHP是否完全安装

      #yum install php

    5. 查看Apache的httpd.conf,确认DocumentRoot地址

      #vi /etc/httpd/conf/httpd.conf

    6. 建立一个测试用index.php

      #vi /var/www/html/index.php

      里面就一行

      <?php phpinfo(); ?>

    7. 启动Apache

      #/etc/ini.d/httpd start

    8. 远程无法访问,在远程使用

      #telnet 111.111.111.111 80

      ,结果无法连接

    9. 设置防火墙

      # vi /etc/sysconfig/iptables

      在类似的位置加入一行

      -A RH-Firewall-1-INPUT -m state –state NEW -m tcp -p tcp –dport 80 -j ACCEPT

      重新启动

      # /etc/init.d/iptables restart

    10. OK 访问 http://111.111.111.111/,可以正常访问了
    11. 下载gnix

      #wget http://www.nginx.org/download/nginx-0.8.53.tar.gz$ tar xvzf nginx-0.8.53.tar.gz
      # mkdir -p /usr/local/src/nginx
      # mv nginx-0.8.53 /usr/local/src/nginx/0.8.53

    12. Configure 分别报了没有C编译器,没有PCRE,没有MD5,所以需要安装

      #yum install gcc
      #yum install pcre pcre-devel
      #yum install openssl openssl-devel
      #yum .configure

    13. 编译安装

      #make
      #make install

    14. 建立一个快捷方式

      # ln -s /usr/local/nginx/sbin/nginx /usr/sbin/nginx

    15. 在另外一台机器中的index.php记入以下

      <?php
      echo(“Test Success!I am Another WebServer “);
      phpinfo();
      ?>

    16. 设置本地Nginx的conf

      vi /usr/local/nginx/conf/nginx.conf

      http {

      upstream myproject{
      server 111.111.111.112:80;
      server 111.111.111.113:80;
      }

      server {
      listen       80;
      server_name  111.111.111.111;

      location / {
      proxy_pass http://myProject;
      }

    17. 访问以下本地http://111.111.111.111/看是不是直接balance到了另外一台机器咯。