Ionic 4向Express路由传Token遇阻,无法验证Storage中Token状态
问题分析与解决方案
你遇到的res.user.access_token显示undefined的问题,核心原因是后端返回的user是一个数组,而你在前端把它当成了单个对象来访问。
看你提供的console.log结果:
res.user:[{"id":1,"name":"Admin","email":"Admin@test.com","password":"$2a$10$2OaS5CyGKMSF5J8wed5W7.qyNFYrPScBM49SgU7L9MBMVF0RWxx1e","created_at":"2019-10-16T13:28:06.000Z","access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaWF0IjoxNTcyNDU1MTk3LCJleHAiOjE1NzI1NDE1OTd9.2eFbQ294TG6gvKUxSyaQGDBEas7ZLFT8k9H7jnpOoXQ"}]
明显res.user是一个包含单个用户对象的数组,直接访问res.user.access_token自然会得到undefined——数组没有这个属性,正确的访问方式应该是res.user[0].access_token。
修复方案
方案1:修改后端代码(推荐)
因为登录逻辑是查找单个用户,后端应该返回单个用户对象而非数组。调整Express路由的返回部分:
router.post('/login', (req, res) => { const email = req.body.email; const form_password = req.body.password; findUserByEmail(email, (err, user) => { if (err) return res.status(500).send({ "message": 'Server error!', "status": '500' }); if (!user[0]) return res.status(404).send({ "message": 'User not found!', "status": '404' }); const result = bcrypt.compareSync(form_password, user[0].password); if (!result) return res.status(401).send({ "message": 'Password not valid!', "status": '401' }); const expiresIn = 24 * 60 * 60; user[0].access_token = jwt.sign({ id: user[0].id }, process.env.SECRET_KEY, { expiresIn: expiresIn }); // 把返回的user改成user[0],返回单个对象 res.status(200).send({ "user": user[0], "expires_in": expiresIn, "message": 'Success!', "status": '200' }); }); });
这样前端拿到的res.user就是单个对象,原来的res.user.access_token就能正常获取值了。
方案2:修改前端代码
如果暂时不想改动后端,可以调整前端访问路径:
login(user: User): Observable<AuthResponse> { return this.httpClient.post(`${this.AUTH_SERVER_ADDRESS}/login`, user).pipe( tap(async (res: AuthResponse) => { // 先判断数组是否有内容 if (res.user && res.user.length > 0) { const userData = res.user[0]; console.log("res.user.access_token:" + userData.access_token); await this.storage.set("ACCESS_TOKEN", userData.access_token); // 注意expires_in是在响应根层级,不是user数组里的 await this.storage.set("EXPIRES_IN", res.expires_in); this.authenticationState.next(true); } }) ) }
验证Token是否存入Storage的方法
方法1:在代码中主动验证存储结果
在存储操作完成后,立即调用storage.get获取值并打印:
tap(async (res: AuthResponse) => { if (res.user && res.user.length > 0) { const userData = res.user[0]; await this.storage.set("ACCESS_TOKEN", userData.access_token); await this.storage.set("EXPIRES_IN", res.expires_in); // 验证存储内容 const savedToken = await this.storage.get("ACCESS_TOKEN"); const savedExpires = await this.storage.get("EXPIRES_IN"); console.log("已存储的Token:", savedToken); console.log("已存储的过期时间:", savedExpires); this.authenticationState.next(true); } })
方法2:通过浏览器开发者工具查看
如果使用的是Ionic的Storage,默认会存在localStorage(或IndexedDB)中:
- 打开浏览器开发者工具(快捷键F12)
- 切换到
Application标签页 - 在左侧菜单找到
Local Storage(或Indexed DB),展开后查看对应键值对,确认ACCESS_TOKEN和EXPIRES_IN是否存在且值正确。
方法3:在其他组件中检查存储状态
在需要验证登录状态的组件中,注入AuthenticationService并查询存储:
constructor(private authService: AuthenticationService) {} ngOnInit() { this.authService.storage.get("ACCESS_TOKEN").then(token => { console.log("从Storage获取的Token:", token); if (token) { console.log("Token已成功存入"); } else { console.log("Token未存入"); } }); }
内容的提问来源于stack exchange,提问作者baumli
相关产品推荐
相关产品推荐

