qwen3-coder:30b.md
· 7.5 KiB · Markdown
原始文件
Here's a complete CRUD REST API implementation using Node.js, Express, MongoDB, and JWT authentication:
```javascript
// server.js
const express = require('express');
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const cors = require('cors');
const app = express();
const PORT = process.env.PORT || 5000;
// Middleware
app.use(cors());
app.use(express.json());
// MongoDB connection
mongoose.connect('mongodb://localhost:27017/crudapi', {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => console.log('Connected to MongoDB'))
.catch((err) => console.error('MongoDB connection error:', err));
// User Schema
const userSchema = new mongoose.Schema({
username: { type: String, required: true, unique: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
}, { timestamps: true });
const User = mongoose.model('User', userSchema);
// Product Schema
const productSchema = new mongoose.Schema({
name: { type: String, required: true },
description: { type: String },
price: { type: Number, required: true },
category: { type: String },
}, { timestamps: true });
const Product = mongoose.model('Product', productSchema);
// JWT secret
const JWT_SECRET = 'your_jwt_secret_key';
// Authentication middleware
const authenticateToken = (req, res, next) => {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) {
return res.status(401).json({ message: 'Access token required' });
}
jwt.verify(token, JWT_SECRET, (err, user) => {
if (err) {
return res.status(403).json({ message: 'Invalid or expired token' });
}
req.user = user;
next();
});
};
// Register endpoint
app.post('/api/register', async (req, res) => {
try {
const { username, email, password } = req.body;
// Check if user already exists
const existingUser = await User.findOne({
$or: [{ email }, { username }]
});
if (existingUser) {
return res.status(400).json({ message: 'User already exists' });
}
// Hash password
const hashedPassword = await bcrypt.hash(password, 12);
// Create user
const user = new User({
username,
email,
password: hashedPassword,
});
await user.save();
res.status(201).json({
message: 'User created successfully',
user: { id: user._id, username: user.username, email: user.email }
});
} catch (error) {
res.status(500).json({ message: 'Server error', error: error.message });
}
});
// Login endpoint
app.post('/api/login', async (req, res) => {
try {
const { email, password } = req.body;
// Find user
const user = await User.findOne({ email });
if (!user) {
return res.status(400).json({ message: 'Invalid credentials' });
}
// Check password
const isPasswordValid = await bcrypt.compare(password, user.password);
if (!isPasswordValid) {
return res.status(400).json({ message: 'Invalid credentials' });
}
// Generate JWT token
const token = jwt.sign(
{ id: user._id, username: user.username },
JWT_SECRET,
{ expiresIn: '24h' }
);
res.json({
message: 'Login successful',
token,
user: { id: user._id, username: user.username, email: user.email }
});
} catch (error) {
res.status(500).json({ message: 'Server error', error: error.message });
}
});
// CRUD endpoints for products
// Create product
app.post('/api/products', authenticateToken, async (req, res) => {
try {
const { name, description, price, category } = req.body;
const product = new Product({
name,
description,
price,
category,
});
await product.save();
res.status(201).json(product);
} catch (error) {
res.status(400).json({ message: 'Error creating product', error: error.message });
}
});
// Get all products
app.get('/api/products', authenticateToken, async (req, res) => {
try {
const products = await Product.find();
res.json(products);
} catch (error) {
res.status(500).json({ message: 'Error fetching products', error: error.message });
}
});
// Get product by ID
app.get('/api/products/:id', authenticateToken, async (req, res) => {
try {
const product = await Product.findById(req.params.id);
if (!product) {
return res.status(404).json({ message: 'Product not found' });
}
res.json(product);
} catch (error) {
res.status(500).json({ message: 'Error fetching product', error: error.message });
}
});
// Update product
app.put('/api/products/:id', authenticateToken, async (req, res) => {
try {
const { name, description, price, category } = req.body;
const product = await Product.findByIdAndUpdate(
req.params.id,
{ name, description, price, category },
{ new: true, runValidators: true }
);
if (!product) {
return res.status(404).json({ message: 'Product not found' });
}
res.json(product);
} catch (error) {
res.status(400).json({ message: 'Error updating product', error: error.message });
}
});
// Delete product
app.delete('/api/products/:id', authenticateToken, async (req, res) => {
try {
const product = await Product.findByIdAndDelete(req.params.id);
if (!product) {
return res.status(404).json({ message: 'Product not found' });
}
res.json({ message: 'Product deleted successfully' });
} catch (error) {
res.status(500).json({ message: 'Error deleting product', error: error.message });
}
});
// Start server
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
```
### Dependencies to Install:
```bash
npm install express mongoose bcryptjs jsonwebtoken cors
```
### API Endpoints:
#### Authentication:
1. **Register** - `POST /api/register`
```json
{
"username": "john_doe",
"email": "[email protected]",
"password": "securepassword"
}
```
2. **Login** - `POST /api/login`
```json
{
"email": "[email protected]",
"password": "securepassword"
}
```
#### Product CRUD Operations:
3. **Create Product** - `POST /api/products`
```
Authorization: Bearer <your-jwt-token>
```
4. **Get All Products** - `GET /api/products`
```
Authorization: Bearer <your-jwt-token>
```
5. **Get Product by ID** - `GET /api/products/:id`
```
Authorization: Bearer <your-jwt-token>
```
6. **Update Product** - `PUT /api/products/:id`
```
Authorization: Bearer <your-jwt-token>
```
7. **Delete Product** - `DELETE /api/products/:id`
```
Authorization: Bearer <your-jwt-token>
```
### Features Implemented:
1. **User Authentication** with JWT tokens
2. **Password Hashing** using bcrypt
3. **CRUD Operations** for products
4. **Input Validation** and error handling
5. **MongoDB Integration** with Mongoose
6. **CORS Support**
7. **Authentication Middleware** protecting routes
### Usage Example:
1. Register a user: `POST /api/register`
2. Login to get token: `POST /api/login`
3. Use the returned JWT token in subsequent requests as:
```
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```
### Security Considerations:
- Passwords are hashed with bcrypt
- JWT tokens have expiration time
- All routes require authentication
- Input validation and error handling
- MongoDB connection security
This implementation provides a solid foundation for a REST API with user authentication and CRUD functionality. You can extend it by adding more validation, pagination, logging, or additional features as needed.
Here's a complete CRUD REST API implementation using Node.js, Express, MongoDB, and JWT authentication:
// server.js
const express = require('express');
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const cors = require('cors');
const app = express();
const PORT = process.env.PORT || 5000;
// Middleware
app.use(cors());
app.use(express.json());
// MongoDB connection
mongoose.connect('mongodb://localhost:27017/crudapi', {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => console.log('Connected to MongoDB'))
.catch((err) => console.error('MongoDB connection error:', err));
// User Schema
const userSchema = new mongoose.Schema({
username: { type: String, required: true, unique: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
}, { timestamps: true });
const User = mongoose.model('User', userSchema);
// Product Schema
const productSchema = new mongoose.Schema({
name: { type: String, required: true },
description: { type: String },
price: { type: Number, required: true },
category: { type: String },
}, { timestamps: true });
const Product = mongoose.model('Product', productSchema);
// JWT secret
const JWT_SECRET = 'your_jwt_secret_key';
// Authentication middleware
const authenticateToken = (req, res, next) => {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) {
return res.status(401).json({ message: 'Access token required' });
}
jwt.verify(token, JWT_SECRET, (err, user) => {
if (err) {
return res.status(403).json({ message: 'Invalid or expired token' });
}
req.user = user;
next();
});
};
// Register endpoint
app.post('/api/register', async (req, res) => {
try {
const { username, email, password } = req.body;
// Check if user already exists
const existingUser = await User.findOne({
$or: [{ email }, { username }]
});
if (existingUser) {
return res.status(400).json({ message: 'User already exists' });
}
// Hash password
const hashedPassword = await bcrypt.hash(password, 12);
// Create user
const user = new User({
username,
email,
password: hashedPassword,
});
await user.save();
res.status(201).json({
message: 'User created successfully',
user: { id: user._id, username: user.username, email: user.email }
});
} catch (error) {
res.status(500).json({ message: 'Server error', error: error.message });
}
});
// Login endpoint
app.post('/api/login', async (req, res) => {
try {
const { email, password } = req.body;
// Find user
const user = await User.findOne({ email });
if (!user) {
return res.status(400).json({ message: 'Invalid credentials' });
}
// Check password
const isPasswordValid = await bcrypt.compare(password, user.password);
if (!isPasswordValid) {
return res.status(400).json({ message: 'Invalid credentials' });
}
// Generate JWT token
const token = jwt.sign(
{ id: user._id, username: user.username },
JWT_SECRET,
{ expiresIn: '24h' }
);
res.json({
message: 'Login successful',
token,
user: { id: user._id, username: user.username, email: user.email }
});
} catch (error) {
res.status(500).json({ message: 'Server error', error: error.message });
}
});
// CRUD endpoints for products
// Create product
app.post('/api/products', authenticateToken, async (req, res) => {
try {
const { name, description, price, category } = req.body;
const product = new Product({
name,
description,
price,
category,
});
await product.save();
res.status(201).json(product);
} catch (error) {
res.status(400).json({ message: 'Error creating product', error: error.message });
}
});
// Get all products
app.get('/api/products', authenticateToken, async (req, res) => {
try {
const products = await Product.find();
res.json(products);
} catch (error) {
res.status(500).json({ message: 'Error fetching products', error: error.message });
}
});
// Get product by ID
app.get('/api/products/:id', authenticateToken, async (req, res) => {
try {
const product = await Product.findById(req.params.id);
if (!product) {
return res.status(404).json({ message: 'Product not found' });
}
res.json(product);
} catch (error) {
res.status(500).json({ message: 'Error fetching product', error: error.message });
}
});
// Update product
app.put('/api/products/:id', authenticateToken, async (req, res) => {
try {
const { name, description, price, category } = req.body;
const product = await Product.findByIdAndUpdate(
req.params.id,
{ name, description, price, category },
{ new: true, runValidators: true }
);
if (!product) {
return res.status(404).json({ message: 'Product not found' });
}
res.json(product);
} catch (error) {
res.status(400).json({ message: 'Error updating product', error: error.message });
}
});
// Delete product
app.delete('/api/products/:id', authenticateToken, async (req, res) => {
try {
const product = await Product.findByIdAndDelete(req.params.id);
if (!product) {
return res.status(404).json({ message: 'Product not found' });
}
res.json({ message: 'Product deleted successfully' });
} catch (error) {
res.status(500).json({ message: 'Error deleting product', error: error.message });
}
});
// Start server
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Dependencies to Install:
npm install express mongoose bcryptjs jsonwebtoken cors
API Endpoints:
Authentication:
-
Register -
POST /api/register
{ "username": "john_doe", "email": "[email protected]", "password": "securepassword" }
-
Login -
POST /api/login
{ "email": "[email protected]", "password": "securepassword" }
Product CRUD Operations:
-
Create Product -
POST /api/products
Authorization: Bearer <your-jwt-token>
-
Get All Products -
GET /api/products
Authorization: Bearer <your-jwt-token>
-
Get Product by ID -
GET /api/products/:id
Authorization: Bearer <your-jwt-token>
-
Update Product -
PUT /api/products/:id
Authorization: Bearer <your-jwt-token>
-
Delete Product -
DELETE /api/products/:id
Authorization: Bearer <your-jwt-token>
Features Implemented:
- User Authentication with JWT tokens
- Password Hashing using bcrypt
- CRUD Operations for products
- Input Validation and error handling
- MongoDB Integration with Mongoose
- CORS Support
- Authentication Middleware protecting routes
Usage Example:
- Register a user:
POST /api/register
- Login to get token:
POST /api/login
- Use the returned JWT token in subsequent requests as:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Security Considerations:
- Passwords are hashed with bcrypt
- JWT tokens have expiration time
- All routes require authentication
- Input validation and error handling
- MongoDB connection security
This implementation provides a solid foundation for a REST API with user authentication and CRUD functionality. You can extend it by adding more validation, pagination, logging, or additional features as needed.