react 服务端渲染 cookie 有2个问题:
- 服务端执行的代码如何拿到cookie并解析透穿给后端接口,后端又如何设置cookie?
- 浏览器执行的代码如何读取cookie?
服务端cookie透传
明白next的渲染流程很重要:
浏览器打开页面 -> node服务请求后端接口 -> node服务渲染页面 并响应
node服务透传cookie给后端接口:此时cookie只能从request中取的cookie: nextjs文档
Article.getInitialProps = async ({ req, query }) => {
// 文章详情
const { article, statusCode, errMessage } = await GET({
url: `/api/article/${id}`,
headers: {
Cookie: req.headers.cookie
}
}).then(resp => {
return {article: resp.data, statusCode: resp.code, errMessage: resp.message}
})
return { article: article, statusCode: statusCode, errMessage: errMessage }
}
后端设置cookie:
- 如果是node服务请求的后端接口,此时的node服务就相当于nginx一样的代理请求,需要将响应的cookie透传给浏览器
import React from "react";
import {GET} from '../src/request';
function Demo ({data}) {
return (
{data}
)
}
Demo.getInitialProps = async ({ req, query, res }) => {
let cookie;
const {data, code, message} = await GET({url: "http://douyacun.io/api/helper/demo", noCheck: true}).
then((resp) => {
res.setHeader("set-cookie", resp.headers["set-cookie"]);
return resp.data
}).
then((data) => {
return data
})
return {data: data}
}
export default Demo
GET 是封装的 axios,axios 的response不是node原生的 response,而nextjs的res是node原生的response,这里需要注意一下使用的请求库
重点是:明白node服务渲染,其实是一层代理服务
- 如果是浏览器客户端请求的后端接口,response是可以直接被浏览器读取到的,就不需要我们做什么事情了。
客户端读取cookie
客户端请求接口会有2个cookie问题:
- 跨域请求携带cookie
- 如何读取并解析cookie
跨域请求携带cookie
原理是一致的,先header请求服务端,验证服务端是否支持跨域,以及支持的域名:
Access-Control-Allow-Origin: https://www.douyacun.com
这里一定要明确指定域名,否则请求还是无法携带cookie的
axios 需要指定:
withCredentials: true
浏览器读取并解析cookie
用户信息存cookie的原因是不安全,也不建议的。当然前提用户信息存在隐私数据,解决方案是存在session中,cookie只是存session id。
我的博客cookie只存 昵称和ID。如何确保cookie不被篡改呢?cookie,对数据进行签名,签名使用的key是存储在服务端里。如果有更高的安全需求的,请移步~
重点:react服务端渲染,cookie是存在浏览器上的,确保代码是在浏览器客户端上执行的才能读取到对吧
import React from 'react';
import { parseCookies } from 'nookies'
function Demo() {
const [user, setUser] = React.useState({})
// 首次加载
React.useEffect(() => {
const all = parseCookies();
if (all.douyacun) {
setUser(JSON.parse(all.douyacun));
}
}, [])
return (
Hello {user.name}.
)
}
export default demo
React.useEffect的用法, 需要注意的是:
默认情况下,effect 将在每轮渲染结束后执行,但你可以选择让它 在只有某些值改变的时候 才执行。
如果想执行只运行一次的 effect(仅在组件挂载和卸载时执行),可以传递一个空数组(
[]
)作为第二个参数。这就告诉 React 你的 effect 不依赖于 props 或 state 中的任何值,所以它永远都不需要重复执行,解析cookie只需要一次就够了~