2014-12-29 67 views
0

嘗試添加pdf文件生成時出現奇怪的行爲。使用服務器路由和onBeforeAction時出現異常

下面的代碼,在if語句,拋出: 兩個\ routes.js

Router.onBeforeAction(function() { if (!Meteor.user() || Meteor.loggingIn()) { 
    this.redirect('welcome.view'); } else { 
    Meteor.call("userFileDirectory", function (error, result) { 
     if (error) 
     throw error; 
     else 
     console.log(result); 
}); 
    this.next(); } }, { except: ['welcome.view'] }); 

Error: Meteor.userId can only be invoked in method calls. Use this.userId in publish functions. at Object.Meteor.userId (packages/accounts-base/accounts_server.js:19:1) at Object.Meteor.user (packages/accounts-base/accounts_server.js:24:1) at [object Object].Router.onBeforeAction.except (app/both/3-router/routes.js:10:15) at packages/iron:router/lib/router.js:277:1 at [object Object]._.extend.withValue (packages/meteor/dynamics_nodejs.js:56:1) at [object Object].hookWithOptions (packages/iron:router/lib/router.js:276:1) at boundNext (packages/iron:middleware-stack/lib/middleware_stack.js:251:1) at runWithEnvironment (packages/meteor/dynamics_nodejs.js:108:1) at packages/meteor/dynamics_nodejs.js:121:1 at [object Object].dispatch (packages/iron:middleware-stack/lib/middleware_stack.js:275:1)

只有當我這段代碼添加到該文件,和/ PDF路線採取:

Router.route('/pdf', function() { 
    var filePath = process.env.PWD + "/server/.files/users/test.pdf"; 
    console.log(filePath); 
    var fs = Npm.require('fs'); 
    var data = fs.readFileSync(filePath); 
    this.response.write(data); 
    this.response.end(); 
}, { 
    where: 'server' 
}); 

上面的代碼工作正常;當我取出onBeforeAction代碼時,PDF將呈現在屏幕上,並且不會引發異常。

反過來也是如此,如果我拿出服務器路由,沒有路由導致異常。

回答

1

這是因爲您使用的路由是服務器端路由。 Meteor用來驗證用戶的技術是通過DDP協議通過websockets完成的。

當您的瀏覽器向服務器發送GET/POST請求時,它沒有任何有關用戶身份驗證狀態的信息。

您在您的Route.onBeforeAction中使用Meteor.user(),但它無法訪問此信息。

解決方法是找到驗證用戶的另一種方法。一種這樣的方法是使用cookie。

這是已知問題流星的認證系統,請參閱:https://github.com/EventedMind/iron-router/issues/649

+0

我在這裏閱讀你的答案:http://stackoverflow.com/questions/16727922/access-meteor-userid-from-outside-a-method-publish,我現在可以使用這個過程(寫在' 13)?如果是這樣,我會將Cookie檢查代碼放在onBeforeAction方法或服務器端路由中嗎? – Aaron

+0

我想你回答了爲什麼,如何解決這個問題由David Weldon在這裏回答:http://stackoverflow.com/questions/27714618/server-side-routes-in-iron-router-and-meteor – Aaron

+0

什麼我意思是說,問題是關於例外,並且每個David Weldon的答案都是例外,但是服務器端認證系統/方法仍然需要解決(這是您答案的一部分,但沒有完全回答這個問題)...再次,你確實回答了爲什麼會發生這種情況,但僅以身份驗證而言。 – Aaron

1

比cookie更好的辦法可能是流星的命名集合存儲帳戶及一些的sessionId:

你可以存儲在當前用戶id在調用服務器之前,客戶端:

var sessionId = Random.id(); 
col = new Mongo.Collection('session'); 
col.insert({ 
    sessionId: sid, 
    userId: Meteor.userId(), 
    issued: new Date() 
}); 

再經過sessionId到服務器通過GET/POST請求和讀它在服務器上:

var sid = this.request.query.sid; 
var user = col.findOne({sessionId: sid}); // returns an object 

使用單獨的參數比使用userId本身,因爲你可以撤銷這個sessionId一段時間後或服務器的呼叫後,立即更好。

正確allow/deny權限是必需的,以防止任何人更新集合。另外,請注意,您不能相信客戶端的new Date()

+0

感謝。但是你能說出爲什麼這是更好的方法嗎? – Aaron

+0

這似乎是一個錯誤的代碼,因爲我們可能有很多用戶,對此抱歉! – romaroma

+0

流星收集是一種安全且被動的方式,用於瞭解用戶是否仍被認證/授權執行某項操作。餅乾不是。但上面的代碼將無法正常工作(我們不得不使用一些ID在客戶端和服務器上提及我們重複的用戶id保存收藏。 – romaroma

相關問題