fix: QA/Infosec update and python to chinese

This commit is contained in:
Oliver Eyton-Williams
2020-08-13 12:00:20 +02:00
committed by Mrugesh Mohapatra
parent 2c78402837
commit 1cfa09adc4
861 changed files with 6847 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
---
id: 589fc832f9fc0f352b528e78
title: Announce New Users
challengeType: 2
videoUrl: ''
localeTitle: 宣布新用户
---
## Description
<section id="description">提醒一下,这个项目是基于<a href="https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-socketio/">Glitch</a>的以下入门项目构建的,或者是从<a href="https://github.com/freeCodeCamp/boilerplate-socketio/">GitHub</a>克隆的。许多聊天室能够在用户连接或断开连接时进行通知然后将其显示给聊天中的所有连接用户。看起来您已经在连接和断开连接上发出事件您只需修改此事件即可支持此功能。最合乎逻辑的方法是使用事件发送3个数据连接/断开用户的名称,当前用户计数以及连接或断开连接的名称。 <hr>将事件名称更改为“user”并且数据传递一个对象包含字段&#39;name&#39;&#39;currentUsers&#39;和boolean&#39;connected&#39;如果是连接则为true对于断开发送的用户则为false。确保对我们有&#39;用户计数&#39;事件的两个点进行更改,并将断开连接设置为对&#39;field&#39;字段发送false而不是像在connect上发出的事件那样为true。 <code>io.emit(&#39;user&#39;, {name: socket.request.user.name, currentUsers, connected: true});</code>现在您的客户端将拥有所有必要信息以便在用户连接或断开连接时正确显示当前用户数和通知要在客户端处理此事件我们应该监听“用户”然后使用jQuery将<code>#num-users</code>的文本更改为“{NUMBER}在线用户”,并附加<code>&lt;li&gt;</code> ,以更新当前用户数<code>&lt;li&gt;</code>使用ID为&#39;messages&#39;的无序列表,其中&#39;{NAME}已{加/左}聊天。&#39;。此实现可能如下所示: <pre> socket.on&#39;user&#39;functiondata{
$&#39;num-users&#39;。textdata.currentUsers +&#39;users online&#39;;
var message = data.name;
ifdata.connected{
消息+ =&#39;已加入聊天。&#39;;
} else {
消息+ =&#39;离开了聊天。&#39;;
}
$&#39;messages&#39;。append$&#39;&lt;li&gt;&#39;。html&#39;&lt;b&gt;&#39;+ message +&#39;&lt;\ / b&gt;&#39;;
}; </pre>当您认为自己已经做对时,请提交您的页面。 </section>
## Instructions
<section id="instructions">
</section>
## Tests
<section id='tests'>
```yml
tests:
- text: 使用namecurrentUsers和connected发出事件“user”
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /io.emit.*('|")user('|").*name.*currentUsers.*connected/gi, 'You should have an event emitted named user sending name, currentUsers, and connected'); }, xhr => { throw new Error(xhr.statusText); })
- text: 客户正确处理和显示事件'用户'中的新数据
testString: "getUserInput => $.get(getUserInput('url')+ '/public/client.js') .then(data => { assert.match(data, /socket.on.*('|\")user('|\")[^]*num-users/gi, 'You should change the text of #num-users within on your client within the \"user\" even listener to show the current users connected'); assert.match(data, /socket.on.*('|\")user('|\")[^]*messages.*li/gi, 'You should append a list item to #messages on your client within the \"user\" event listener to announce a user came or went'); }, xhr => { throw new Error(xhr.statusText); })"
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

View File

@@ -0,0 +1,51 @@
---
id: 5895f70df9fc0f352b528e68
title: Authentication Strategies
challengeType: 2
videoUrl: ''
localeTitle: 认证策略
---
## Description
<section id="description">提醒一下,这个项目是基于<a href="https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-advancednode/">Glitch</a>的以下入门项目构建的,或者是从<a href="https://github.com/freeCodeCamp/boilerplate-advancednode/">GitHub</a>克隆的。策略是一种验证用户的方法。您可以使用策略允许用户根据本地保存的信息如果您首先注册或从Google或Github等各种提供商进行身份验证。对于这个项目我们将制定一个本地战略。要查看的策略100的列表请访问网站护照<a href="http://passportjs.org/">这里</a> 。将<em>passport-local</em>添加为依赖项并将其添加到服务器,如下所示: <code>const LocalStrategy = require(&#39;passport-local&#39;);</code>现在,您必须告诉护照<b>使用</b>实例化的LocalStartegy对象并定义一些设置。确保这一点以及此时的所有内容都封装在数据库连接中因为它依赖于它 <pre> passport.use新的LocalStrategy
function用户名密码已完成{
db.collection&#39;users&#39;。findOne{usernameusername}functionerruser{
console.log&#39;用户&#39;+用户名+&#39;试图登录。&#39;;
iferr{return doneerr; }
ifuser{return donenullfalse; }
ifpassword== user.password{return donenullfalse; }
return donenulluser;
};
}
; </pre>这是我们尝试在本地验证某人时要采取的过程。首先它尝试使用输入的用户名在我们的数据库中查找用户然后检查要匹配的密码最后如果没有弹出我们检查过的错误如错误的密码则返回用户对象它们是认证。许多策略都是使用不同的设置设置的一般来说根据该策略库中的README很容易设置它。一个很好的例子是Github策略我们不需要担心用户名或密码因为用户将被发送到Github的auth页面进行身份验证只要他们登录并同意然后Github返回他们的个人资料我们用。在下一步中我们将设置如何实际调用身份验证策略以根据表单数据验证用户如果您认为自己已经完成了这一点请提交您的页面。 </section>
## Instructions
<section id="instructions">
</section>
## Tests
<section id='tests'>
```yml
tests:
- text: Passport-local是一种依赖
testString: getUserInput => $.get(getUserInput('url')+ '/_api/package.json') .then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'passport-local', 'Your project should list "passport-local " as a dependency'); }, xhr => { throw new Error(xhr.statusText); })
- text: Passport-local正确需要和设置
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /require.*("|')passport-local("|')/gi, 'You should have required passport-local'); assert.match(data, /new LocalStrategy/gi, 'You should have told passport to use a new strategy'); assert.match(data, /findOne/gi, 'Your new local strategy should use the findOne query to find a username based on the inputs'); }, xhr => { throw new Error(xhr.statusText); })
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

View File

@@ -0,0 +1,48 @@
---
id: 589fc831f9fc0f352b528e77
title: Authentication with Socket.IO
challengeType: 2
videoUrl: ''
localeTitle: 使用Socket.IO进行身份验证
---
## Description
<section id="description">提醒一下,这个项目是基于<a href="https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-socketio/">Glitch</a>的以下入门项目构建的,或者是从<a href="https://github.com/freeCodeCamp/boilerplate-socketio/">GitHub</a>克隆的。目前您无法确定谁连接到您的Web套接字。虽然&#39;req.user&#39;对用户对象进行了容器处理但只有当您的用户与Web服务器进行交互并且使用Web套接字时您才没有req请求因此没有用户数据。解决知道谁连接到您的Web套接字的问题的一种方法是解析和解码包含护照会话的cookie然后对其进行反序列化以获取用户对象。幸运的是NPM上有一个包只是为了将一次复杂的任务变成简单的事情 <hr>将“passport.socketio”添加为依赖项并将其命名为“passportSocketIo”。现在我们只需要告诉Socket.IO使用它并设置选项。确保在现有套接字代码之前添加它而不是在现有连接侦听器中添加。对于您的服务器它应如下所示 <pre> io.usepassportSocketIo.authorize{
cookieParsercookieParser
key&#39;express.sid&#39;
secretprocess.env.SESSION_SECRET
storesessionStore
}; </pre>您还可以选择将“成功”和“失败”与在客户端尝试连接时身份验证过程完成后调用的函数一起传递。现在可以在套接字对象上以<code>socket.request.user</code>访问用户对象。例如,现在您可以添加以下内容: <code>console.log(&#39;user &#39; + socket.request.user.name + &#39; connected&#39;);</code>它将登录已连接的服务器控制台!当您认为自己已经做对时,请提交您的页面。如果您遇到错误,可以<a href="https://gist.github.com/JosephLivengood/a9e69ff91337500d5171e29324e1ff35">在此处</a>查看项目。 </section>
## Instructions
<section id="instructions">
</section>
## Tests
<section id='tests'>
```yml
tests:
- text: passportSocketIo是一个依赖项
testString: getUserInput => $.get(getUserInput('url')+ '/_api/package.json') .then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'passport.socketio', 'Your project should list "passport.socketio" as a dependency'); }, xhr => { throw new Error(xhr.statusText); })
- text: passportSocketIo是正确需要的
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js').then(data => { assert.match(data, /require\((['"])passport\.socketio\1\)/gi, 'You should correctly require and instantiate "passport.socketio"');}, xhr => { throw new Error(xhr.statusText); })
- text: passportSocketIo已正确设置
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /io\.use\(.+\.authorize\(/gi, 'You should register "passport.socketio" as socket.io middleware and provide it correct options'); }, xhr => { throw new Error(xhr.statusText); })
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

View File

@@ -0,0 +1,40 @@
---
id: 589690e6f9fc0f352b528e6e
title: Clean Up Your Project with Modules
challengeType: 2
videoUrl: ''
localeTitle: 使用模块清理项目
---
## Description
<section id="description">提醒一下,这个项目是基于<a href="https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-advancednode/">Glitch</a>的以下入门项目构建的,或者是从<a href="https://github.com/freeCodeCamp/boilerplate-advancednode/">GitHub</a>克隆的。现在你拥有的一切都在你的server.js文件中。这可能导致难以管理不易扩展的代码。创建2个新文件Routes.js和Auth.js两者都应该从以下代码开始 <pre> module.exports = functionappdb{
<p> } </p></pre>现在位于服务器文件的顶部,需要这样的文件: <code>const routes = require(&#39;./routes.js&#39;);</code>在您与数据库建立成功连接之后,实例化它们中的每一个如下: <code>routes(app, db)</code>最后获取服务器中的所有路由并将它们粘贴到新文件中并从服务器文件中删除它们。也可以使用ensureAuthenticated因为我们专门为路由创建了中间件功能。您现在必须正确添加所使用的依赖项例如<code>const passport = require(&#39;passport&#39;);</code> 在routes.js文件中导出行的最上方。继续添加它们直到不再存在错误并且您的服务器文件不再有任何路由现在在auth.js文件中执行相同的操作其中包含与身份验证相关的所有内容例如序列化和本地策略的设置并从服务器文件中删除它们。确保添加依赖项并在同一位置调用服务器中的<code>auth(app,db)</code> 。确保<code>routes(app, db)</code> <code>auth(app, db)</code>之前有<code>auth(app, db)</code> <code>routes(app, db)</code>因为我们的注册路由取决于发起的护照!恭喜 - 您已经处于Advanced Node和Express的这一部分的末尾并且有一些漂亮的代码可供展示当您认为自己已经做对时请提交您的页面。如果您遇到错误可以<a href="https://glitch.com/#!/project/delicious-herring">在此处查看</a>已完成项目的示例。 <p></p></section>
## Instructions
<section id="instructions">
</section>
## Tests
<section id='tests'>
```yml
tests:
- text: 存在的模块
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /require\s*\(('|")\.\/routes(\.js)?\1\)/gi, 'You should have required your new files'); assert.match(data, /mongo.connect[^]*routes/gi, 'Your new modules should be called after your connection to the database'); }, xhr => { throw new Error(xhr.statusText); })
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

View File

@@ -0,0 +1,45 @@
---
id: 589fc831f9fc0f352b528e75
title: Communicate by Emitting
challengeType: 2
videoUrl: ''
localeTitle: 通过发射进行沟通
---
## Description
<section id="description">提醒一下,这个项目是基于<a href="https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-socketio/">Glitch</a>的以下入门项目构建的,或者是从<a href="https://github.com/freeCodeCamp/boilerplate-socketio/">GitHub</a>克隆的。 <dfn>Emit</dfn>是您将使用的最常见的沟通方式。当您从服务器向&#39;io&#39;发送内容时,会将事件的名称和数据发送到所有连接的套接字。这个概念的一个很好的例子就是每次新用户连接时都会发出连接用户的当前数量! <hr>首先添加一个变量,以便在您当前正在侦听连接之前跟踪用户。 <code>var currentUsers = 0;</code>现在当有人连接时,你应该在发出计数之前递增计数,这样你就可以在连接监听器中添加增量器。 <code>++currentUsers;</code>最后,在递增计数后,您应该发出事件(仍在连接侦听器中)。该事件应命名为“用户计数”,数据应该只是&#39;currentUsers&#39;<code>io.emit(&#39;user count&#39;, currentUsers);</code> <hr>现在,您可以为客户实施一种方式来监听此事件!与在服务器上侦听连接类似,您将使用<em>on</em>关键字。 <pre> socket.on&#39;user count&#39;functiondata{
的console.log数据;
}; </pre>现在尝试加载您的应用并进行身份验证您应该在客户端控制台中看到“1”代表当前用户数尝试加载更多客户端并进行身份验证以查看数量是否上升。当您认为自己已经做对时请提交您的页面。 </section>
## Instructions
<section id="instructions">
</section>
## Tests
<section id='tests'>
```yml
tests:
- text: currentUsers已定义
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js').then(data => {assert.match(data, /currentUsers/gi, 'You should have variable currentUsers defined');}, xhr => { throw new Error(xhr.statusText); })
- text: 服务器在每个新连接上发出当前用户计数
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /io.emit.*('|")user count('|").*currentUsers/gi, 'You should emit "user count" with data currentUsers'); }, xhr => { throw new Error(xhr.statusText); })
- text: 您的客户正在侦听“用户计数”事件
testString: getUserInput => $.get(getUserInput('url')+ '/public/client.js') .then(data => { assert.match(data, /socket.on.*('|")user count('|")/gi, 'Your client should be connection to server with the connection defined as socket'); }, xhr => { throw new Error(xhr.statusText); })
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

View File

@@ -0,0 +1,49 @@
---
id: 5895f70df9fc0f352b528e6a
title: Create New Middleware
challengeType: 2
videoUrl: ''
localeTitle: 创建新的中间件
---
## Description
<section id="description">提醒一下,这个项目是基于<a href="https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-advancednode/">Glitch</a>的以下入门项目构建的,或者是从<a href="https://github.com/freeCodeCamp/boilerplate-advancednode/">GitHub</a>克隆的。同样,任何用户都可以通过输入网址来查看/配置他们是否通过身份验证。我们希望通过在呈现配置文件页面之前检查用户是否首先进行身份验证来防止这种情况。这是何时创建中间件的完美示例。这里的挑战是创建中间件功能<code>ensureAuthenticated(req, res, next)</code> 它将检查用户是否通过调用护照进行身份验证isAuthenticated对<em>请求</em>进行检查,然后检查<em>req.user</em>是否定义。如果是,那么应该调用<em>next</em> ,否则我们只需通过重定向到我们的主页来回复请求即可登录。该中间件的实现是: <pre> function ensureAuthenticatedreqresnext{
ifreq.isAuthenticated{
return next;
}
res.redirect &#39;/&#39;;
}; </pre>现在在包含呈现页面的函数的get请求的参数之前<em>ensureAuthenticated</em>作为中间件添加到配置文件页面的请求中。 <pre> app.route &#39;/简档&#39;
.getensureAuthenticatedreqres=&gt; {
res.renderprocess.cwd+&#39;/ views / pug / profile&#39;;
}; </pre>当您认为自己已经做对时,请提交您的页面。 </section>
## Instructions
<section id="instructions">
</section>
## Tests
<section id='tests'>
```yml
tests:
- text: 中间件确保应该在我们的/配置文件路由上实现
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /ensureAuthenticated[^]*req.isAuthenticated/gi, 'Your ensureAuthenticated middleware should be defined and utilize the req.isAuthenticated function'); assert.match(data, /profile[^]*get[^]*ensureAuthenticated/gi, 'Your ensureAuthenticated middleware should be attached to the /profile route'); }, xhr => { throw new Error(xhr.statusText); })
- text: 正确的Get请求/配置文件重定向到/因为我们未经过身份验证
testString: getUserInput => $.get(getUserInput('url')+ '/profile') .then(data => { assert.match(data, /Home page/gi, 'An attempt to go to the profile at this point should redirect to the homepage since we are not logged in'); }, xhr => { throw new Error(xhr.statusText); })
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

View File

@@ -0,0 +1,41 @@
---
id: 589fc831f9fc0f352b528e76
title: Handle a Disconnect
challengeType: 2
videoUrl: ''
localeTitle: 处理断开连接
---
## Description
<section id="description">提醒一下,这个项目是基于<a href="https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-socketio/">Glitch</a>的以下入门项目构建的,或者是从<a href="https://github.com/freeCodeCamp/boilerplate-socketio/">GitHub</a>克隆的。您可能会注意到,到目前为止,您只增加了用户数。处理用户断开连接就像处理初始连接一样简单,除了区别在于你必须在每个套接字上监听它而不是在整个服务器上监听它。 <hr>为此请在现有的连接侦听器中添加一个侦听器该侦听器在没有数据传递的情况下侦听套接字上的“disconnect”。您只需登录用户已断开连接的控制台即可测试此功能。 <code>socket.on(&#39;disconnect&#39;, () =&gt; { /*anything you want to do on disconnect*/ });</code>要确保客户端持续获得当前用户的更新计数您应该在断开连接时将currentUsers减少1然后使用更新的计数发出&#39;user count&#39;事件! <strong>注意</strong> <br>就像&#39;disconnect&#39;一样,套接字可以向服务器发出的所有其他事件应该在我们定义了&#39;socket&#39;的连接监听器中处理。当您认为自己已经做对时,请提交您的页面。 </section>
## Instructions
<section id="instructions">
</section>
## Tests
<section id='tests'>
```yml
tests:
- text: 服务器处理与套接字的事件断开连接
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /socket.on.*('|")disconnect('|")/gi, ''); }, xhr => { throw new Error(xhr.statusText); })
- text: 您的客户正在侦听“用户计数”事件
testString: getUserInput => $.get(getUserInput('url')+ '/public/client.js') .then(data => { assert.match(data, /socket.on.*('|")user count('|")/gi, 'Your client should be connection to server with the connection defined as socket'); }, xhr => { throw new Error(xhr.statusText); })
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

View File

@@ -0,0 +1,41 @@
---
id: 58a25c98f9fc0f352b528e7f
title: Hashing Your Passwords
challengeType: 2
videoUrl: ''
localeTitle: 哈希密码
---
## Description
<section id="description">提醒一下,这个项目是基于<a href="https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-advancednode/">Glitch</a>的以下入门项目构建的,或者是从<a href="https://github.com/freeCodeCamp/boilerplate-advancednode/">GitHub</a>克隆的。回到信息安全部分,您​​可能还记得存储明文密码<em>永远不会</em>好。现在是时候实施BCrypt来解决这个问题了。 <hr>将BCrypt添加为依赖项并在服务器中将其需要。您需要在两个关键区域处理散列您在哪里处理注册/保存新帐户以及在登录时检查密码是否正确。目前在我们的注册路线上,您将用户的密码插入数据库,如下所示: <code>password: req.body.password</code> 。实现保存哈希的一种简单方法是在数据库逻辑<code>var hash = bcrypt.hashSync(req.body.password, 12);</code>之前添加以下内容<code>var hash = bcrypt.hashSync(req.body.password, 12);</code>并使用<code>password: hash</code>替换数据库保存中的<code>req.body.password</code> 。最后在我们的身份验证策略中,我们在完成流程之前在代码中检查以下内容: <code>if (password !== user.password) { return done(null, false); }</code> 。完成之前的更改后,现在<code>user.password</code>是一个哈希。在更改现有代码之前,请注意语句如何检查密码是否不相等,然后返回未经过身份验证的密码。考虑到这一点,您的代码可能如下所示,以正确检查针对哈希输入的密码: <code>if (!bcrypt.compareSync(password, user.password)) { return done(null, false); }</code>这是所有需要实现的最重要的安全功能之一,当你有来存储密码!当您认为自己已经做对时,请提交您的页面。 </section>
## Instructions
<section id="instructions">
</section>
## Tests
<section id='tests'>
```yml
tests:
- text: BCrypt是一种依赖
testString: getUserInput => $.get(getUserInput('url')+ '/_api/package.json') .then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'bcrypt', 'Your project should list "bcrypt" as a dependency'); }, xhr => { throw new Error(xhr.statusText); })
- text: BCrypt正确需要并实施
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /require.*("|')bcrypt("|')/gi, 'You should have required bcrypt'); assert.match(data, /bcrypt.hashSync/gi, 'You should use hash the password in the registration'); assert.match(data, /bcrypt.compareSync/gi, 'You should compare the password to the hash in your strategy'); }, xhr => { throw new Error(xhr.statusText); })
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

View File

@@ -0,0 +1,39 @@
---
id: 5895f70ef9fc0f352b528e6b
title: How to Put a Profile Together
challengeType: 2
videoUrl: ''
localeTitle: 如何将配置文件放在一起
---
## Description
<section id="description">提醒一下,这个项目是基于<a href="https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-advancednode/">Glitch</a>的以下入门项目构建的,或者是从<a href="https://github.com/freeCodeCamp/boilerplate-advancednode/">GitHub</a>克隆的。现在我们可以确保访问<em>/ profile</em>的用户已经过身份验证我们可以使用页面上“req.user”中包含的信息继续将包含变量<em>username</em> equaling&#39;req.user.username&#39;的对象传递到配置文件视图的render方法中。然后转到你的&#39;profile.pug&#39;视图并添加第<code>h2.center#welcome Welcome, #{username}!</code><code>h2.center#welcome Welcome, #{username}!</code>使用“center”类创建h2元素并使用包含文本“Welcome”和用户名的id“welcome”创建同样在配置文件中添加指向<em>/ logout</em>的链接。该路由将托管用于取消身份验证用户的逻辑。 <code>a(href=&#39;/logout&#39;) Logout</code>当您认为自己正确时,请提交您的页面。 </section>
## Instructions
<section id="instructions">
</section>
## Tests
<section id='tests'>
```yml
tests:
- text: 正确地将Pug渲染变量添加到/ profile
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /\/views\/pug\/profile[^]*username:( |)req.user.username/gi, 'You should be passing the variable username with req.user.username into the render function of the profile page'); }, xhr => { throw new Error(xhr.statusText); })
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

View File

@@ -0,0 +1,41 @@
---
id: 5895f70df9fc0f352b528e69
title: How to Use Passport Strategies
challengeType: 2
videoUrl: ''
localeTitle: 如何使用Passport策略
---
## Description
<section id="description">提醒一下,这个项目是基于<a href="https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-advancednode/">Glitch</a>的以下入门项目构建的,或者是从<a href="https://github.com/freeCodeCamp/boilerplate-advancednode/">GitHub</a>克隆的。在提供的index.pug文件中实际上有一个登录表单。它之前已被隐藏因为内联javascript <code>if showLogin</code>的形式缩进后。在showLogin作为变量从未定义之前它从未呈现包含该表单的代码块。继续在该页面的res.render上向对象<code>showLogin: true</code>添加一个新变量。刷新页面时,您应该看到表单!此表单设置为<b>POST</b> on <em>/ login</em>因此我们应该设置此接受POST并验证用户身份。对于此挑战您应添加路由/登录以接受POST请求。要在此路由上进行身份验证您需要添加中间件才能发送响应。这是通过在您的<code>function(req,res)</code>之前使用中间件传递另一个参数来完成的!要使用的中间件是<code>passport.authenticate(&#39;local&#39;)</code><em>passport.authenticate</em>也可以将一些选项作为参数,例如: <code>{ failureRedirect: &#39;/&#39; }</code>这非常有用,所以一定要添加它。作为使用中间件后的响应(只有在身份验证中间件通过时才会调用)应该是将用户重定向到<em>/ profile</em>并且该路由应该呈现视图&#39;profile.pug&#39;。如果身份验证成功,则用户对象将保存在<em>req.user中</em> 。现在,如果您在表单中输入用户名和密码,它应该重定向到主页<em>/</em>并且在服务器的控制台中应该是&#39;用户{USERNAME}尝试登录&#39;。因为我们目前无法登录未注册的用户。当您认为自己已经做对时,请提交您的页面。如果您遇到错误,可以<a href="https://gist.github.com/JosephLivengood/8a335d1a68ed9170da02bb9d8f5b71d5">在这里查看</a>到目前为止完成的项目。 </section>
## Instructions
<section id="instructions">
</section>
## Tests
<section id='tests'>
```yml
tests:
- text: 所有步骤都在server.js中正确实现
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /showLogin:( |)true/gi, 'You should be passing the variable "showLogin" as true to your render function for the homepage'); assert.match(data, /failureRedirect:( |)('|")\/('|")/gi, 'Your code should include a failureRedirect to the "/" route'); assert.match(data, /login[^]*post[^]*local/gi, 'You should have a route for login which accepts a POST and passport.authenticates local'); }, xhr => { throw new Error(xhr.statusText); })
- text: 对/ login的POST请求正确重定向到/
testString: getUserInput => $.post(getUserInput('url')+ '/login') .then(data => { assert.match(data, /Looks like this page is being rendered from Pug into HTML!/gi, 'A login attempt at this point should redirect to the homepage since we do not have any registered users'); }, xhr => { throw new Error(xhr.statusText); })
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

View File

@@ -0,0 +1,47 @@
---
id: 5895f70cf9fc0f352b528e67
title: Implement the Serialization of a Passport User
challengeType: 2
videoUrl: ''
localeTitle: 实现Passport用户的序列化
---
## Description
<section id="description">提醒一下,这个项目是基于<a href="https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-advancednode/">Glitch</a>的以下入门项目构建的,或者是从<a href="https://github.com/freeCodeCamp/boilerplate-advancednode/">GitHub</a>克隆的。现在我们没有加载实际的用户对象因为我们还没有设置我们的数据库。这可以通过许多不同的方式完成但是对于我们的项目当我们启动服务器并在应用程序的整个生命周期中保持持久连接时我们将连接到数据库。为此请将MongoDB添加为依赖项并在服务器中将其需要。 <code>const mongo = require(&#39;mongodb&#39;).MongoClient;</code> )现在我们想要连接到我们的数据库,然后开始侦听请求。这样做的目的是在连接数据库之前或者出现数据库错误时不允许请求。要实现此目的,您需要在以下内容中包含序列化和应用程序侦听器: <pre> mongo.connectprocess.env.DATABASEerrdb=&gt; {
if错误{
console.log&#39;数据库错误:&#39;+错误);
} else {
console.log&#39;成功的数据库连接&#39;;
<pre> <code> //serialization and app.listen</code> </pre>
<p> }}; </p></pre>您现在可以在deserializeUser中取消注释该块并删除您的<code>done(null, null)</code> 。确保将.env文件中的<em>DATABASE</em>设置为数据库的连接字符串(例如: <code>DATABASE=mongodb://admin:pass@mlab.com:12345/my-project</code> )。您可以在<a href="https://mlab.com/welcome/">mLab</a>上设置免费数据库。恭喜 - 您已完成序列化设置!当您认为自己已经做对时,请提交您的页面。如果您遇到错误,可以<a href="https://gist.github.com/JosephLivengood/e192e809a1d27cb80dc2c6d3467b7477">在这里查看</a>到目前为止完成的项目。 <p></p></section>
## Instructions
<section id="instructions">
</section>
## Tests
<section id='tests'>
```yml
tests:
- text: 存在数据库连接
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /mongo.connect/gi, 'You should have created a connection to your database'); assert.match(data, /mongo.connect[^]*app.listen[^]*}[^]*}/gi, 'You should have your app.listen nested at within your database connection at the bottom'); }, xhr => { throw new Error(xhr.statusText); })
- text: 反序列化现在正确使用DB并且擦除了<code>done(null, null)</code>
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.notMatch(data, /null,( |)null/gi, 'The callback in deserializeUser of (null, null) should be completely removed for the db block uncommented out'); }, xhr => { throw new Error(xhr.statusText); })
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

View File

@@ -0,0 +1,52 @@
---
id: 589a69f5f9fc0f352b528e71
title: Implementation of Social Authentication II
challengeType: 2
videoUrl: ''
localeTitle: 社会认证的实施II
---
## Description
<section id="description">提醒一下,这个项目是基于<a href="https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-socialauth/">Glitch</a>的以下入门项目构建的,或者是从<a href="https://github.com/freeCodeCamp/boilerplate-socialauth/">GitHub</a>克隆的。设置Github身份验证的最后一部分是创建策略本身。为此您需要将&#39;passport-github&#39;的依赖项添加到项目中并将其作为GithubStrategy例如<code>const GitHubStrategy = require(&#39;passport-github&#39;).Strategy;</code> 。要设置Github策略你必须告诉<b>护照</b> <b>使用</b>实例化的<b>GithubStrategy</b> 它接受2个参数一个对象包含<em>clientID</em> <em>clientSecret</em><em>callbackURL</em> 和一个在成功验证用户时要调用的函数我们将确定如果用户是新用户以及最初要保存在用户数据库对象中的字段。这在许多策略中很常见但有些可能需要更多信息如特定策略的github README所述;例如Google也需要一个<em>范围</em>来确定您的请求所返回的信息类型,并要求用户批准此类访问。我们正在实施的当前策略<a>在此处</a>列出<a></a>它的用法但我们将在freeCodeCamp上完成所有这些工作以下是您的新战略应该如何看待这一点 <pre> passport.usenew GitHubStrategy{
clientIDprocess.env.GITHUB_CLIENT_ID
clientSecretprocess.env.GITHUB_CLIENT_SECRET
callbackURL/ * INSERT CALLBACK URL在这里输入GITHUB * /
}
functionaccessTokenrefreshTokenprofilecb{
的console.log配置文件;
//这里的数据库逻辑带有包含我们用户对象的回调
}
; </pre>您的身份验证还不会成功并且实际上会抛出错误没有数据库逻辑和回调但如果您尝试它它应该将您的Github配置文件记录到您的控制台当您认为自己已经做对时请提交您的页面。 </section>
## Instructions
<section id="instructions">
</section>
## Tests
<section id='tests'>
```yml
tests:
- text: 依赖性增加了
testString: getUserInput => $.get(getUserInput('url')+ '/_api/package.json') .then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'passport-github', 'Your project should list "passport-github" as a dependency'); }, xhr => { throw new Error(xhr.statusText); })
- text: 需要依赖性
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /require.*("|')passport-github("|')/gi, 'You should have required passport-github'); }, xhr => { throw new Error(xhr.statusText); })
- text: 到目前为止Github策略设置正确
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /passport.use.*new GitHubStrategy/gi, 'Passport should use a new GitHubStrategy'); assert.match(data, /callbackURL:( |)("|').*("|')/gi, 'You should have a callbackURL'); assert.match(data, /process.env.GITHUB_CLIENT_SECRET/g, 'You should use process.env.GITHUB_CLIENT_SECRET'); assert.match(data, /process.env.GITHUB_CLIENT_ID/g, 'You should use process.env.GITHUB_CLIENT_ID'); }, xhr => { throw new Error(xhr.statusText); })
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

View File

@@ -0,0 +1,58 @@
---
id: 589a8eb3f9fc0f352b528e72
title: Implementation of Social Authentication III
challengeType: 2
videoUrl: ''
localeTitle: 社会认证的实施III
---
## Description
<section id="description">提醒一下,这个项目是基于<a href="https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-socialauth/">Glitch</a>的以下入门项目构建的,或者是从<a href="https://github.com/freeCodeCamp/boilerplate-socialauth/">GitHub</a>克隆的。策略的最后一部分是处理从Github返回的配置文件。我们需要加载用户数据库对象如果存在或创建一个如果不存在并填充配置文件中的字段然后返回用户的对象。 Github在每个配置文件中为我们提供了一个唯一的<em>ID</em> ,我们可以使用它来搜索(已经实现)用户序列化。下面是您可以在项目中使用的示例实现 - 它位于作为新策略的第二个参数的函数内,就在<code>console.log(profile);</code>目前是: <pre> db.collection &#39;socialusers&#39;。findAndModify
{idprofile.id}
{}
{$ setOnInsert{
idprofile.id
nameprofile.displayName || &#39;John Doe&#39;
照片profile.photos [0] .value || ”
电子邮件profile.emails [0] .value || &#39;没有公开电子邮件&#39;
created_onnew Date
providerprofile.provider || “
} $设置:{
last_login新日期
} $ INC {
login_count1
}}
{upserttruenewtrue}
错误doc=&gt; {
return cbnulldoc.value;
}
; </pre>使用findAndModify它允许您搜索对象并对其进行更新如果对象不存在则将其置换并在每次回调函数中接收新对象。在这个例子中我们总是将last_login设置为now我们总是将login_count增加1并且只有当我们插入一个新对象新用户我们才会填充大部分字段。需要注意的是使用默认值。有时返回的个人资料不会填写所有信息或者用户会选择保留私密信息;所以在这种情况下我们必须处理它以防止错误。你现在应该可以登录你的应用了 - 试试吧!当您认为自己已经做对时,请提交您的页面。如果你正在运行到错误,您可以检查出的这个小项目的完成代码的例子<a href="https://glitch.com/#!/project/guttural-birch">在这里</a></section>
## Instructions
<section id="instructions">
</section>
## Tests
<section id='tests'>
```yml
tests:
- text: Github策略设置完成
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /GitHubStrategy[^]*db.collection/gi, 'Strategy should use now use the database to search for the user'); assert.match(data, /GitHubStrategy[^]*socialusers/gi, 'Strategy should use "socialusers" as db collection'); assert.match(data, /GitHubStrategy[^]*return cb/gi, 'Strategy should return the callback function "cb"'); }, xhr => { throw new Error(xhr.statusText); })
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

View File

@@ -0,0 +1,44 @@
---
id: 589a69f5f9fc0f352b528e70
title: Implementation of Social Authentication
challengeType: 2
videoUrl: ''
localeTitle: 社会认证的实施
---
## Description
<section id="description">提醒一下,这个项目是基于<a href="https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-socialauth/">Glitch</a>的以下入门项目构建的,或者是从<a href="https://github.com/freeCodeCamp/boilerplate-socialauth/">GitHub</a>克隆的。此类身份验证在您的应用中遵循的基本路径是: <ol><li>用户单击按钮或链接将它们发送到我们使用特定策略进行身份验证的路由EG.GitHub </li><li>您的路由呼叫<code>passport.authenticate(&#39;github&#39;)</code> 将其重定向到Github。 </li><li>用户登陆的页面在Github上允许他们登录如果他们还没有。然后它要求他们批准从我们的应用程序访问他们的个人资料。 </li><li>然后,如果用户获得批准,则会使用他们的个人资料将该用户返回到我们的应用。 </li><li>它们现在已经过身份验证,您的应用应检查它是否为返回的配置文件,如果不是,则将其保存在数据库中。 </li></ol> OAuth策略要求您至少拥有<em>客户端ID</em><em>客户端密钥</em> 以便他们验证身份验证请求的来源以及是否有效。这些是从您尝试使用Github实现身份验证的站点获得的并且对您的应用程序是唯一的 - 它们不会被<b>共享</b> ,不应该上传到公共存储库或直接在您的代码中编写。通常的做法是将它们放在<em>.env</em>文件中并引用它们: <code>process.env.GITHUB_CLIENT_ID</code> 。对于这个挑战我们将使用Github策略。 <em><em>从Github</em></em>获取您的<em>客户ID和密码<em>是在“开发者设置”下的帐户配置文件设置中完成的,然后是“ <a href="https://github.com/settings/developers">OAuth应用程序</a> ”。点击“注册一个新的应用程序”,为您的应用命名,将网址粘贴到您的故障主页( <b>不是项目代码的网址</b> ),最后为回调网址,粘贴到与主页相同的网址,但使用&#39;/ auth / github / callback&#39;已添加。这是用户将被重定向到我们在Github上进行身份验证后处理的地方。将返回的信息保存为.env文件中的“GITHUB_CLIENT_ID”和“GITHUB_CLIENT_SECRET”。在重新混合的项目中创建2条接受GET请求的路由/ auth / github和/ auth / github / callback。第一个应该只调用护照来验证&#39;github&#39;,第二个应该调用护照来验证&#39;github&#39;,失败重定向到&#39;/&#39;然后如果成功重定向到&#39;/ profile&#39;(类似于我们的上一个项目)。 &#39;/ auth / github / callback&#39;应该如何看待的示例与我们在上一个项目中处理正常登录的方式类似:</em></em> <pre> <em><em>app.route &#39;/登录&#39;
.postpassport.authenticate&#39;local&#39;{failureRedirect&#39;/&#39;}reqres=&gt; {
res.redirect &#39;/简档&#39;;
};</em></em> </pre> <em><em>当您认为自己已经做对时,请提交您的页面。如果您遇到错误,可以<a href="https://gist.github.com/JosephLivengood/28ea2cae7e1dc6a53d7f0c42d987313b">在此处</a>查看项目。</em></em> </section>
## Instructions
<section id="instructions">
</section>
## Tests
<section id='tests'>
```yml
tests:
- text: Route / auth / github正确
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /('|")\/auth\/github('|")[^]*get.*passport.authenticate.*github/gi, 'Route auth/github should only call passport.authenticate with github'); }, xhr => { throw new Error(xhr.statusText); })
- text: Route / auth / github /回调正确
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /('|")\/auth\/github\/callback('|")[^]*get.*passport.authenticate.*github.*failureRedirect:( |)("|')\/("|')/gi, 'Route auth/github/callback should accept a get request and call passport.authenticate for github with a failure redirect to home'); }, xhr => { throw new Error(xhr.statusText); })
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

View File

@@ -0,0 +1,49 @@
---
id: 58965611f9fc0f352b528e6c
title: Logging a User Out
challengeType: 2
videoUrl: ''
localeTitle: 记录用户
---
## Description
<section id="description">提醒一下,这个项目是基于<a href="https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-advancednode/">Glitch</a>的以下入门项目构建的,或者是从<a href="https://github.com/freeCodeCamp/boilerplate-advancednode/">GitHub</a>克隆的。创建注销逻辑很容易。路径应该只是取消认证用户并重定向到主页而不是渲染任何视图。在护照中, <code>req.logout();</code>认证用户就像调用<code>req.logout();</code>一样简单<code>req.logout();</code>在重定向之前。 <pre> app.route &#39;/注销&#39;
.getreqres=&gt; {
req.logout;
res.redirect &#39;/&#39;;
}; </pre>您可能已经注意到我们也没有处理丢失的页面404在Node中处理此问题的常用方法是使用以下中间件。继续在所有其他路线之后添加 <pre> app.usereqresnext=&gt; {
res.status404
.TYPE &#39;文本&#39;
.send&#39;未找到&#39;;
}; </pre>当您认为自己已经做对时,请提交您的页面。 </section>
## Instructions
<section id="instructions">
</section>
## Tests
<section id='tests'>
```yml
tests:
- text: 退出路线
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /req.logout/gi, 'You should be calling req.logout() in your /logout route'); }, xhr => { throw new Error(xhr.statusText); })
- text: 注销应该重定向到主页/
testString: getUserInput => $.get(getUserInput('url')+ '/logout') .then(data => { assert.match(data, /Home page/gi, 'When a user logs out they should be redirected to the homepage'); }, xhr => { throw new Error(xhr.statusText); })
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

View File

@@ -0,0 +1,72 @@
---
id: 58966a17f9fc0f352b528e6d
title: Registration of New Users
challengeType: 2
videoUrl: ''
localeTitle: 新用户注册
---
## Description
<section id="description">提醒一下,这个项目是基于<a href="https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-advancednode/">Glitch</a>的以下入门项目构建的,或者是从<a href="https://github.com/freeCodeCamp/boilerplate-advancednode/">GitHub</a>克隆的。现在我们需要允许我们网站上的新用户注册一个帐户。在主页的res.render上向传递的对象添加一个新变量 - <code>showRegistration: true</code> 。刷新页面时您应该会看到已在index.pug文件中创建的注册表单此表单设置为<b>POST</b> on <em>/ register</em>因此我们应该设置此接受POST并在数据库中创建用户对象。注册路由的逻辑应如下所示注册新用户&gt;验证新用户&gt;重定向到/配置文件步骤1的逻辑注册新用户应如下所示使用findOne命令查询数据库&gt;如果用户返回然后它存在并重定向回到主页<em>或者</em>如果用户未定义且没有发生错误则使用用户名和密码将“insertOne”输入数据库只要没有错误发生然后调用<em>next</em>转到步骤2验证新的user我们已经在POST / login路由中编写了逻辑。 <pre> app.route &#39;/寄存器&#39;
.postreqresnext=&gt; {
db.collection&#39;users&#39;。findOne{usernamereq.body.username}functionerruser{
if错误{
下一个ERR;
} else ifuser{
res.redirect &#39;/&#39;;
} else {
db.collection &#39;用户&#39;。insertOne
{usernamereq.body.username
密码req.body.password}
错误doc=&gt; {
if错误{
res.redirect &#39;/&#39;;
} else {
nextnulluser;
}
}
}
}}
passport.authenticate&#39;local&#39;{failureRedirect&#39;/&#39;}
reqresnext=&gt; {
res.redirect &#39;/简档&#39;;
}
; </pre>当您认为自己已经做对时,请提交您的页面。如果您遇到错误,可以<a href="https://gist.github.com/JosephLivengood/6c47bee7df34df9f11820803608071ed">在这里查看</a>到目前为止完成的项目。 </section>
## Instructions
<section id="instructions">
</section>
## Tests
<section id='tests'>
```yml
tests:
- text: 注册路线并在家中显示
testString: 'getUserInput => $.get(getUserInput(''url'')+ ''/_api/server.js'') .then(data => { assert.match(data, /showRegistration:( |)true/gi, ''You should be passing the variable "showRegistration" as true to your render function for the homepage''); assert.match(data, /register[^]*post[^]*findOne[^]*username:( |)req.body.username/gi, ''You should have a route accepted a post request on register that querys the db with findone and the query being "username: req.body.username"''); }, xhr => { throw new Error(xhr.statusText); })'
- text: 注册应该工作
testString: 'getUserInput => $.ajax({url: getUserInput(''url'')+ ''/register'',data: {username: ''freeCodeCampTester'', password: ''freeCodeCampTester''},crossDomain: true, type: ''POST'', xhrFields: { withCredentials: true }}) .then(data => { assert.match(data, /Profile/gi, ''I should be able to register and it direct me to my profile. CLEAR YOUR DATABASE if this test fails (each time until its right!)''); }, xhr => { throw new Error(xhr.statusText); })'
- text: 登录应该工作
testString: 'getUserInput => $.ajax({url: getUserInput(''url'')+ ''/login'',data: {username: ''freeCodeCampTester'', password: ''freeCodeCampTester''}, type: ''POST'', xhrFields: { withCredentials: true }}) .then(data => { assert.match(data, /Profile/gi, ''Login should work if previous test was done successfully and redirect successfully to the profile. Check your work and clear your DB''); assert.match(data, /freeCodeCampTester/gi, ''The profile should properly display the welcome to the user logged in''); }, xhr => { throw new Error(xhr.statusText); })'
- text: 注销应该有效
testString: 'getUserInput => $.ajax({url: getUserInput(''url'')+ ''/logout'', type: ''GET'', xhrFields: { withCredentials: true }}) .then(data => { assert.match(data, /Home/gi, ''Logout should redirect to home''); }, xhr => { throw new Error(xhr.statusText); })'
- text: 注销后配置文件不再有效
testString: 'getUserInput => $.ajax({url: getUserInput(''url'')+ ''/profile'', type: ''GET'', crossDomain: true, xhrFields: { withCredentials: true }}) .then(data => { assert.match(data, /Home/gi, ''Profile should redirect to home when we are logged out now again''); }, xhr => { throw new Error(xhr.statusText); })'
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

View File

@@ -0,0 +1,41 @@
---
id: 589fc832f9fc0f352b528e79
title: Send and Display Chat Messages
challengeType: 2
videoUrl: ''
localeTitle: 发送和显示聊天消息
---
## Description
<section id="description">提醒一下,这个项目是基于<a href="https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-socketio/">Glitch</a>的以下入门项目构建的,或者是从<a href="https://github.com/freeCodeCamp/boilerplate-socketio/">GitHub</a>克隆的。是时候开始允许客户端向服务器发送聊天消息以向所有客户端发送消息已经在您的client.js文件中您应该看到在提交messgae表单时已经存在一段代码处理 <code>$(&#39;form&#39;).submit(function(){ /*logic*/ });</code> <hr>在您处理表单提交的代码中您应该在定义“messageToSend”之后但在清除文本框<code>#m</code>之前发出事件。该事件应命名为“聊天消息”数据应为“messageToSend”。 <code>socket.emit(&#39;chat message&#39;, messageToSend);</code>现在在您的服务器上您应该收听事件“聊天消息”的套接字并将数据命名为“message”。一旦接收到事件应该然后发射所述事件“聊天消息”到所有插座<code>io.emit</code>与数据为含“名称”和“报文”的对象。现在再次在您的客户端上,您现在应该监听事件“聊天消息”,并在收到时,将一个列表项追加到<code>#messages</code> ,其名称为冒号和消息!此时聊天功能齐全,并在所有客户端发送消息!当您认为自己已经做对时,请提交您的页面。如果您遇到错误,可以<a href="https://gist.github.com/JosephLivengood/3e4b7750f6cd42feaa2768458d682136">在此处</a>检查项目到此时<a href="https://gist.github.com/JosephLivengood/3e4b7750f6cd42feaa2768458d682136">为服务器</a><a href="https://gist.github.com/JosephLivengood/41ba76348df3013b7870dc64861de744">客户端</a></section>
## Instructions
<section id="instructions">
</section>
## Tests
<section id='tests'>
```yml
tests:
- text: 服务器侦听“聊天消息”,然后正确发出
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /socket.on.*('|")chat message('|")[^]*io.emit.*('|")chat message('|").*name.*message/gi, 'Your server should listen to the socket for "chat message" then emit to all users "chat message" with name and message in the data object'); }, xhr => { throw new Error(xhr.statusText); })
- text: 客户端正确处理和显示事件“聊天消息”中的新数据
testString: "getUserInput => $.get(getUserInput('url')+ '/public/client.js') .then(data => { assert.match(data, /socket.on.*('|\")chat message('|\")[^]*messages.*li/gi, 'You should append a list item to #messages on your client within the \"chat message\" event listener to display the new message'); }, xhr => { throw new Error(xhr.statusText); })"
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

View File

@@ -0,0 +1,54 @@
---
id: 5895f70cf9fc0f352b528e66
title: Serialization of a User Object
challengeType: 2
videoUrl: ''
localeTitle: 用户对象的序列化
---
## Description
<section id="description">提醒一下,这个项目是基于<a href="https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-advancednode/">Glitch</a>的以下入门项目构建的,或者是从<a href="https://github.com/freeCodeCamp/boilerplate-advancednode/">GitHub</a>克隆的。序列化和反序列化是身份验证方面的重要概念。序列化对象意味着将其内容转换为一个小<em>键,</em>基本上可以将其反序列化为原始对象。这使我们能够知道与服务器通信的人,而无需在每次请求新页面时发送用户名和密码等身份验证数据。要正确设置它,我们需要一个序列化函数和一个反序列化函数。在护照中,我们使用<code>passport.serializeUser( OURFUNCTION )</code><code>passport.deserializeUser( OURFUNCTION )</code>创建它们。使用2个参数调用serializeUser完整的用户对象和护照使用的回调。在回调中返回应该是唯一的键来标识该用户 - 最容易使用的用户是对象中的用户_id因为它应该是MongoDb生成的唯一用户。类似地使用该密钥和护照的回调函数调用deserializeUser但这次我们必须获取该密钥并将用户完整对象返回到回调。要进行查询搜索Mongo _id您必须创建<code>const ObjectID = require(&#39;mongodb&#39;).ObjectID;</code> ,然后使用它调用<code>new ObjectID(THE_ID)</code> 。一定要将MongoDB添加为依赖项。您可以在以下示例中看到 <pre> passport.serializeUseruserdone=&gt; {
donenulluser._id;
}; </pre><br><pre> passport.deserializeUseriddone=&gt; {
db.collection &#39;用户&#39;。findOne
{_idnew ObjectIDid}
错误doc=&gt; {
完成nulldoc;
}
;
}; </pre>注意这个deserializeUser将抛出一个错误直到我们在下一步中设置数据库因此注释掉整个块并在函数deserializeUser中调用<code>done(null, null)</code> 。当您认为自己已经做对时,请提交您的页面。 </section>
## Instructions
<section id="instructions">
</section>
## Tests
<section id='tests'>
```yml
tests:
- text: 序列化用户功能正确
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /passport.serializeUser/gi, 'You should have created your passport.serializeUser function'); assert.match(data, /null, user._id/gi, 'There should be a callback in your serializeUser with (null, user._id)'); }, xhr => { throw new Error(xhr.statusText); })
- text: 反序列化用户功能正确
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /passport.deserializeUser/gi, 'You should have created your passport.deserializeUser function'); assert.match(data, /null,( |)null/gi, 'There should be a callback in your deserializeUser with (null, null) for now'); }, xhr => { throw new Error(xhr.statusText); })
- text: MongoDB是一个依赖项
testString: getUserInput => $.get(getUserInput('url')+ '/_api/package.json') .then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'mongodb', 'Your project should list "mongodb" as a dependency'); }, xhr => { throw new Error(xhr.statusText); })
- text: Mongodb正确要求包括ObjectId
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /require.*("|')mongodb("|')/gi, 'You should have required mongodb'); assert.match(data, /new ObjectID.*id/gi, 'Even though the block is commented out, you should use new ObjectID(id) for when we add the database'); }, xhr => { throw new Error(xhr.statusText); })
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

View File

@@ -0,0 +1,43 @@
---
id: 5895f700f9fc0f352b528e63
title: Set up a Template Engine
challengeType: 2
videoUrl: ''
localeTitle: 设置模板引擎
---
## Description
<section id="description">提醒一下,这个项目是基于<a href="https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-advancednode/">Glitch</a>的以下入门项目构建的,或者是从<a href="https://github.com/freeCodeCamp/boilerplate-advancednode/">GitHub</a>克隆的。模板引擎使您可以在应用程序中使用静态模板文件(例如用<em>Pug</em>编写的文件。在运行时模板引擎将模板文件中的变量替换为可由服务器提供的实际值并将模板转换为静态HTML文件然后将其发送到客户端。这种方法可以更轻松地设计HTML页面并允许在页面上显示变量而无需从客户端进行API调用。要设置<em>Pug</em>以便在项目中使用您需要先在package.json中将其作为依赖项添加。 <code>&quot;pug&quot;: &quot;^0.1.0&quot;</code>现在告诉Node / Express使用模板引擎你必须告诉你的快递<b>应用程序</b> <b></b> &#39;pug&#39; <b>设置</b>&#39;view-engine&#39;<code>app.set(&#39;view engine&#39;, &#39;pug&#39;)</code>最后,你应该改变请求您响应该指数路线<code>res.render</code>与路径视图<em>意见/哈巴狗/ index.pug。</em>如果一切按计划进行您应该刷新应用程序主页并看到一条小消息说您已成功从我们的Pug文件中删除Pug当您认为自己已经做对时请提交您的页面。 </section>
## Instructions
<section id="instructions">
</section>
## Tests
<section id='tests'>
```yml
tests:
- text: 帕格是一个依赖
testString: getUserInput => $.get(getUserInput('url')+ '/_api/package.json') .then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'pug', 'Your project should list "pug" as a dependency'); }, xhr => { throw new Error(xhr.statusText); })
- text: 查看引擎是帕格
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /('|")view engine('|"),( |)('|")pug('|")/gi, 'Your project should set Pug as a view engine'); }, xhr => { throw new Error(xhr.statusText); })
- text: 帕格正在工作
testString: getUserInput => $.get(getUserInput('url')+ '/') .then(data => { assert.match(data, /pug-success-message/gi, 'Your projects home page should now be rendered by pug with the projects .pug file unaltered'); }, xhr => { throw new Error(xhr.statusText); })
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

View File

@@ -0,0 +1,49 @@
---
id: 5895f70cf9fc0f352b528e65
title: Set up Passport
challengeType: 2
videoUrl: ''
localeTitle: 设置护照
---
## Description
<section id="description">提醒一下,这个项目是基于<a href="https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-advancednode/">Glitch</a>的以下入门项目构建的,或者是从<a href="https://github.com/freeCodeCamp/boilerplate-advancednode/">GitHub</a>克隆的。是时候设置<em>Passport</em>这样我们终于可以开始允许用户注册或登录帐户了除了Passport我们还将使用Express-session来处理会话。使用此中间件将会话ID保存为客户端中的cookie并允许我们使用服务器上的该ID访问会话数据。这样我们将个人帐户信息保留在客户端使用的cookie之外以验证我们的服务器是否经过身份验证并保留<em>密钥</em>以访问存储在服务器上的数据。要设置Passport以便在项目中使用您需要先在package.json中将其作为依赖项添加。 <code>&quot;passport&quot;: &quot;^0.3.2&quot;</code>此外现在还要将Express-session添加为依赖项。 Express-session拥有大量可以使用的高级功能但现在我们只是要使用基础知识 <code>&quot;express-session&quot;: &quot;^1.15.0&quot;</code>您需要立即设置会话设置并初始化Passport。一定要先创建变量&#39;session&#39;&#39;passport&#39;,分别要求&#39;express-session&#39;&#39;passport&#39;。要设置您要使用的快速应用程序使用会话我们将仅定义几个基本选项。请务必将“SESSION_SECRET”添加到.env文件中并为其提供随机值。这用于计算用于加密cookie的哈希值 <pre> app.use会话{
secretprocess.env.SESSION_SECRET
resave是的
saveUninitializedtrue
}; </pre>您也可以继续告诉您的快递应用程序<b>使用</b> &#39;passport.initialize&#39;&#39;passport.session&#39;。 (例如, <code>app.use(passport.initialize());</code> )当您认为自己正确时,请提交您的页面。如果您遇到错误,可以<a href="https://gist.github.com/JosephLivengood/338a9c5a326923c3826a666d430e65c3">在这里查看</a>到目前为止完成的项目。 </section>
## Instructions
<section id="instructions">
</section>
## Tests
<section id='tests'>
```yml
tests:
- text: Passort和Express-session是依赖项
testString: getUserInput => $.get(getUserInput('url')+ '/_api/package.json') .then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'passport', 'Your project should list "passport" as a dependency'); assert.property(packJson.dependencies, 'express-session', 'Your project should list "express-session" as a dependency'); }, xhr => { throw new Error(xhr.statusText); })
- text: 正确要求依赖性
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /require.*("|')passport("|')/gi, 'You should have required passport'); assert.match(data, /require.*("|')express-session("|')/gi, 'You should have required express-session'); }, xhr => { throw new Error(xhr.statusText); })
- text: Express应用程序使用新的依赖项
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /passport.initialize/gi, 'Your express app should use "passport.initialize()"'); assert.match(data, /passport.session/gi, 'Your express app should use "passport.session()"'); }, xhr => { throw new Error(xhr.statusText); })
- text: 正确设置会话和会话密钥
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /secret:( |)process.env.SESSION_SECRET/gi, 'Your express app should have express-session set up with your secret as process.env.SESSION_SECRET'); }, xhr => { throw new Error(xhr.statusText); })
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

View File

@@ -0,0 +1,48 @@
---
id: 589fc830f9fc0f352b528e74
title: Set up the Environment
challengeType: 2
videoUrl: ''
localeTitle: 设置环境
---
## Description
<section id="description">提醒一下,这个项目是基于<a href="https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-socketio/">Glitch</a>的以下入门项目构建的,或者是从<a href="https://github.com/freeCodeCamp/boilerplate-socketio/">GitHub</a>克隆的。将Socket.IO添加为依赖项并在服务器中要求/实例化它,定义为&#39;io&#39;并将http服务器作为参数。 <code>const io = require(&#39;socket.io&#39;)(http);</code>需要处理的第一件事是从客户端侦听新连接。 <dfn>on</dfn>关键字就是这样 - 监听特定事件。它需要2个参数一个包含所发出事件标题的字符串以及一个用于传递数据的函数。在我们的连接侦听器的情况下我们使用<em>socket</em>来定义第二个参数中的数据。套接字是连接的个人客户端。要在我们的服务器上侦听连接,请在项目中的注释之间添加以下内容: <pre> io.on&#39;connection&#39;socket =&gt; {
console.log&#39;用户已连接&#39;;
}; </pre>现在对于客户端进行连接您只需要将以下内容添加到client.js中该客户端经过身份验证后由页面加载 <pre> / * global io * /
var socket = io; </pre>注释会抑制您通常会看到的错误因为文件中未定义“io”。我们已经在chat.pug页面上的Socket.IO库中添加了一个可靠的CDN。现在尝试加载您的应用并进行身份验证您应该在服务器控制台中看到“用户已连接” <strong>注意</strong> <br> <code>io()</code>仅在连接到同一URL /服务器上托管的套接字时起作用。要连接到其他地方托管的外部套接字,您可以使用<code>io.connect(&#39;URL&#39;);</code> 。当您认为自己已经做对时,请提交您的页面。 </section>
## Instructions
<section id="instructions">
</section>
## Tests
<section id='tests'>
```yml
tests:
- text: Socket.IO是一个依赖项
testString: getUserInput => $.get(getUserInput('url')+ '/_api/package.json') .then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'socket.io', 'Your project should list "socket.io" as a dependency'); }, xhr => { throw new Error(xhr.statusText); })
- text: Socket.IO已得到适当的要求和实例化
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js').then(data => {assert.match(data, /io.*=.*require.*('|")socket.io('|").*http/gi, 'You should correctly require and instantiate socket.io as io.');}, xhr => { throw new Error(xhr.statusText); })
- text: Socket.IO应该正在监听连接
testString: getUserInput => $.get(getUserInput('url')+ '/_api/server.js') .then(data => { assert.match(data, /io.on.*('|")connection('|").*socket/gi, 'io should listen for "connection" and socket should be the 2nd arguments variable'); }, xhr => { throw new Error(xhr.statusText); })
- text: 您的客户端应该连接到您的服务器
testString: getUserInput => $.get(getUserInput('url')+ '/public/client.js') .then(data => { assert.match(data, /socket.*=.*io/gi, 'Your client should be connection to server with the connection defined as socket'); }, xhr => { throw new Error(xhr.statusText); })
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

View File

@@ -0,0 +1,39 @@
---
id: 5895f70bf9fc0f352b528e64
title: Use a Template Engine's Powers
challengeType: 2
videoUrl: ''
localeTitle: 使用模板引擎的权力
---
## Description
<section id="description">提醒一下,这个项目是基于<a href="https://glitch.com/#!/import/github/freeCodeCamp/boilerplate-advancednode/">Glitch</a>的以下入门项目构建的,或者是从<a href="https://github.com/freeCodeCamp/boilerplate-advancednode/">GitHub</a>克隆的。使用模板引擎的最大特点之一是能够将变量从服务器传递到模板文件然后再将其呈现为HTML。在您的Pug文件中您将通过引用变量名称作为<code>#{variable_name}</code>与元素上的其他文本内联,或者在元素上使用相等的一侧而不使用空格(例如<code>p= variable_name</code>来设置该<code>p= variable_name</code> 。 p元素文本等于变量。我们强烈建议在他们的Githubs自述文件中<a href="https://github.com/pugjs/pug">查看</a> Pug的语法和结构。 Pug就是使用空格和制表符来显示嵌套元素并减少制作漂亮网站所需的代码量。查看项目中包含的我们的pug文件&#39;index.pug&#39;,我们使用变量<em>title</em><em>message</em>要从我们的服务器单独传递它们,您需要将一个对象作为第二个参数添加到<em>res.render中</em> ,并带有变量和他们的价值。例如,传递此对象以设置索引视图的变量: <code>{title: &#39;Hello&#39;, message: &#39;Please login&#39;</code>它应该看起来像: <code>res.render(process.cwd() + &#39;/views/pug/index&#39;, {title: &#39;Hello&#39;, message: &#39;Please login&#39;});</code>现在刷新页面您应该在视图中呈现的那些值在index.pug文件中列出的正确位置当您认为自己已经做对时请提交您的页面。 </section>
## Instructions
<section id="instructions">
</section>
## Tests
<section id='tests'>
```yml
tests:
- text: 帕格渲染变量正确
testString: getUserInput => $.get(getUserInput('url')+ '/') .then(data => { assert.match(data, /pug-variable("|')>Please login/gi, 'Your projects home page should now be rendered by pug with the projects .pug file unaltered'); }, xhr => { throw new Error(xhr.statusText); })
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>