课程名称:web前端架构师
课程章节:第16周 第三章、第四章
主讲老师:张轩
课程内容: toJSON 和 transform 处理文档 和 cookie 的回顾
toJSON 和 transform 处理文档
默认情况下我们返回给用户的信息时查询到的所有信息,有一些信息不应该返回给用户,比如密码等
我们可以这样做
我们可能会想到获取到用户信息后,将不需要的字段删除就行了
...
const user = await service.user.findByUsername(username);
// 这里 ts 会报错
delete user.password;
...
但是运行代码后我们会发现, password 属性并没有被删除,同时 ts 会报错,因为查询的结果并不是一个普通的对象, 但是它自带一个 toJSON 方法,可以将它转化为 json
...
const user = await service.user.findByUsername(username);
// 这里 ts 会报错, 先不管这个
delete user.password;
...
就这样就可以将 password 属性给删除了,但是这样做也很不好,每次都要手动删除不需要的属性
在创建 Schema 时,有第二个参数,这里可以设置 toJSON 的时候,将 password 属性删除
const UserSchema = new Schema<User>({
username: String,
password: String,
email: String,
nickname: String,
phoneNumber: String,
}, {
timestamps: true,
toJSON: {
transform(_doc, ret) {
// 这里可以删除掉不需要的信息
delete ret.password;
delete ret._v;
},
},
});
这样就将加不需要的信息给删除掉了
mongoose-sequence
在我们刚开始接触 mysql 时,经常会用 id 作为索引,并且可以把它设为自增,mongoose 会默认给我们创建 _id 作为索引,如果我们想使用一个自增的索引,那么就可以使用 mongoose-sequence插件 ,它是 mongoose 的一个插件
不过个人认为如果我们使用自增索引作为查询条件的话,是非常不好的
用户认证的方式 - cookie
Cookie
Cookie 为了解决 HTTP 无状态的问题。https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Cookies
创建 Cookie
服务器使用 Set-Cookie 响应头部向用户代理(一般是浏览器)发送 Cookie信息。
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry
现在,对该服务器发起的每一次新请求,浏览器都会将之前保存的Cookie信息通过 Cookie 请求头部再发送给服务器。这是一个自动的过程
GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry
设置cookie后,对该服务器发起的每一次新请求,浏览器都会将之前保存的Cookie信息通过 Cookie 请求头部再发送给服务器。这是一个自动的过程。
GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry
Cookie 的生命周期
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
特别注意:当Cookie的过期时间被设定时,设定的日期和时间只与客户端相关,而不是服务端。
Cookie 安全性
- Secure: 只应通过被 HTTPS 协议加密过的请求发送给服务端
- HttpOnly: 无法使用 Javascript 对他进行访问。可以有效缓解 XSS 攻击
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
// document.cookie 无法访问到对应的数据
作用域
- Domain:Domain 指定了哪些主机可以接受 Cookie,如果不指定,默认为 origin,不包含子域名。
- Path:Path 标识指定了主机下的哪些路径可以接受 Cookie。
下面举个例子
- 假如不设置作用域,假如我们的网址目前是 test.com,只有完全同源才能访问。
- Set-Cookie: id=a3fWa;
- 那么只有 test.com 可以访问,api.test.com 不可访问。
- Set-Cookie: id=a3fWa; Domain=test.com; Path=/
- 如果设置,子域名也包含其中,
- 比如 test.com, api.test.com, xxx.test.com
SameSite 新的属性
SameSite Cookie 允许服务器要求某个 cookie 在跨站请求时不会被发送,可以阻止跨站请求伪造攻击(Cross-Site Request Forgery,简称 CSRF),SameSite cookies 是相对较新的一个字段,所有主流浏览器都已经得到支持。
// 描述问题
// bank.com
Set-Cookie:id=a3fWa;
// evil.com
<form action="bank.com/transfer" method="POST">
...
</form>
// 提交表单后,由于登录银行的 cookie 已经存在,钱被转走
// evil2.com 插入一张图片
<img src="http://bank.com/transfer?account=bob&amount=1000000&for=mallory">
// 访问图片后,由于登录银行的 Cookie 还存在,钱被转走
SameSite 属性
- Strict 最为严格,完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。换言之,只有当前网页的 URL 与请求目标一致,才会带上 Cookie。
- Lax 规则稍稍放宽,大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外。
- None 完全没有限制, 默认就是none
所以我们可以使用 Lax 和 Strict ,但是 Strict 导航到目标网址也不会发送 Cookie,假如我们登录了 github,如果通过该网站访问,那么每次跳过去的github 网页都是未登录的体验较差,所以我们多数情况下可以使用 Lax 。由于get请求还是携带 Cookie ,所以一些跟用户信息安全等相关的操作要使用 get
Set-Cookie: CookieName=CookieValue; SameSite=Lax;