Fetch API 使用详解:Bearer Token 与 localStorage 实践

发布于:2025-06-10 ⋅ 阅读:(17) ⋅ 点赞:(0)

        Fetch API:现代浏览器内置的用于发送 HTTP 请求的 API,Bearer Token:一种基于令牌的身份验证方案,常用于 JWT 认证,localStorage:浏览器提供的持久化存储方案,用于在客户端存储数据。

        token是我们前端获取后端数据的令牌,


// 登录函数 - 调用真实后端API
async function loginUser(username, password) {
    try {
        const response = await fetch(`${API_URL}/auth/login`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                username: username,
                password: password
            })
        });
        
        // 检查响应状态
        if (!response.ok) {
            const errorData = await response.json();
            throw new Error(errorData.message || '登录失败');
        }
        
        // 解析响应数据
        const data = await response.json();
        
        // 从响应中获取token(后端返回的token字段)
        const token = data.token;
        
        // 将token存入localStorage
        localStorage.setItem('authToken', token);
        
        return token;
    } catch (error) {
        console.error('登录错误:', error);
        throw error;
    }
}

        我们通过输入的账户密码,从前端表格中获取,然后在这个登录函数中参数是我们输入的账户密码,然后我们通过fetch我们的后端发送请求,通过我们的账户密码来验证,后端对应的路由上的方法接受账户密码后生成我们账户专属的token,方便我们查看我们自己账户的数据,然后用localStorage.setItem来保存我们用户的token。这函数是通过我们的登录的账户密码向后端申请我们账户的token,方便我们调用后端数据。有token才能访问加密数据。

        

// 获取受保护数据 - 使用Bearer Token
async function getProtectedData() {
    // 从localStorage获取token
    const token = localStorage.getItem('authToken');
    
    if (!token) {
        throw new Error('未找到Token,请先登录');
    }
    
    try {
        const response = await fetch(`${API_URL}/protected/data`, {
            headers: {
                'Authorization': `Bearer ${token}`
            }
        });
        
        // 检查Token是否有效
        if (response.status === 401) {
            // Token无效或过期
            localStorage.removeItem('authToken');
            throw new Error('Token已过期,请重新登录');
        }
        
        if (!response.ok) {
            throw new Error('获取数据失败');
        }
        
        return await response.json();
    } catch (error) {
        console.error('请求错误:', error);
        throw error;
    }
}

        这是我们通过loginuser函数获取token后就可以通过const response = await fetch(`${API_URL}/protected/data`, { headers: { 'Authorization': `Bearer ${token}` } });直接访问后端api然后获取加密数据了,比如我们的账户个人信息,我们可以在很多地方使用token。

        

// 在登录按钮事件中使用
loginBtn.addEventListener('click', async () => {
    const username = usernameInput.value;
    const password = passwordInput.value;
    
    try {
        // 调用真实后端API
        const token = await loginUser(username, password);
        
        // 更新UI显示
        tokenDisplay.innerHTML = `<strong>获取的Token:</strong> ${token}`;
        showResponse('登录成功!Token已存储');
        
    } catch (error) {
        showResponse(`登录失败: ${error.message}`, 'error');
    }
});

        我们在登录按钮点击登录的时候添加事件,看我们的后端数据库是否存在我们的账户密码,如果有对应的token说明账户密码存在,如果报错没找到,就登录失败。也就是如果登录成功顺便拿我们的token令牌。

        

// 在获取受保护数据按钮中使用
getProtectedDataBtn.addEventListener('click', async () => {
    try {
        // 使用Bearer Token获取数据
        const data = await getProtectedData();
        showResponse(`受保护数据: ${JSON.stringify(data, null, 2)}`);
        
    } catch (error) {
        showResponse(`获取失败: ${error.message}`, 'error');
    }
});

        

// 模拟受保护的API调用
        function simulateProtectedApiCall(token) {
            // 验证token格式
            if (!token || token.split('.').length !== 3) {
                throw new Error('Invalid token');
            }
            
            // 模拟API响应
            return {
                id: 1,
                userId: 1,
                title: "受保护的数据",
                body: "这是一个需要有效Bearer Token才能访问的数据示例。",
                accessTime: new Date().toISOString()
            };
        }

        这段是函数通过前面登录拿到的token之后,通过判断token的格式,如果token确实是我们设置的格式,也就是说token是对的,我们就返回我们的加密数据。然后点击按钮调用这个函数,就可以显示出我们的加密数据了,和我们在网站登录后查看个人信息一样。

        

// 后端示例(Node.js/Express)
const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();

app.use(express.json());

// 登录端点
app.post('/auth/login', (req, res) => {
    const { username, password } = req.body;
    
    // 1. 验证用户凭证(实际应查询数据库)
    if (username !== 'demo_user' || password !== 'demo_password') {
        return res.status(401).json({ message: '无效凭证' });
    }
    
    // 2. 生成JWT Token
    const token = jwt.sign(
        { userId: '123', username: 'demo_user' }, // 负载(payload)
        'YOUR_SECRET_KEY', // 密钥
        { expiresIn: '1h' } // 有效期
    );
    
    // 3. 返回Token给前端
    res.json({ token });
});

// 受保护的数据端点
app.get('/protected/data', (req, res) => {
    // 1. 获取Authorization头
    const authHeader = req.headers.authorization;
    
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
        return res.status(401).json({ message: '缺少Token' });
    }
    
    const token = authHeader.split(' ')[1];
    
    try {
        // 2. 验证Token
        const decoded = jwt.verify(token, 'YOUR_SECRET_KEY');
        
        // 3. 返回受保护数据
        res.json({
            message: '欢迎访问受保护数据',
            user: decoded.username,
            protectedData: [/* 敏感数据 */]
        });
        
    } catch (err) {
        return res.status(401).json({ message: '无效Token' });
    }
});

        这是后端代码部分。前面的app.post是login发送的请求,通过接受前端发来的账户密码,我们去数据库中查询是否存在,然后验证通过 后生成专属的token密钥返回给前端,前端就可以拿着token密钥来访问保护数据了。

        后面的get接口,是我们在点击显示保护数据按钮之后,我们函数体首先拿到我们登录后存取的localStorge.setItem(token),然后在请求头中'Authorization': `Bearer ${token}`加上这个来告诉后端我们有token可以获取加密数据,然后点击按钮发送后端app.get路由,后端验证发送的token是否和后端的一致,一致则返回json响应体里面是受保护的数据,然后前端在发送命令后修改文本为响应体返回来的数据文本,这个过程就实现了。

        这是登录的时候我们通过token,以及fetch实现了前后端数据的流动,也就是登录的时候验证并且加载出我们的个人信息,还有相关的数据通过get获取都需要token来验证是否可以获取,然后记住通过localStorge.getItem,localStorge.setItem来存储token。