---
title: 添加用戶
slug: adding-users
date: 0006/01/01
number: 6
points: 5
photoUrl: http://www.flickr.com/photos/kroqert/9687074783/
photoAuthor: B?rd Harald Krogen
contents: 學習 Meteor 的用戶帳戶。|在 Microscope 中添加所有必要的用戶驗證。|使用內置的 accounts-ui 包實現實時性的用戶界面。
paragraphs: 27
---
到目前為止,我們已經以較合理的方式去創建并顯示一些靜態數據,并將其連接到成一個簡單的數據原型。
盡管我們的界面是根據變化的數據進行即時響應的,并且數據的實時插入或更改的都會在界面上得到體現。然而,我們的網站似乎還沒有提供用戶去修改數據的頁面。實際上,我們甚至連用戶都還沒有!
下面讓我們看看如何去解決這個問題吧。
### 賬戶:讓用戶變得簡單
在大多數的 web 框架,添加用戶帳戶是一個熟悉而又麻煩的工作。然而,你所做的每一個項目幾乎都要用到,但它都不曾讓我們覺得簡單過。甚至如果當你要處理開放授權(OAuth)或其他第三方身份驗證的時候,這些工作往往會變得更加惡心和復雜。
幸運的是, Meteor 可以幫你輕松解決。由于 Meteor 包的代碼可以同時運行在服務器(JavaScript)和客戶端(JavaScript、HTML 和 CSS),這樣我們就可以很輕松地得到一個賬戶系統。
我們可以使用 Meteor 內置的賬戶界面(通過 `meteor add accounts-ui` ),但是由于我們已經在構建 App 的時候用了 Bootstrap 包,所以我們將使用 `accounts-ui-bootstrap-3` 包去代替(別擔心,唯一的區別只是里面的樣式不同)。我們在終端輸入:
~~~bash
meteor add ian:accounts-ui-bootstrap-3
meteor add accounts-password
~~~
<%= caption "Terminal" %>
這兩個命令的作用是把一些特別的賬戶模板提供到我們的項目,然后就可以通過 `{{loginButtons}}` helper 在我們的網站中使用。溫馨提示:你可以去控制登錄框下拉菜單的對齊方向,通過添加其 `align` 屬性(例如:`{{loginButtons align="right"}}`)。
我們將按鈕添加到我們的頭部(header)模板。這樣頭部包含的內容將會越來越多了,下面我們為它騰出更多的空間吧(我們將把它放在 `client/templates/includes/` )。同時我們使用一些額外的標記和 class [請參考 Bootstrap](http://getbootstrap.com/components/#navbar) 來使界面更好看:
~~~html
<template name="layout">
<div class="container">
{{> header}}
<div id="main" class="row-fluid">
{{> yield}}
</div>
</div>
</template>
~~~
<%= caption "client/templates/application/layout.html" %>
<%= highlight "3~6" %>
~~~html
<template name="header">
<nav class="navbar navbar-default" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navigation">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="{{pathFor 'postsList'}}">Microscope</a>
</div>
<div class="collapse navbar-collapse" id="navigation">
<ul class="nav navbar-nav navbar-right">
{{> loginButtons}}
</ul>
</div>
</nav>
</template>
~~~
<%= caption "client/templates/includes/header.html" %>
現在,去瀏覽我們的 App,我們會看到賬戶登錄的按鈕出現在網站的右上角。
<%= screenshot "6-1", "Meteor 內置的賬戶界面" %>
這樣我們就可以用它來注冊,登錄,改變密碼,它擁有和其他所有網站一樣的賬戶系統功能。
如何告訴我們的賬戶系統要求用戶需要通過用戶名密碼來登錄?只需配置一個 Accounts.ui 模塊到一個名叫 `config.js` 的文件里面,并把文件放在 `client/helpers/` 中:
~~~js
Accounts.ui.config({
passwordSignupFields: 'USERNAME_ONLY'
});
~~~
<%= caption "client/helpers/config.js" %>
<%= commit "6-1", "添加賬戶和它的模板到頭(header)模板" %>
### 創建我們的第一個用戶
接下來去注冊一個帳戶:然后“登錄”按鈕會變成顯示你的用戶名。這說明了一個用戶帳戶已經創建成功。但是,用戶帳戶的數據來自哪里呢?
在添加 `accounts` 包以后, Meteor 已經創造了一個新的集合,它可以通過 `Meteor.users` 去訪問。為了驗證它,打開你的瀏覽器控制臺并輸入:
~~~js
? Meteor.users.findOne();
~~~
<%= caption "瀏覽器控制臺(Browser console)" %>
控制臺應該會返回一個用戶對象,如果你仔細看看,可以找到你的用戶名,以及唯一標識你賬號的 `_id` 。注意,你還可以通過 `Meteor.user()` 獲得當前登錄的用戶。
現在我們注銷并再次注冊一個不同的用戶名。 `Meteor.user()` 現在應該返回第二個注冊的用戶。但是等一等,我們看看先運行:
~~~js
? Meteor.users.find().count();
1
~~~
<%= caption "瀏覽器控制臺(Browser console)" %>
控制臺返回的是1?難道不是2嗎?第一個用戶被刪除了嗎?如果你再次登錄第一個用戶,你會發現并沒有被刪除。
讓我們去 Mongo 數據庫里面查查看吧。進入 Mongo 數據庫(在終端輸入 `meteor mongo` )輸入以下代碼:
~~~bash
> db.users.count()
2
~~~
<%= caption "Mongo console" %>
確定是存在兩個用戶。可是剛剛為什么我們在瀏覽器中只看到一個呢?
### 發布的謎團!
如果你回想起第4章,可能還記得我們移除了 `autopublish` 包,我們阻止了集合從服務器自動發送所有數據到每個訪問的客戶端。然后我們創建了發布和訂閱方法來實現數據的傳輸。
但我們并沒有設置過任何用戶的發布方法。那為什么我們還可以看到用戶的數據呢?
答案就是賬戶包確實“自動發布”了當前登錄用戶的基本賬戶信息。如果沒有的話,該用戶是無法登錄到網站的!
不過賬戶包只發布了**當前**登錄的用戶。這就解釋了為什么一個用戶看不到另一個帳戶的詳細信息了。
所以發布的只是當前登錄用戶的用戶對象(而且當你注銷之后就沒有了)。
更重要的是,我們用戶的集合似乎在服務器和客戶端中并不是包含完全相同的字段。在 Mongo 數據庫中,用戶擁有大量的數據。為了檢驗一下,回到你的 Mongo 終端并輸入:
~~~bash
> db.users.find()
{
"_id": "H5kKyxtbkLhmPgtqs",
"createdAt": ISODate("2015-02-10T08:26:48.196Z"),
"profile": {},
"services": {
"password": {
"bcrypt": "$2a$10$yGPywo3/53IHsdffdwe766roZviT03YBGltJ0UG"
},
"resume": {
"loginTokens": [{
"when": ISODate("2015-02-10T08:26:48.203Z"),
"hashedToken": "npxGH7Rmkuxcv098wzz+qR0/jHl0EAGWr0D9ZpOw="
}]
}
},
"username": "sacha"
}
~~~
<%= caption "Mongo console" %>
但是在瀏覽器中,用戶對象的字段就比較少了,可以通過輸入這樣的命令看到:
~~~js
? Meteor.users.findOne();
Object {_id: "kYdBd9hr3fWPGPcii", username: "tmeasday"}
~~~
<%= caption "瀏覽器控制臺(Browser console)" %>
這個例子向我們展示了本地集合是如何成為一個**安全的**數據庫**數據子集**。登錄用戶只能看到那些足夠去配合客戶端工作(例如:登陸)的集合屬性。以后你會知道這是一個非常值得學習的模式。
但這并不意味著你就不能把更多的用戶數據發布出來。你可以參考[ Meteor 說明文檔](http://docs.meteor.com/#meteor_users),看看 `Meteor.users` 集合是如何選擇性地發布更多的字段。