统一身份认证系统
哎,兄弟们,今天咱们聊点实在的。你有没有遇到过这种情况?公司里有好多个系统,每个系统都要单独登录,账号密码还不同,一不小心就记混了,特别烦人。这时候你就想,要是能有一个统一的身份认证系统,所有系统都用同一个账号密码,那多方便啊!
对,这就是所谓的“统一身份认证系统”(简称UAS)。它就像一个总闸门,所有系统都要经过这个闸门来验证用户身份。这样一来,管理起来也方便多了,不用再为每个系统单独维护账号了。
那么问题来了,怎么才能自己动手做一个这样的系统呢?别急,我这就给你讲讲我的经验,还会给你一些具体的代码示例,让你能直接上手试试看。
### 一、什么是统一身份认证系统?
先说说什么是统一身份认证系统吧。简单来说,它是一个集中管理用户身份信息的系统。用户只需要在一次登录后,就能访问所有授权的系统。这种系统通常会使用OAuth2、JWT或者SAML等协议来实现跨系统的身份验证。
比如,你登录了公司的一个内部系统,之后访问另一个系统的时候,就不需要再输入账号密码了,系统会自动通过统一身份认证系统验证你的身份。
但如果你是刚开始做,可能对这些概念不太熟悉,没关系,后面我会一步步带你走。
### 二、技术选型
在开始写代码之前,先得确定用什么技术来搭建这个系统。这里我选择的是**Node.js + Express + MongoDB**,因为它们都是比较常用的工具,而且学习曲线不算太陡。
- **Node.js**:用于后端开发,速度快,适合做API。
- **Express**:基于Node.js的Web框架,可以快速搭建RESTful API。
- **MongoDB**:用来存储用户信息,比如用户名、密码、角色等。
当然,如果你想用其他语言,比如Python或者Java,也可以,不过我这里还是以Node.js为主,毕竟我比较熟。
### 三、项目结构
我们先创建一个项目文件夹,然后初始化一下:
mkdir unified-auth-system
cd unified-auth-system
npm init -y
然后安装依赖:
npm install express mongoose body-parser cors
这里用了`express`做服务器,`mongoose`连接MongoDB,`body-parser`解析请求体,`cors`解决跨域问题。
接下来我们创建几个文件:
- `server.js`:主程序入口。
- `models/User.js`:用户模型。
- `routes/auth.js`:认证相关路由。
- `config/db.js`:数据库连接配置。
### 四、数据库连接配置
在`config/db.js`中,我们连接MongoDB:
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/unified_auth', {
useNewUrlParser: true,
useUnifiedTopology: true
});
mongoose.connection.on('connected', () => {
console.log('Connected to MongoDB');
});
mongoose.connection.on('error', (err) => {
console.error('MongoDB connection error:', err);
});
这个配置很简单,就是连接本地的MongoDB数据库,如果没装的话,可以去官网下载安装。
### 五、用户模型
在`models/User.js`中,定义用户的数据结构:
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
username: { type: String, required: true, unique: true },
password: { type: String, required: true },
role: { type: String, default: 'user' }
});
module.exports = mongoose.model('User', UserSchema);
这里定义了一个用户模型,包含用户名、密码和角色。角色可以是普通用户、管理员等等。
### 六、认证路由
在`routes/auth.js`中,我们写一些认证相关的接口:
const express = require('express');
const router = express.Router();
const User = require('../models/User');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
// 注册接口
router.post('/register', async (req, res) => {
const { username, password } = req.body;
try {
const existingUser = await User.findOne({ username });
if (existingUser) {
return res.status(400).json({ message: '用户名已存在' });
}
const hashedPassword = await bcrypt.hash(password, 10);
const newUser = new User({ username, password: hashedPassword });
await newUser.save();
res.status(201).json({ message: '注册成功' });
} catch (err) {
res.status(500).json({ message: '注册失败', error: err.message });
}
});
// 登录接口
router.post('/login', async (req, res) => {
const { username, password } = req.body;
try {
const user = await User.findOne({ username });
if (!user) {
return res.status(400).json({ message: '用户不存在' });
}
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res.status(400).json({ message: '密码错误' });
}
const token = jwt.sign({ userId: user._id }, 'your-secret-key', { expiresIn: '1h' });
res.json({ token });
} catch (err) {
res.status(500).json({ message: '登录失败', error: err.message });
}
});
module.exports = router;
这段代码实现了注册和登录两个功能。注册时会对用户名进行唯一性检查,并用`bcrypt`加密密码。登录时则会验证用户名和密码是否匹配,如果匹配,就生成一个JWT令牌返回给客户端。
### 七、主程序入口
在`server.js`中,我们启动服务器并引入路由:
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const authRoutes = require('./routes/auth');
const app = express();
app.use(cors());
app.use(bodyParser.json());
app.use('/api/auth', authRoutes);
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
这个文件主要是设置中间件和路由,监听3000端口。
### 八、测试一下
你可以用Postman或者curl来测试一下这两个接口。
- **注册接口**:POST http://localhost:3000/api/auth/register
{
"username": "testuser",
"password": "123456"
}

- **登录接口**:POST http://localhost:3000/api/auth/login
{
"username": "testuser",
"password": "123456"
}
如果一切正常,你会收到一个JWT令牌,这就可以用来作为后续请求的凭证了。
### 九、使用JWT进行权限控制
接下来,我们可以利用JWT来保护其他接口,比如用户信息接口。
在`routes/user.js`中添加:
const express = require('express');
const router = express.Router();
const User = require('../models/User');
const jwt = require('jsonwebtoken');
// 获取用户信息
router.get('/me', verifyToken, async (req, res) => {
try {
const user = await User.findById(req.user.userId);
res.json(user);
} catch (err) {
res.status(500).json({ message: '获取用户信息失败' });
}
});
function verifyToken(req, res, next) {
const token = req.headers['authorization'];
if (!token) {
return res.status(401).json({ message: '没有提供令牌' });
}
jwt.verify(token, 'your-secret-key', (err, decoded) => {
if (err) {
return res.status(401).json({ message: '无效的令牌' });
}
req.user = decoded;
next();
});
}
module.exports = router;
然后在`server.js`中引入这个路由:
const userRoutes = require('./routes/user');
app.use('/api/user', userRoutes);
这样,当你访问 `/api/user/me` 时,就需要带上之前得到的JWT令牌,否则会被拒绝访问。
### 十、扩展功能
上面只是一个基础的统一身份认证系统,你还可以继续扩展很多功能,比如:
- 多种登录方式(邮箱、手机号、第三方登录)
- 用户角色管理(区分管理员、普通用户)
- 日志记录(记录用户操作)
- 密码找回功能
- 使用Redis缓存JWT令牌
比如,如果你要支持第三方登录,可以用OAuth2协议,比如微信、QQ、GitHub等。这部分内容比较复杂,可能需要额外的库和配置,但原理是一样的。
### 十一、总结
今天我们从零开始搭建了一个简单的统一身份认证系统。虽然只是基础版本,但它已经具备了注册、登录、JWT验证、权限控制等功能。
如果你是个刚入门的开发者,这样的项目非常适合练手。它可以帮助你理解用户认证的基本流程,也能让你掌握一些常用技术,比如Node.js、Express、MongoDB、JWT等。
当然,实际生产环境中的系统会更复杂,比如要考虑安全性、高可用、分布式部署等问题。但不管怎样,打好基础最重要。
所以,如果你也在做类似的项目,不妨试试这个思路,看看能不能做出自己的统一身份认证系统。
最后,希望这篇文章对你有帮助,如果你觉得不错,记得点赞、分享哦!咱们下期见!