路由守卫区分认证用户与访客时Auth Service获取user为null
localStorage.getItem('user') Returns Null in Your Auth Guard Let's break down what's going wrong and how to fix this auth guard issue step by step:
First, Verify the Basics
Before jumping into code changes, confirm these two critical points:
- Is the
useractually being stored in localStorage? Open your browser's dev tools (Chrome: Application > Local Storage; Firefox: Storage > Local Storage) and check if there's auserkey present with a valid JSON string value. - Are you mixing Ionic Storage and browser localStorage? You injected Ionic's
Storageservice in yourAuthService, but you're usinglocalStorage.getItem()to fetch data. These are not the same storage mechanisms—by default, Ionic Storage uses IndexedDB in browsers, not localStorage. That's a super common gotcha!
Fix 1: Use Ionic Storage Consistently (Recommended)
Since you're working with Ionic, sticking with its Storage service is better for cross-platform compatibility. Note that Ionic Storage methods are asynchronous, so we'll adjust your auth service and guard to handle promises:
Update auth.service.ts
import { Injectable } from '@angular/core'; import { Storage } from '@ionic/storage'; @Injectable({ providedIn: 'root' }) export class AuthService { constructor(public storage: Storage) {} // ... other methods public async isAuthenticated(): Promise<boolean> { const user = await this.storage.get('user'); console.log('Fetched user from Ionic Storage:', user); // Check if user exists, has a token, and token is not expired if (user && user.token && user.token_deadline) { const tokenExpiry = new Date(user.token_deadline); return tokenExpiry > new Date(); } return false; } }
Update auth-guard.service.ts
The canActivate method supports returning a Promise, so we'll make it async to handle the auth check properly:
import { Injectable } from '@angular/core'; import { Router, CanActivate, ActivatedRouteSnapshot } from '@angular/router'; import { AuthService } from './auth.service'; @Injectable() export class AuthGuardService implements CanActivate { constructor(private router: Router, private authService: AuthService) { } async canActivate(route: ActivatedRouteSnapshot): Promise<boolean> { const isAuthenticated = await this.authService.isAuthenticated(); // Redirect to login page if user isn't authenticated if (!isAuthenticated) { this.router.navigate(['/login']); return false; } return true; } }
Fix 2: Stick with Browser localStorage (If You Prefer)
If you want to use the browser's native localStorage, make sure you're stringifying the user object when storing it (localStorage only accepts string values):
// Example login success code to store user data const userData = { token: 'your-valid-auth-token', token_deadline: '2024-12-31T23:59:59' // Use a valid ISO date string }; localStorage.setItem('user', JSON.stringify(userData));
Then update your isAuthenticated method to parse the stored string back into an object:
public isAuthenticated(): boolean { const userStr = localStorage.getItem('user'); if (!userStr) return false; const user = JSON.parse(userStr); console.log('Fetched user from localStorage:', user); if (user.token && user.token_deadline) { const tokenExpiry = new Date(user.token_deadline); return tokenExpiry > new Date(); } return false; }
Other Quick Checks
- Same-origin policy: localStorage is tied to your app's origin (domain + port). If you're storing data on one port and accessing it on another, you'll get null.
- Accidental clearing: Double-check that no other code (like a logout function or page refresh handler) is clearing the
userkey from localStorage before the guard runs.
内容的提问来源于stack exchange,提问作者Katalux

