app.use(helmet({
frameguard: { // configure
action: 'deny'
},
contentSecurityPolicy: { // enable and configure
directives: {
defaultSrc: ["self"],
styleSrc: ['style.com'],
}
},
dnsPrefetchControl: false // disable
}))
我们分别为教学目的引入了每个中间件,并且易于测试。使用“父”头盔()中间件对于真实项目来说是最简单,更清洁的。 bcrypt.hash(myPlaintextPassword, saltRounds, (err, hash) => { /*Store hash in your db*/ });
bcrypt.compare(myPlaintextPassword, hash, (err, res) => { /*res == true or false*/ });
。在记录完成的哈希并将“res”记录到比较中的控制台之后,将其添加到现有哈希函数中(因为您需要在调用比较函数之前等待哈希完成)。您应该在控制台中看到一个哈希值,然后打印出“true”!如果您将compare函数中的'myPlaintextPassword'更改为'someOtherPlaintextPassword',那么它应该为false。 bcrypt.hash('passw0rd!',13,(错误,哈希)=> { - 的console.log(散列); //$2a$12$Y.PHPE15wR25qrrtgGkiYe2sXo98cjuMCG1YwSI5rJW1DSJp0gEYS - bcrypt.compare('passw0rd!',hash,(err,res)=> { - 的console.log(RES); //真正 - }); -});当您认为自己已经做对时,请提交您的页面。
bcrypt.hash(myPlaintextPassword, saltRounds, (err, hash) => { /*Store hash in your db*/ });
+
+```js
+bcrypt.hash(myPlaintextPassword, saltRounds, (err, hash) => {
+ /*Store hash in your db*/
+});
+```
+
+bcrypt.compare(myPlaintextPassword, hash, (err, res) => { /*res == true or false*/ });
. 把这个添加到你已有的哈希方法(你需要等哈希完成之后才能调用对比方法) 在你输入哈希过的值之后在对比方法里面输入 'res' 到控制台. 你会看到一个哈希值和 ``true`` 被打印出来。如果你在对比方法里面把 'myPlaintextPassword' 改变成 'someOtherPlaintextPassword' 那么应该会输出 ``false``
+
+```js
+bcrypt.compare(myPlaintextPassword, hash, (err, res) => {
+ /*res == true or false*/
+});
+```
+
+当控制台打印哈希完成并且在对比的 console 里打印 ‘res’ 后,将其添加到现有的哈希函数中(因为要等待哈希完成才能调用 compare 函数)。 控制台中应该打印一个哈希,然后打印 “true”! 如果将比较函数中的 “myPlaintextPassword” 更改为 “someOtherPlaintextPassword”,则它应该显示为false。
+
+```js
+bcrypt.hash('passw0rd!', 13, (err, hash) => {
+ console.log(hash);
+ //$2a$12$Y.PHPE15wR25qrrtgGkiYe2sXo98cjuMCG1YwSI5rJW1DSJp0gEYS
+ bcrypt.compare('passw0rd!', hash, (err, res) => {
+ console.log(res); //true
+ });
+});
+
+```
+
+提交页面当你觉得已经完成的时候。
var hash = bcrypt.hashSync(myPlaintextPassword, saltRounds);
var result = bcrypt.compareSync(myPlaintextPassword, hash);
结果是布尔值true或false。添加此功能并登录控制台结果以查看其是否正常工作。当您认为自己已经做对时,请提交您的页面。如果您在这些挑战期间遇到错误,可以在此处查看示例完成的代码。 X-Powered-By: Express
默认情况下会被添加到所有响应的头部。不过 helmet.hidePoweredBy() 中间件可以帮你移除 X-Powered-By 头。你甚至可以把头设置成其它的值。 如 app.use(helmet.hidePoweredBy({ setTo: 'PHP 4.2.0' }))
+<frame>
或<iframe>
。除其他外,这可能导致点击劫持攻击。点击劫持是一种欺骗用户与不同于用户认为的页面进行交互的技术。这可以通过iframing在恶意上下文中执行您的页面获得。在这种情况下,黑客可以在页面上放置隐藏层。隐藏按钮可用于运行错误的脚本。此中间件设置X-Frame-Options标头。它限制了谁可以将您的网站放在框架中。它有三种模式:DENY,SAMEORIGIN和ALLOW-FROM。我们不需要我们的应用程序框架。您应该使用配置对象{action: 'deny'}
传递的helmet.frameguard()
。
或者
标签里,用以实现“点击劫持”。点击劫持是一种视觉上的欺骗手段,让用户误以为自己在与所看到的网页交互。通过 iframe,黑客可以在你的页面上添加一个透明的“层”,然后把自己的恶意代码放在一个用户看不到的按钮中。这样一来,你网站的执行环境就被黑客设置成了他想要的效果。helmet 中间件可以设置 X-Frame-Options 这个头部。这样就能限制谁可以通过 iframe 引入你的页面了。 有三个模式可供配置: DENY, SAMEORIGIN, 和 ALLOW-FROM.
+我们的应用不需要被 iframe 引用。
+helmet.frameguard()
这个方法,然后传入配置对象 {action: 'deny'}
就可以了。
helmet.frameguard()
中的 action
属性的值应该为 "DENY"'
testString: getUserInput => $.get(getUserInput('url') + '/_api/app-info').then(data => { assert.property(data.headers, 'x-frame-options'); assert.equal(data.headers['x-frame-options'], 'DENY');}, xhr => { throw new Error(xhr.responseText); })
```
@@ -36,6 +42,11 @@ tests:
helmet.contentSecurityPolicy()
,并将其配置为将defaultSrc指令
设置为["self"]
(允许的列表) 来源必须位于一个数组中,以便默认情况下仅信任您的网站地址。 还设置scriptSrc
指令,以便您允许从您的网站以及"trusted-cdn.com"域下载脚本。
-提示:在self
关键字中,单引号是关键字本身的一部分,因此需要使用双引号将其括起来才能起作用。
+$2a$13$ZyprE5MRw2Q3WpNOGZWGbeG7ADUre1Q8QO.uUUtcbqloU0yvzavOm
确实有一个结构。第一小部分数据$2a
定义了使用何种哈希算法。下一部分$13
定义了成本 。成本是计算哈希值所需的功率。它具有2 ^成本的对数标度,并确定通过散列算法放置数据的次数。例如,以10为代价,您可以在普通计算机上每秒散列10个密码,但是每个散列需要花费3秒才能进行散乱...并且需要花费更多时间,成本为31需要多天才能完成哈希。目前,12的成本被认为是非常安全的。哈希$ZyprE5MRw2Q3WpNOGZWGbeG7ADUre1Q8QO.uUUtcbqloU0yvzavOm
的最后一部分看起来像$ZyprE5MRw2Q3WpNOGZWGbeG7ADUre1Q8QO.uUUtcbqloU0yvzavOm
数字,句号和字母,但它实际上是两条独立的信息。前22个字符是纯文本的盐,其余的是哈希密码! $2a$13$ZyprE5MRw2Q3WpNOGZWGbeG7ADUre1Q8QO.uUUtcbqloU0yvzavOm
,它遵循固定的结构. 前面一小节 $2a
说明了该哈希采用什么算法。下一部分 $13
定义了 代价. 代价就是用多少计算资源来生成哈希。 它的对数刻度是 2^cost 它决定了数据被放入哈希算法多少次。举个例子,如果代价为10也就是说你能够在一个普通的计算机上每秒钟哈希10个密码。然而,如果代价为15,那每个哈希都要3秒钟,再举例子,如果代价是31at a cost of 31,那每次哈希能耗费好几天。通常代价为12就已经足够安全。哈希的最后一部分 $ZyprE5MRw2Q3WpNOGZWGbeG7ADUre1Q8QO.uUUtcbqloU0yvzavOm
, 看起来像随机字符、句号、字母组成的随机字符串。但实际上它有两部分内容。前面22个字符就是纯文本的盐,剩下的就是加密过的密码!
+