iT邦幫忙

2024 iThome 鐵人賽

DAY 10
0
自我挑戰組

利用 node.js/express 架設網站系列 第 10

Day-10 用戶驗證與授權

  • 分享至 

  • xImage
  •  

1.理解驗證與授權的區別
2.實現用戶驗證(Authentication)
3.實現授權(Authorization)

驗證與授權的區別

  • 在學習如何實現用戶驗證和授權前,首先需要了解它們的區別:
    • 驗證:是識別用戶身份的過程。例如,當一個用戶登錄時,你需要驗證他是否為系統中的合法用戶。
    • 授權:在驗證用戶身份後,你還需要確定該用戶可以執行哪些操作,例如普通用戶只能查看自己的數據,而管理員可以管理所有用戶。

使用 JWT 實現用戶驗證

  • JWT(JSON Web Token) 是一種廣泛使用的身份驗證方法,適合 RESTful API,因為它在服務器無需保存會話狀態,並且可以將身份信息包含在令牌中。

安裝 JWT 所需的庫

npm install jsonwebtoken bcryptjs

設置用戶註冊與登錄
範例:用戶註冊

const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');

// 註冊用戶
app.post('/register', async (req, res) => {
    const { username, password } = req.body;

    // 加密密碼
    const hashedPassword = await bcrypt.hash(password, 10);

    // 保存用戶資料庫
    // 假設我們有一個 User 模型
    const user = await User.create({ username, password: hashedPassword });

    res.status(201).json({ message: 'User registered successfully' });
});

範例:用戶登入

app.post('/login', async (req, res) => {
    const { username, password } = req.body;

    // 查找用戶
    const user = await User.findOne({ where: { username } });
    if (!user) {
        return res.status(401).json({ message: 'Invalid username or password' });
    }

    // 驗證密碼
    const isPasswordValid = await bcrypt.compare(password, user.password);
    if (!isPasswordValid) {
        return res.status(401).json({ message: 'Invalid username or password' });
    }

    // 生成 JWT
    const token = jwt.sign({ id: user.id, username: user.username }, 'secretKey', { expiresIn: '1h' });

    res.status(200).json({ message: 'Login successful', token });
});

驗證 JWT
為了保護需要授權的路由,你可以創建一個中介軟體來驗證請求中是否包含有效的 JWT。
範例:

const authenticateToken = (req, res, next) => {
    const token = req.headers['authorization']?.split(' ')[1]; // Authorization: Bearer <token>

    if (!token) {
        return res.status(401).json({ message: 'Access token is missing or invalid' });
    }

    jwt.verify(token, 'secretKey', (err, user) => {
        if (err) return res.status(403).json({ message: 'Invalid token' });
        req.user = user;
        next();
    });
};

// 保護的路由
app.get('/profile', authenticateToken, (req, res) => {
    res.status(200).json({ message: `Welcome, ${req.user.username}` });
});

這段代碼會在進行 API 請求時檢查是否包含有效的 JWT,並允許只有已驗證的用戶訪問受保護的路由。

實現用戶授權

授權是在驗證後進一步控制用戶操作權限的步驟。通常你會根據用戶角色來設置授權邏輯。
設置用戶角色
可以在用戶數據模型中添加一個 role 字段來標識用戶的身份類型,如 admin 或 user。

const User = sequelize.define('User', {
    username: DataTypes.STRING,
    password: DataTypes.STRING,
    role: {
        type: DataTypes.STRING,
        defaultValue: 'user' // 默認為普通用戶
    }
});

創建授權中介軟體
根據用戶角色控制其訪問不同路由的權限。可以創建一個授權中介軟體來檢查用戶的角色。

const authorizeRoles = (roles) => {
    return (req, res, next) => {
        if (!roles.includes(req.user.role)) {
            return res.status(403).json({ message: 'Access denied' });
        }
        next();
    };
};

// 僅限管理員訪問的路由
app.delete('/admin/users/:id', authenticateToken, authorizeRoles(['admin']), async (req, res) => {
    const userId = req.params.id;
    await User.destroy({ where: { id: userId } });
    res.status(200).json({ message: 'User deleted' });
});

這段代碼會檢查用戶的角色,只有角色為 admin 的用戶才能刪除其他用戶。


上一篇
Day-09 資料庫整合與進階查詢操作
下一篇
Day-11 文件上傳與處理
系列文
利用 node.js/express 架設網站30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言