React中如何通过Session Storage在页面间传递Token?
我有一个React登录页,支持用户名和密码输入。提交凭据后,会通过JSON API验证并生成客户端Token。我的目标是在登录成功后将Token传递到落地页,并用对应客户端数据填充下拉列表。目前遇到的问题是无法将Token从登录页传递到落地页。
登录页中,我使用Fetch从API获取Token,然后存入sessionStorage,相关代码如下:
componentDidMount() { this.fetchData(); } //request the token fetchData() { return fetch('http://myapiaut:1111/api/auth', { method: 'POST', headers: { 'Content-type': 'application/json', }, body: JSON.stringify({ username: 'myAdminusername', password: 'myAdminPassword', Authorization: 'myAdminPassword', }) }) /*end fetch */ .then(results => results.json()) .then(data => { this.setState({ data: data }) sessionStorage.setItem("token", data) }) } //authenticate request requestUserInfo() { var token = sessionStorage.getItem("token"); return fetch('http://myapiaut:1111/api/auth', { method: 'GET', headers: new Headers({ Authorization: 'Bearer' + sessionStorage.token }), }) .then((response) => response.json()); }
落地页代码如下:
componentDidMount() { fetch('http://myapiclients:22222/api/clients', { method: 'GET', headers: { 'Content-type': 'application/json', 'Authorization': 'Bearer ' + sessionStorage.token }, }) .then(results => results.json()) .then(data => this.setState({ data: data })) }
我已确认登录页的fetchData函数能成功获取Token,但问题在于无法正确存储Token以传递到落地页。另外,落地页在手动复制Token到Fetch的Authorization字段时可正常工作,希望得到问题排查帮助。
我帮你梳理几个最可能的问题点,你可以逐一排查验证:
1. Token存储的是整个响应对象,而非纯Token字符串
你现在直接把API返回的data整个存入sessionStorage,但data应该是一个包含Token字段的对象(比如data.token或者data.access_token),而不是Token本身。sessionStorage只能存储字符串,直接存对象的话会被转成[object Object],这样落地页拿到的自然不是有效的Token。
修改方式:
先确认API返回的Token字段名称,比如假设返回的结构是{ token: "xxx..." },那存储的时候要改成:
.then(data => { this.setState({ data: data }) // 只存储Token字段的值 sessionStorage.setItem("token", data.token) })
2. 落地页获取Token的方式不够可靠
你在落地页用sessionStorage.token来获取值,虽然这种写法可行,但更推荐用标准的sessionStorage.getItem("token")方法,避免一些隐式的属性访问问题。同时可以在落地页加个日志,确认拿到的Token是什么:
修改落地页代码:
componentDidMount() { const token = sessionStorage.getItem("token"); console.log("落地页拿到的Token:", token); // 先打印看看值是否正确 fetch('http://myapiclients:22222/api/clients', { method: 'GET', headers: { 'Content-type': 'application/json', 'Authorization': 'Bearer ' + token }, }) .then(results => results.json()) .then(data => this.setState({ data: data })) }
3. 跳转时机过早,Token还没完成存储
如果登录成功后你是直接跳转页面,可能存在异步存储还没完成就跳转的情况。要确保在sessionStorage.setItem执行完成之后再进行页面跳转(比如用React Router的history.push)。
示例修改(假设用React Router):
.then(data => { this.setState({ data: data }) sessionStorage.setItem("token", data.token) // 确认存储完成后再跳转 this.props.history.push('/landing-page'); })
4. 检查同源策略问题
如果登录页和落地页不是同源(比如域名、端口不同),sessionStorage是无法跨域共享的。不过从你的API地址来看,登录API是1111端口,客户端API是22222端口,但页面本身应该是同一个域名下的,所以这个可能性较低,但也可以确认一下页面的URL是否一致。
另外,你登录页的requestUserInfo方法里,Authorization头的Bearer和Token之间少了一个空格,写成了'Bearer' + sessionStorage.token,虽然这不是当前问题的直接原因,但也建议改成'Bearer ' + sessionStorage.token,避免后续请求出错。
内容的提问来源于stack exchange,提问作者user1724708

