如何将用户ID存入Local Storage以从数据库获取对应用户数据?
Hey there! Let's fix your login flow step by step so you can successfully store the user ID in localStorage after login and fetch user-specific data later. We'll go through both your backend and frontend code, fixing syntax issues, security gaps, and logic errors.
Backend (Node.js) Fixes
Your backend has syntax mistakes, SQL injection risks, and logical inconsistencies. Here's the corrected version with explanations:
app.post('/api/user/login', (req, res) => { // Fixed arrow function syntax const { username, password } = req.body; // Destructure request body for cleaner code // Use parameterized query to block SQL injection (critical security fix!) const sql = 'SELECT * FROM user WHERE username = ? AND password = ? LIMIT 1'; mysqlConnection.query(sql, [username, password], (err, rows) => { // Fixed arrow function + added safe parameters if (err) { console.error(err); return res.status(500).json({ error: 'Server error' }); // Proper error status code } if (rows.length > 0) { // Fixed length check logic // Return the full user object (including ID) as JSON res.status(200).json(rows[0]); } else { // Return 401 (Unauthorized) for invalid credentials (standard HTTP semantics) res.status(401).json({ error: 'Invalid username or password' }); } }); });
Key changes made:
- Corrected arrow function syntax (
=>instead of=in callback definitions) - Eliminated SQL injection risk with parameterized queries (never concatenate user input directly into SQL!)
- Fixed broken SQL statement structure (moved
LIMIT 1outside the password string) - Used proper HTTP status codes for success/error responses
- Switched to JSON responses instead of plain strings for consistent frontend parsing
- Cleaned up request body handling with destructuring
Frontend (Angular) Fixes
Your Angular component has issues with form handling, API response parsing, and localStorage usage. Here's the corrected code:
import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; // Added validators for basic validation import { AuthService } from '../auth.service'; @Component({ selector: 'login-form', templateUrl: "./login-form.component.html", styleUrls: ["./login-form.component.css"] }) export class LoginFormComponent implements OnInit { loginForm: FormGroup; // Renamed for clarity constructor( private router: Router, private formBuilder: FormBuilder, private authService: AuthService ) { this.loginForm = this.formBuilder.group({}); // Initialize form in constructor } ngOnInit() { this.initLoginForm(); } initLoginForm() { this.loginForm = this.formBuilder.group({ // Set empty defaults + add required validators username: ['', Validators.required], password: ['', Validators.required] }); } onLogin() { if (this.loginForm.invalid) { return; // Block submission if form is incomplete } const loginData = this.loginForm.value; console.log('Login attempt:', loginData); this.authService.login(loginData).subscribe({ next: (user) => { // Store user ID in localStorage (key first, value second; convert to string) localStorage.setItem('userId', user.id.toString()); // Navigate to the todo app route this.router.navigate(['/todoapp']); }, error: (err) => { console.error('Login failed:', err); // Add user-friendly error feedback here (e.g., toast message, alert) } }); } }
Corresponding AuthService Adjustment
Make sure your AuthService handles HTTP requests correctly:
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class AuthService { private apiUrl = 'http://your-backend-url/api/user/login'; // Replace with your actual backend URL constructor(private http: HttpClient) { } login(loginData: { username: string; password: string }): Observable<any> { return this.http.post(this.apiUrl, loginData); } }
Key frontend changes:
- Fixed FormGroup initialization with proper defaults and validators
- Renamed methods/variables for better readability (
onLogininstead oflog,loginForminstead ofform) - Accessed form values correctly from
loginForm.valueinstead of uninitialized class variables - Fixed localStorage syntax (
setItem(key, value)instead of reversed parameters) - Used the actual user ID returned from the backend (not an unassigned
this.id) - Added error handling for login failures
- Added form validation to prevent empty submissions
Using the Stored User ID to Fetch Data
Once the user ID is saved in localStorage, you can retrieve it in any component to fetch user-specific data. Example in a Todo component:
import { Component, OnInit } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Component({ selector: 'app-todoapp', templateUrl: './todoapp.component.html', styleUrls: ['./todoapp.component.css'] }) export class TodoappComponent implements OnInit { userData: any; constructor(private http: HttpClient) { } ngOnInit() { this.fetchUserData(); } fetchUserData() { const userId = localStorage.getItem('userId'); if (!userId) { // Redirect to login if no user ID exists window.location.href = '/login'; return; } // Replace with your actual API endpoint for user data this.http.get(`http://your-backend-url/api/user/${userId}`).subscribe({ next: (data) => { this.userData = data; }, error: (err) => { console.error('Failed to fetch user data:', err); } }); } }
Add this backend endpoint to fetch user data by ID:
app.get('/api/user/:id', (req, res) => { const userId = req.params.id; const sql = 'SELECT * FROM user WHERE id = ? LIMIT 1'; mysqlConnection.query(sql, [userId], (err, rows) => { if (err) { console.error(err); return res.status(500).json({ error: 'Server error' }); } if (rows.length > 0) { res.status(200).json(rows[0]); } else { res.status(404).json({ error: 'User not found' }); } }); });
内容的提问来源于stack exchange,提问作者Malik Shafi

