Compare commits

...

14 Commits

Author SHA1 Message Date
wzj
f64e7b18b0 docker支持 2025-09-06 09:50:47 +08:00
wzj
9c92be13d9 修复验证码bug 2025-06-16 12:53:16 +08:00
wzj
89cb0af79a 修复验证码bug 2025-06-16 12:50:36 +08:00
wzj
9cbb6b022c 修复验证码bug 2025-06-16 12:49:25 +08:00
wzj
375816df87 修复验证码bug 2025-06-16 12:04:59 +08:00
wzj
2b36de569d 调整描述 2025-06-15 10:13:19 +08:00
wzj
21142a6104 调整描述 2025-06-15 10:10:18 +08:00
wzj
f3a2f05b1c 调整描述 2025-06-15 10:08:25 +08:00
wzj
722d88a017 开源协议 2025-06-15 09:54:09 +08:00
wzj
179400f9ed 调整应用信息 2025-06-15 09:27:35 +08:00
wzj
cc2b18ba80 显示证书创建人 2025-06-15 09:23:42 +08:00
wzj
fc3801f0f2 显示证书创建人 2025-06-15 09:21:44 +08:00
wzj
c2ca546955 添加配置模板 2025-06-15 08:57:10 +08:00
wzj
f711ca8280 Remove .env and add to gitignore 2025-06-15 08:51:36 +08:00
12 changed files with 220 additions and 31 deletions

View File

@ -12,7 +12,7 @@ DB_PORT=3306 # 数据库端口MySQL默认3306
# [应用配置]
APP_HOST=0.0.0.0 # 应用监听地址0.0.0.0表示允许所有IP访问
APP_PORT=9875 # 应用监听端口
APP_PORT=5000 # 应用监听端口
DEBUG=False # 调试模式(生产环境必须关闭)
APP_DOMAIN=localhost # 应用对外域名(用于邮件链接生成)
APP_PROTOCOL=http # 应用协议http或https

BIN
.gitignore vendored

Binary file not shown.

33
Dockerfile Normal file
View File

@ -0,0 +1,33 @@
# 使用官方 Python 镜像Debian 系)
FROM python:3.8-slim
# 设置时区为北京时间
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 安装系统依赖(仅运行时需要的库)
RUN apt-get update && \
apt-get install -y --no-install-recommends \
libjpeg-dev \
zlib1g-dev \
libtiff5-dev \
libfreetype6-dev \
liblcms2-dev \
libwebp-dev \
&& rm -rf /var/lib/apt/lists/*
# 设置工作目录
WORKDIR /app
# 复制依赖文件并安装
COPY requirements.txt .
RUN pip install --no-cache-dir -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
# 复制应用代码
COPY . .
# 暴露端口
EXPOSE 5000
# 运行命令
CMD ["python", "app.py"]

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) [2025] [jeazw]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

131
README.md Normal file
View File

@ -0,0 +1,131 @@
# 自签名证书管理系统
![Python Version](https://img.shields.io/badge/Python-3.7+-blue)
![Flask](https://img.shields.io/badge/Flask-2.0+-green)
<div align="center">
<img src="./static/favicon.svg" alt="qilin SSL Logo" width="150">
<p>一款易用的自签证书管理系统</p>
</div>
一个基于Flask的Web应用程序用于管理自签名证书颁发机构(CA)和证书。
**全部代码由DeepSeek生成**
## 功能特性
- **证书颁发机构管理**
- 创建和管理自签名CA
- 查看CA详情及相关证书
- 生成证书吊销列表(CRL)
- 导出CA捆绑包(证书+私钥)
- **证书管理**
- 颁发由您的CA签名的证书
- 管理主题备用名称(SAN)
- 吊销和续订证书
- 支持多种格式导出(PKCS#12, PEM, CRT+KEY)
- **用户管理**
- 带邮箱验证的用户注册
- 基于角色的访问控制(管理员/普通用户)
- 密码策略强制执行
## 系统截图
<div style="display: flex; justify-content: space-between; margin: 20px 0;">
<img src="screenshots/index.png" alt="首页" style="width: 32%; border: 1px solid #ddd; border-radius: 4px;">
<img src="screenshots/ca_detail.png" alt="CA详情页" style="width: 32%; border: 1px solid #ddd; border-radius: 4px;">
<img src="screenshots/cert_detail.png" alt="证书详情页" style="width: 32%; border: 1px solid #ddd; border-radius: 4px;">
</div>
## demo测试账号
https://ssl.liuyan.wang
admin/123456
## 系统要求
- Python 3.7+
- MySQL/MariaDB数据库
- OpenSSL
- 所需Python包(见`requirements.txt`)
## 安装指南
1. 克隆仓库:
```bash
git clone https://github.com/yourusername/certificate-management-system.git
cd certificate-management-system
```
2. 创建并激活虚拟环境:
```bash
python -m venv venv
source venv/bin/activate # Windows系统: venv\Scripts\activate
```
3. 安装依赖:
```bash
pip install -r requirements.txt
```
4. 基于`.env.example`创建`.env`文件并配置:
```ini
DB_HOST=localhost # 数据库服务器IP地址或域名
DB_PORT=3306 # 数据库端口MySQL默认3306
DB_NAME=cert_management # 数据库名称
DB_USER=root # 数据库用户名
DB_PASSWORD=yourpassword # 数据库密码(生产环境建议使用强密码)
SECRET_KEY=your-secret-key-here # Flask应用加密密钥生产环境必须修改建议使用32位随机字符串
MAIL_SERVER=smtp.example.com # SMTP服务器地址QQ邮箱为smtp.qq.com
MAIL_PORT=587 # SMTP端口QQ邮箱SSL端口为465
MAIL_USE_TLS=True # 是否使用SSL加密QQ邮箱必须开启
MAIL_USERNAME=your-email@example.com # 发件邮箱地址
MAIL_PASSWORD=your-email-password # SMTP授权码非邮箱密码
APP_DOMAIN=localhost # 应用对外域名(用于邮件链接生成)
APP_PROTOCOL=https # 应用协议http或https
```
## 运行应用
```bash
python app.py
```
默认情况下,应用将在`http://localhost:5000`可用。
## 使用说明
1. 注册新账户(若注册开放)或直接登录
2. 管理员可:
- 创建和管理CA
- 颁发证书
- 查看系统所有证书
3. 普通用户可:
- 使用自己创建的CA颁发证书
- 管理自己的证书
## API接口
- `/`: 仪表盘
- `/login`, `/logout`: 认证相关
- `/register`: 用户注册
- `/cas`: CA管理
- `/certificates`: 证书管理
- `/download/<filename>`: 文件下载
## 安全注意事项
- 请始终在安全环境中运行本系统
- 妥善保管您的`.env`文件
- 定期备份证书存储和数据库
- 生产环境建议使用HTTPS
## 开源许可
[MIT License](LICENSE)
## 贡献指南
欢迎提交Pull Request。重大改动请先创建Issue讨论。
## 技术支持
如有问题请提交GitHub仓库Issue。

43
app.py
View File

@ -198,37 +198,24 @@ def get_db_connection():
return None
def generate_captcha():
# 生成6位随机验证码
captcha_code = ''.join(random.choices(string.ascii_uppercase + string.digits, k=6))
conn = get_db_connection()
if conn:
try:
cursor = conn.cursor()
# 清除旧的验证码
cursor.execute("DELETE FROM captcha WHERE created_at < NOW() - INTERVAL 10 MINUTE")
# 插入新验证码
cursor.execute("INSERT INTO captcha (code) VALUES (%s)", (captcha_code,))
conn.commit()
return captcha_code
except Error as e:
print(f"Database error: {e}")
return None
finally:
if conn.is_connected():
cursor.close()
conn.close()
return None
def verify_captcha(user_input):
"""验证用户输入的验证码是否正确只验证最新的4位验证码"""
conn = get_db_connection()
if conn:
try:
cursor = conn.cursor()
cursor.execute("SELECT code FROM captcha ORDER BY created_at DESC LIMIT 1")
# 只查询最新的验证码确保是4位的
cursor.execute("""
SELECT code FROM captcha
WHERE LENGTH(code) = 4 -- 只查询4位验证码
ORDER BY created_at DESC
LIMIT 1
""")
result = cursor.fetchone()
if result and user_input.upper() == result[0]:
# 验证成功后删除已使用的验证码
cursor.execute("DELETE FROM captcha WHERE code = %s", (result[0],))
conn.commit()
return True
return False
except Error as e:
@ -859,9 +846,9 @@ def register():
conn.close()
# 生成新验证码
captcha_code = generate_captcha()
captcha_url = url_for('captcha') # 使用图片验证码
return render_template('register.html',
captcha_code=captcha_code,
captcha_url=captcha_url, # 前端改为显示图片验证码
registration_open=current_app.config['REGISTRATION_OPEN'],
email_required=current_app.config['EMAIL_VERIFICATION_REQUIRED'])
@ -1081,8 +1068,8 @@ def login():
cursor.close()
conn.close()
captcha_code = generate_captcha()
return render_template('login.html', captcha_code=captcha_code)
captcha_url = url_for('captcha')
return render_template('login.html', captcha_url=captcha_url)
@app.route('/logout')

13
docker-compose.yml Normal file
View File

@ -0,0 +1,13 @@
version: '3.8'
services:
tiku_bm:
image: certmanager:latest
container_name: certmanager
ports:
- "5002:5000"
environment:
- FLASK_ENV=production
volumes:
- ./data:/app/data
restart: unless-stopped

BIN
screenshots/ca_detail.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
screenshots/cert_detail.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
screenshots/index.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

View File

@ -138,6 +138,7 @@
<th>通用名</th>
<th>状态</th>
<th>有效期至</th>
<th>创建者</th>
<th>创建时间</th>
<th class="pe-4">操作</th>
</tr>
@ -167,6 +168,7 @@
{% endif %}
</td>
<td>{{ cert.expires_at.strftime('%Y-%m-%d') }}</td>
<td>{{ get_username(cert.created_by) }}</td>
<td>{{ cert.created_at.strftime('%Y-%m-%d') }}</td>
<td class="pe-4">
<div class="btn-group btn-group-sm">

View File

@ -34,6 +34,7 @@
<th>CA机构</th>
<th>状态</th>
<th>有效期至</th>
<th>创建者</th>
<th>创建时间</th>
<th class="pe-4">操作</th>
</tr>
@ -67,6 +68,7 @@
{% endif %}
</td>
<td>{{ cert.expires_at.strftime('%Y-%m-%d') }}</td>
<td>{{ get_username(cert.created_by) }}</td>
<td>{{ cert.created_at.strftime('%Y-%m-%d') }}</td>
<td class="pe-4">
<div class="btn-group btn-group-sm">