facebook注册上传照片 信息库里 怎么上传商品

您的位置: >>
  【编者注】王淮是Facebook第二位中国籍工程师,也是第一位中国籍研发经理,他一手开创了Facebook的支付安全和客服工具领域。2011年他离开Facebook,回国成为天使投资人,希望用自己在Facebook的经验帮助创业者。
  在详细说明Facebook产品开发流程的九大步骤之前,必须先讲清楚一点,这些是我用马后炮的方式来思考自己在Facebook做产品、项目的实践中可能出现的步骤。所谓的&流程&,在Facebook内部并不存在,这些步骤并不都是必须的。对于不同类型的项目,有些对时间要求高一些,所以更强调速度;有些对质量要求高一些,会更强调项目管理的流程(Process)。请读者在阅读时仔细斟酌,哪些符合自身的实际情况,则可以借鉴; 哪些不适合,要灵活掌握。
  描绘远景,设置目标
  做每件事情之前都要有明确的目标,在聚焦于细节之前要有大的远景(Vision),这可以在以后的实施过程中指引方向。对于远景的思考,主要围绕以下三点。
  1. 为什么设这个目标,而不是另外一个?
  2. 在做一件事情之前,脑子里应该有这件事情完成之后是什么样子这个画面,接下来很多事情都是围绕着这个最终画面来进行的。
  3. 计划做些什么来实现这个远景?这就需要将最终目标具体化,变成一个可以想象的图片,甚至量化,然后才能使得最终目标容易被别人理解。
  那又该如何设定目标呢?在Facebook,常用的方法是遵循&SMART&规则。
  S&&非常详细具体的(Specific)。目标必须被清晰定义,无法被混淆或者误解。
  M&&是能够衡量的(Measurable)。只有可以被衡量的目标,才能一直清楚做得如何,离目标有多远,当前是超出还是低于预期的进度。
  A&&要有足够的难度和挑战性(Aggressive)。容易完成的目标,很容易让员工懈怠;一旦失去战斗的激情,更谈不上发挥潜能。
  R&&现实的(Realistic),这是对上一点的平衡。过于有难度的目标,会令员工疲惫不堪,如果最后还是没能完成任务的话,对他们的信心是非常大的打击。
  T&&要有实现的期限(Time-bound)。没有实现期限的目标是没有意义的,因为不知道什么时候应该到达什么程度。
  有了目标之后,才可能有很详细的项目计划,所有的项目都应该是跟这些目标相关的。不相干的项目会分散注意力(Distraction),要坚决抵制。接下来,组里人员的绝大多数时间都要花在跟这几个目标相关的项目上。
  收集想法并排出优先次序
  有了目标以后,会产生很多相关的想法(Idea),但很难判断究竟哪个想法一定能达到这些目标,也不可能把所有的想法都试一遍,往往到最后都需要有理有据地 进行&赌博&,把精力押在某几个核心的想法上。这也是Facebook要招最好的工程师的原因之一。工程师不仅要善于写程序,也要有选择想法的能力,你不仅要对这个问题有很深入的思考,进行大量的分析,还要有胆量,能果断押注,并且有很高的命中率。
  那么,这些想法从何而来呢?最自然的方式就是之前延续下来的、大家明确知道要做的项目,而那些不明确的想法,才是难点。在发展非常快的公司里,绝对不会缺少这种不明确的想法。在Facebook, 一般是由技术经理、产品经理、工程师贡献大量的想法。负责商业运营(Business Operation)的同事也会贡献一些想法。做下一个月计划时,我会在当月25日左右开始给相关人员发一个一周后的头脑风暴会议邀请,并希望他们在会议之前把自己认为应做的或者想做的事情发邮件告诉我。我事先做分类整理,让会议进行得更加高效。当然,线下的讨论、分享等也是产生想法的好机会。
  接下来最为关键的就是分析想法&&如何挑选出最可能产生效果的想法。理论上,如果有无限的资源,我们应该尝试所有的想法。但在Facebook,任何时候都处于资源短缺的状态,我们必须把有限的资源放到有可能产生最大价值的想法上面。
  这里,我要特别强调一下&Top X(只做前X项)&规则:只做对目标最有影响的前X项。我们会对所有的想法进行讨论,根据每个想法对目标的影响和其所需要的资源(主要是人力与时间&& &人周&)进行讨论,然后排序(按P0,P1,P2&&的方式来),最后挑选排在最前面的几项。分析完后,对几个明显一定要做的想法很容易决定,对几个要去掉的也很容易决定,关键是剩下的那些想法,没有足够的精力把它们都尝试一遍,这就要考验你的抉择能力了。
  跨团队沟通
  决定了要做的项目之后,就需讨论如何跟其他相关组的计划对接。你当然不希望原本以为兄弟组能配合自己做一个项目时,却发现对方并未把与你项目相关的工作放入他们的计划中。这里要进行的沟通,就是让相关组之间做的事情是相辅相成的,而不是互相扯皮,造成不必要的内耗。
  有两类人是特别需要沟通的。
  1. 不同职能之间的沟通,包括工程师、产品经理、设计师,还有与项目相关的上下游团队或部门。
  2. 相关的工程兄弟组之间的沟通。因为大家相互之间经常有技术或者框架上的共享,我们定下要做的事情,就看看相互之间是否有可以匹配的项目,如果我们需要他们的配合,就要看怎样可以列入他们的计划。
  告知所有可能关心的人
  我们会召开一次最终的计划定夺会议。主要是由工程师和产品经理及一些非常相关的人参加,这种会议是小规模的,因为不想在决策时让其他非产品技术的人员参与进来,其他人的声音已经在之前的跨团队沟通过程中被充分地考虑了。如果前面的工作准备得比较好,这种会议速度都很快,一般半个小时左右。
  整个计划定下来之后,会发一封邮件给所有关心该计划的人和相关工作的人。并且会在接收人那里把老板、老板的老板都放进去,以确保他们能清楚、理解并支持我们组的计划。
  设计产品
  对于任何一个项目,具体执行中一般都涉及四个维度:功能(Feature Set),预期完成时间(Time to Market),预算(Budget,主要是人员,还有服务器、带宽资源、金钱等),完成质量(Quality,包括可扩展性Scalability、性能Performance等)。不管你做没做计划,所有的决定都围绕着这四个方面进行考量。如果进度拖后了,那么可以去掉或精简一个功能,或者推后完成的时间,或者增加人手、加大投入,或者降低质量等,无非就是在这四个方面进行取舍。
  很重要的一点是,设计产品时,要大概知道第一版本(V1)是什么样子。可以在设计时构思产品的最终状态,但公司不会允许花大量的资源去打造一个所谓的终极版本。一定要思考第一版本包含哪些功能、什么时间发布、要多少人员配置、要花多少钱做市场宣传、达到什么效果等。
  这可以避免一开始投入过大,但做出的产品并不是市场所需要的,再进行很大修改甚至放弃该产品的情况出现,这无疑是很大的浪费。
  而对于技术性的系统或框架,通常会召集相关专家开会,介绍新系统,并讨论为什么做这个系统,以及其优缺点、跟已有系统的关联。这种讨论会,相对技术性比较强,一般不会有产品经理参与(他们不大懂后台的技术),更多的是邀请有相关经验的后台工程师参加。
  这里要特别强调的是,Facebook非常注意不重复开发新的技术系统。一个原则是:有好的开源系统,就用开源的;有好的商用产品,就购买商用的;必须自己开发的或者跟Facebook核心竞争力息息相关的,则集中力量开发一套,而不是重复劳动,开发多套类似系统。而对于一些跟核心数据息息相关的系统,即使市场上有商用系统,Facebook还是会自己开发。
  另外,Facebook从不期望由一个人完成某个项目所有的事情。我会要求某个组员来承担某个项目的责任,但要的是让他驱动整个项目,并不代表所有的事情都完全靠他个人去做。我会要求他善于使用整个公司的力量,学会积极主动地获得别人的帮助,事半功倍地完成一个项目,同时在这个过程中获得成长。如果让其他组帮助做一些事情更加适合的话,我也会鼓励朝这个方向努力。
  但如果一个项目最终不成功,那么项目负责人是不能以别人无法提供帮助作为借口的。因此,即使别人答应帮忙,项目负责人还是需要学会去激励别人、监督别人,通过&抒情讲理&甚至&威逼利诱&等各种手段获得及时的帮助。
  但Facebook的文化鼓励只有适合寻求帮助时才这么做,属于一个项目核心的工作必须由该团队自身去完成。别人一般只能在他们的系统上给予配合或者技术上给予建议,最主要的挑战还是靠自己。也只有这样,一个团队才能真正获得成长。
  指定项目责任人
  要为每一个项目都指定一个明确的责任人,一般都是工程师。这样做最大的好处是责任非常清楚,每一个项目都有非常清晰的拥有者(Owner),这让推脱责任变得很难。
  第二个好处是锻炼员工的才能。Facebook不希望初级工程师永远做螺丝钉的角色,希望每个工程师都能积极领导一项任务,推动项目进展。责任明确的项目可以&逼迫&工程师担当起责任。
  第三个好处是方便交流。公司里任何一位对某个项目感兴趣的同事都可以了解该项目的进展情况,项目责任人就是他交流的对象,而不需要一定要去找技术经理或者产品经理。
  定期碰头会
  对于每一个开发中的项目,我们都要清楚地知道具体进展,因为今天做好的东西是明天的基础。根据项目的紧急性和重要程度定期讨论,可以每天都进行,也可以每周进行一两次。一般每次会议在10~30分钟,而越频繁的碰头用的时间应该越短。
  召开碰头会时,所有跟这个项目相关的人都要参与,围绕着这个项目把所有相关的任务及其进展迅速过一遍,每个人把自己前一天(或者前一周)完成的任务情况汇报 一下。如果遇到了困难,大家会集中讨论,帮忙解决。最好不要找一些愚蠢的借口来搪塞,这将导致原先答应的事情没有按时按质按量地完成。
  了解进度 汇总报告
  对负责一个团队的研发经理而言,要对自己组里正在进行的每个项目都有深入和及时的了解,知道最新进展。处于绿灯状态的,当然很好,要给予鼓励;处于黄灯状态 的,要给予适当的帮助,挪掉绊脚石,加速项目进展;处于红灯状态的,要了解为什么会这样,还能否采取相应措施补救。在行动之外,非常重要的就是反省,弄清楚为什么没有在黄灯时及时发现并给予帮助,然后吸取教训,避免将来出现同样的失误。
  对战斗在第一线的团队,定期的项目碰头会可以让某个项目的所有战斗人员都能保持对信息获取的一致性,有共同的交流基础。然而,后方人员,比如关心某个项目的同事或者老板的老板等,要了解一个项目的进展不是非常轻松的事情。作为研发经理,我会在每周五把组里当前正在进行的所有项目的进展情况汇总到一起,形成简报,给所有关注支付产品的人发邮件,让他们都能有机会了解到相关情况。
  发布产品 监测数据
  产品完成开发之后,当然就要推出去。推出去之前,有些产品需要进行风险控制。比如,支付类的产品经常会做发布前评估(Pre-launch Review)。
  所谓发布前评估,就是在发布之前,根据具体的产品或者该次发布的特点,做一些诸如发布策略、需监测的核心数据、产品演示、核心算法改变等方面的讨论。在做产品讨论时,我会要求参会的人员思考这个问题&&&如果这次发布出现大问题的话,可能会是什么?&主要目的是在发布之前思考可能会出现失误的节点,如果是大风险,做一些必要的防护措施;如果是小风险,心里要清楚自己在冒这个险,准备好一旦出问题该如何补救。另外,由于Facebook发布的产品比较多,经常出现互相影响的情况,做发布前评估可以让大家知道什么产品即将在什么时候推出去。
  一种发布工程的做法是阀门控制式的灰度发布,就是有所控制地选择发布的人群及其比例。灰度发布是控制发布的范围和速度,但如何才能得知某一阶段产品发布的质量,何种状况下才提高灰度发布的范围呢?只有通过数据监测来判断发布状态。需要监测两类数据。
  一类数据反映当前的系统状态,比如访问总量、访问成功量及其占总量的比例、致命范围错误的量和比例、访问速度、出现最多的错误类型统计等。这些数据的统计和展示都应该是实时的,才能确保一旦发生问题,能够在最短的时间内发现并采取措施。
  另一类数据反映新功能的用户影响(User Impact或者Business Insight)。这部分数据能直接反映出一开始做这个产品或者功能的目的。只有这部分的数据反馈是正向的,而且其变化达到了让人接受的程度,才可以考虑扩大发布范围。
  并不是所有的发布都是成功的。从我的经验来看,追求完美的发布是不现实的,不管之前的Pre-launch Review多么全面,每次发布都有这样或者那样的问题产生,最好的情况就是每次的问题都是新的,而不是上次已经出现的失误。但在问题发生之后,通常通过 Post-Mortem尝试尽可能从失误中吸取教训,让每次的发布带来的学习价值最大化。
  所谓Post-mortem,是通过分析过去发生的问题,从中总结可以采取的行动方案,以避免类似的错误再次发生。不仅适合于产品发布产生的问题研究,同时也常用于任何突发事件的事后分析。
  以上就是我所总结的Facebook产品开发流程,当然,对于每一个具体的产品来说,不一定严格按照这些步骤进行,但大体的思路类似。根据需要,部分步骤可以被省略。根本目的是为了在产品满足基本的质量标准之后,尽可能早地发布出去,然后根据监测数据再快速迭代。
  我跟国内的一些创业公司就产品开发流程进行过沟通,希望硅谷公司的思路可以带给他们启发。然而,Facebook的这些做法不一定适用于中国的互联网企业。 在Facebook,很多时候是在证明你不行之前,假设你有能力完成一件艰巨的任务。由于Facebook招的人都是最顶尖的,这种假设在多数情况下被证明是可行的。
  本文节选自印刷工业出版社《打造Facebook:亲历Facebook爆发的5年》一书。特此感谢作者王淮的授权。本文选登时有删减。
软件工程热门文章
软件工程最新文章拒绝访问 |
| 百度云加速
请打开cookies.
此网站 () 的管理员禁止了您的访问。原因是您的访问包含了非浏览器特征(3ad10d4d131d437c-ua98).
重新安装浏览器,或使用别的浏览器使用 Bluemix 和 MEAN 堆栈构建自助发表 Facebook 信息的应用程序,第 2 部分:将用户信息存储在服务器上
有时用户希望当他们不在线时,服务器代表他们向 Facebook
发表帖子。例如,业务页面的所有者可能希望在某款产品的库存不多时发布公告,鼓励顾客在还有货时尽快购买。或者一个人可能希望他的时间表以随机的间隔发布消息。可以编写一个服务器来实现此目的,但这么做并不容易。在这个 3 教程系列文章中,我将展示如何使用 IBM Bluemix
作为云提供商来实现此目的。本系列还会介绍 MEAN 堆栈所有 4
个组件的基本知识。为了演示此功能,我将展示如何构建一个应用程序,在随机的时间代表用户发表笑话。 介绍如何使用 Facebook 作为登录来源和身份验证机制。 第 2 部分(本教程)介绍如何配置 MongoDB 来存储从 Facebook 获取的用户信息。
介绍如何使用 Facebook REST API 让服务器充当用户。构建您的应用程序所需的准备工作一个
帐户。HTML 和 JavaScript 的知识。一个 Facebook 帐户。一个可将 Node.js 应用程序上传到 Bluemix 的开发环境,比如 Eclipse。要使用 Eclipse,请参阅 “”。如果应用程序仅知道来自 Facebook
的某个用户已经过验证,那么拥有已验证的用户毫无意义。要使用身份验证功能,您必须拥有访问用户信息的能力。要查看您能使用哪些用户信息,可将以下代码添加到
facebook.js 文件中的 loggedOn 函数中。// Download the user information.
// Show the response in the status.
FB.api('/me', function(response) {
setFacebookStatus("User information:" +
JSON.stringify(response));
});JSON.stringify 函数将一个对象转换为它的 JSON 字符串表示。结果与下面的内容类似:User information:{"id":"85551","email":"ori@","first_name":"Ori","gender":"male","last_name":"Pomerantz","link":"/app_scoped_user_id/85551/","locale":"en_US","name":"Ori Pomerantz","timezone":-5,"updated_time":"T02:52:51+0000","verified":true}用户的名称是 request.name。要向用户给予问候,而不是在用户已登录时要求用户登录,可执行以下更改:在 datamodel.js 文件中,将 myApp.controller
调用改为:myApp.controller("facebookCtrl", function($scope) {
// Status of Facebook communications
$scope.fbStatus = "";
// Name of the connected person
$scope.userName = "";
});您需要修改多个范围变量,而不只是 fbStatus。为了简化此过程,将函数
setFacebookStatus
替换为:// This function sets the a scope variable to a value.
// It is useful to have this function so that the rest of
// the JavaScript code would be able do this without relying
// on Angular
var setScopeVar = function(variable, value) {
var scope = angular.element($("#facebookCtrl")).scope();
// scope.$apply takes a function because of re-entrancy.
// The browser may not be able to handle changes in the
// scope variable immediately, in which case the function
// will be executed later.
scope.$apply(function() {
scope[variable] =
var setFacebookStatus = function(status) {
setScopeVar("fbStatus", status);
};在 facebook.js 文件中,将 loggedOn
函数改为://This function is called when we KNOW the user is logged on.
function loggedOn() {
setFacebookStatus("You're in");
FB.api('/me', function(response) {
setScopeVar("userName", response.name);
}在 index.html
文件中,将要求登录的部分改为:&fb:login-button scope="public_profile,email"
onlogin="checkLoginState();" ng-if="userName == ''"&
&/fb:login-button&
&div ng-if="userName != ''"&
Hello {{userName}}
&/div&注意在
&fb:login-button& 和 &div&
标签内使用了 ng-if
属性。此属性使您能够指定,仅在条件满足时才显示一个特定的标签和其中的内容。因此,如果 userName
是空的,用户将看到登录按钮。但如果它有一个值,用户会看到一个问候语,其中包含用户的名称。现在,用户信息可供浏览器使用。但是您需要将它存储在服务器上。这需要两个操作:从浏览器向服务器发送一条包含该信息的请求。将信息存储在一个数据库中。为此,最简单的方法是创建一个数据库,然后通过 REST 服务来访问数据库。在
中,您将创建该数据库中。在
中,您将创建和使用该 REST 服务。第 2 步.
配置一个 MongoDB 数据库Node.js 常用的 MongoDB 数据库可在 Bluemix 上以一个单独服务的形式来提供。登录 Bluemix 仪表板。单击 ADD A SERVICE OR API 磁贴。在 Web and Application 列表中,单击 mongodb。选择您使用的应用程序空间(如果能访问多个空间)和应用程序。为了能够剪切和粘贴代码,我建议您使用服务名称
mongodb-usingfb。单击 CREATE。 出现提示时单击 RESTAGE。在 package.json 文件中修改依赖项,以指定该应用程序需要
MongoDB,如下所示。新的代码内容已加粗。"dependencies":{
"express":"4.12.x",
"cfenv":"1.0.x",
"mongodb":"*" },在 manifest.yml 文件中修改依赖项,以指定该应用程序使用
mongodb-usingfb,如下所示。新的代码内容已加粗。--- applications:
- disk_quota:1024M
host: fb-bluemix2
name: fb-bluemix2
domain: mybluemix.net
instances:1
memory:256M
mongodb-usingfb:
label: mongodb
version:'2.4'
plan:'100'
provider: core第 3 步.
连接到 MongoDB 数据库现在您已拥有数据库,下一步是从服务器应用程序连接该数据库。该服务器应用程序的源代码位于 app.js 文件中。在从 Cloud Foundry
获取应用程序环境的代码行的下面添加以下代码,连接到数据库。// Find the MongoDB service from the application
// environment
var dbInfo = appEnv.getService(/mongodb/);
// If there is no MongoDB service, exit
if (dbInfo == undefined) {
console.log("No MongoDB to use, I am useless without it.");
process.exit(-1);
// The variable used to actually connect to the database. It starts
// as null until gives a usable value in the connect function.
var userCollection =
// Connect to the database. dbInfo.credentials.url contains the user name
// and password required to connect to the database.
require('mongodb').connect(dbInfo.credentials.url, function(err, conn) {
if (err) {
console.log("Cannot connect to database " + dbInfo.credentials.url);
console.log(err.stack);
process.exit(-2);
console.log("Database OK");
// Set the actual variable used to communicate with the database
userCollection = conn.collection("users");
});重新运行该应用程序。发送修改后的应用程序并在 Bluemix 上执行时,选择 Save to manifest
file,然后单击 Next,直到您到达服务选择面板。在这里选择 mongodb-usingfb,然后单击
Finish。确保在控制台中看到了成功消息。第 4 步.
测试数据库连接要验证数据库连接,可将以下代码添加到 app.js 文件中。此代码会尝试插入数据库并从中读取信息。// Insert data into the collection. If there is an after
// function, call it afterwards
var insertData = function(data, after) {
// If the userCollection is not available yet,
// wait a second and try again.
if (userCollection == null) {
setTimeout(function() {insertData(data, after);}, 1000);
// Insert the data
userCollection.insert(data, {safe: true}, function(err) {
if (err) {
// Log errors
console.log("Insertion error");
console.log("Data:" + JSON.stringify(data));
console.log("Stack:");
console.log(err.stack);
// If no error, call after();
if (after != null)
// Read data in the collection, run the perEntry function on
// each entry.
var readData = function(filter, perEntry) {
// If the userCollection is not available yet,
// wait a second and try again.
if (userCollection == null) {
setTimeout(function() {readData(filter, perEntry);}, 1000);
// If we're successful, run perEntry on each entry. If not, log
// that fact.
userCollection.find(filter, {}, function(err, cursor) {
if (err) {
console.log("Search error");
console.log("Filter:" + JSON.stringify(filter));
console.log("Stack:");
console.log(err.stack);
cursor.toArray(function(err, items) {
for (i=0; i & items. i++)
perEntry(items[i]);
// End of cursor.toArray
// End of userCollection.find
// End of readData
insertData({name: "jack", id: 25}, null);
readData({}, function(entry) {
console.log("Entry:" + JSON.stringify(entry));
});注意,定期轮询 userCollection 变量(这里采用的方式)的效率很低。我使用它而不使用 Node.js
的事件基础设施的唯一原因是,该过程仅在应用程序启动时执行。在这之后,userCollection 应始终可用。可以为浏览器设计您自己的接口来读取和写入用户信息。但为什么要这么麻烦呢?对于这个问题,现在已有一个非常完美的标准:。在 package.json 文件中修改依赖项,以指定该应用程序需要 body-parser
包,如下所示。新的代码内容已加粗。这个包用于解析 HTTP 请求的正文,这对创建或更新条目的 REST
请求很有必要。"dependencies":{
"express":"4.12.x",
"cfenv":"1.0.x",
"mongodb":"*",
"body-parser":"*" },在
app.js 文件中现有的 app.get 调用上方输入以下小步骤(步骤 2 到
6)中代码。新调用被限制到路径 /rest/user
或它之下的路径,而且对于这些路径,调用应覆盖一般的处理函数。注释中已解释了代码的作用。输入以下代码,其中包含 REST
接口所需的定义。// The CRUD functions (Create, Read, Update, Delete) are
// implemented under /rest/user
var restUserPath = "/rest/user";
// The body-parser is necessary for creating new entities
// or updating existing ones. In both cases, the entity
// attributes appear as JSON in the HTTP request body.
var bodyParser = require('body-parser');添加以下代码,该代码展示了如何处理 POST 请求,以创建新用户。通常在 REST 中,一个 POST
请求会返回所创建的新条目的标识符,但在本例中,我使用 Facebook
ID,所以不需要此请求。// Create is implemented in REST as HTTP Post, without the
// ID (usually the client won't know the ID in advance,
// although in this case it does).
app.post(restUserPath, bodyParser.json(), function(req, res) {
var userData = req.
// bodyParser.json() takes care
// of parsing the request
console.log("Trying to add user: " + JSON.stringify(userData));
// After inserting the data, call res.send() to send an
// empty response to the client, which is interpreted as
// "operation successful".
// This is demonstration code. In production code you
// need to add more intelligent error handling than
// pretending they never happen.
insertData(userData, function() { res.send()});
});添加以下代码,处理对所有用户信息的请求。// GETting restUserPath gives a list of users with their
// full information. In production code you would limit
// the query size.
app.get(restUserPath, function(req, res) {
userCollection.find({}, // Empty filter for all users,
{}, // No options
function(err, cursor) {
if (err) {
console.log("Search error in getting the whole list");
console.log("Stack:");
console.log(err.stack);
// Respond to avoid getting the request forwarded to the
// next handler.
res.send();
cursor.toArray(function(err, items) {
// Send the item array.
res.send(items);
// End of cursor.toArray
// End of userCollection.find
});添加以下代码,处理对一个特定用户信息的请求。这是您第一次包含用户 ID 作为 URL
的一部分。// GETting restUserPath/&id& gives all the information
// about the user with that id. The :id means that the
// string that matches it will be available in the
// request as req.params.id.
app.get(restUserPath + "/:id", function(req, res) {
userCollection.find({"id": req.params.id},
{}, // No options
function(err, cursor) {
if (err) {
console.log("Search error in getting a single item");
console.log("Stack:");
console.log(err.stack);
// Respond to avoid getting the request forwarded to the
// next handler.
res.send();
cursor.toArray(function(err, items) {
res.send(items[0]);
// End of cursor.toArray
// End of userCollection.find
});添加以下代码,执行更新和删除操作。注意,MongoDB 允许您修改文档中的字段(在 MongoDB
中,大体来讲这表示一个关联数组),方法是用 $set
参数名并将值放在字段及其新值的关联数组中。// PUT is used to update existing entries.
app.put(restUserPath + "/:id", bodyParser.json(), function(req, res) {
// In a MongoDB update, you can use the command $set followed
// by an associative array of all the fields you wish to set and
// their new values.
userCollection.update({"id": req.params.id}, {$set: req.body},
{upsert: true});
res.send();
// DELETE, logically enough, deletes a user
app.delete(restUserPath + "/:id", function(req, res) {
userCollection.remove({"id": req.params.id});
res.send();
});用户登录时,浏览器不知道需要创建用户条目,还是更新用户条目。但是,因为更新操作拥有参数
upsert: true,所以您始终会更新该条目。如果它不存在,就会创建它。要发送此信息,可编辑 facebook.js 文件来修改 loggedOn 并添加新函数
putUserInfo,如下所示:var loggedOn = function() {
setFacebookStatus("You're in");
FB.api('/me', function(response) {
setScopeVar("userName", response.name);
// Only send the information we want to store
putUserInfo({id: response.id,
name: response.name,
email: response.email
// This function PUTs the user information to the server
var putUserInfo = function(userInfo) {
// The URL. A relative URL so we don't have to
// figure out the host we came from.
var url = "rest/user/" + userInfo.
// $ is a variable that holds jQuery functions.
// AJAX is asynchronous Javascript and XML,
// which is used to communicate with servers
// The HTTP verb we use
type: "PUT",
// Use JSON (rather than XML)
contentType: "application/ charset=utf-8",
data: JSON.stringify(userInfo),
// Function called in case this is successful
success: function(msg) {
// If we wanted to report success
// Function called in case this fails
error: function(msg) {
alert("Problem with user information:" + msg);
}此刻,攻击者只需要用户的 Facebook ID 即可读取和修改用户的信息。幸运的是,Facebook 提供的用户 ID
是特定于此应用程序的。但是,为了预防 ID 被滥用,您需要隐藏它。为此,将 app.js 文件中的第一个 app.get
函数改为以下代码,并注释掉第二个函数(需要用户 ID 的函数)。// GETting restUserPath gives a list of users with their
// information. In production code you would limit
// the query size.
app.get(restUserPath, function(req, res) {
userCollection.find({}, // Empty filter for all users,
{}, // No options
function(err, cursor) {
if (err) {
console.log("Search error in getting the whole list");
console.log("Stack:");
console.log(err.stack);
// Respond to avoid getting the request forwarded to the
// next handler.
res.send();
cursor.toArray(function(err, items) {
// items array, but limited to the
// information we are willing to send
var censored = new Array(items.length);
// Only send the users' names
for (var i=0; i&items. i++)
censored[i] = {
name: items[i].name
// Send the censored array.
res.send(censored);
// End of cursor.toArray
// End of userCollection.find
});Facebook 提供的用户 ID 是一个共享秘密,Facebook 和服务器都拥有它。但是,需要将它从 Facebook
传输到浏览器,因为要使用该条目向浏览器应用程序执行验证。如果它来自服务器,攻击者就能通过某种途径获取它,尽管攻击者没有被验证,情况也是如此。记住,客户端代码可供攻击者使用,所以他们可在客户端和服务器之间的协议中模仿任何角色。结束语您现在已将用户信息存储在服务器上。这个谜题中剩下的唯一部分就是如何实际使用该信息来控制
Facebook,我将在本系列的下一篇文章中解释这个难题:“”
添加或订阅评论,请先或。
有新评论时提醒我
static.content.url=/developerworks/js/artrating/SITE_ID=10Zone=Cloud computing, Web developmentArticleID=1010819ArticleTitle=使用 Bluemix 和 MEAN 堆栈构建自助发表 Facebook 信息的应用程序,第 2 部分:将用户信息存储在服务器上publish-date=

我要回帖

更多关于 facebook上传照片 的文章

 

随机推荐