仓库源文站点原文


tags: [Vue, Vuetify, Flask, 前端, 后端] title: 设计一个前后端分离的管理系统 last_modified_at: 2023-8-29 slug: vue-flask-nginx-website redirect_from:

- /posts/设计一个前后端分离的管理系统

别看,没有任何价值。

架构

其实下面这个架构很蠢,不如online-clipboard,直接用Flask托管前端build出来的静态文件就行了。而且直接手写SQLite就是纯玩具,不如SQLAlchemy。

前端请求发送给运行于443端口的nginx反向代理服务器,nginx再根据请求路径(以/api/开头的发给后端)分别发送给前端(Vuetify 3,运行于127.0.0.1:8901)或后端(Flask,运行于127.0.0.1:8902),数据库使用SQLite。

使用nginx是为了规避跨域、HTTPS与Cookies问题。

域名为EU.org的永久免费域名,使用Cloudflare作为DNS服务商,DNS解析记录指向内网IP地址。

使用acme.sh自动化HTTPS证书申请,自动申请Let's Encrypt的免费证书并配置nginx。

用户访问时,nginx首先请求http://127.0.0.1:8901,Vuetify根据Vue Router返回RootPath.vue这一组件,其中的TypeScript代码会跳转到首页(MainView.vue)。由于Vue Router中标记本页面需要登录,如果用户未登录,会跳转到登录页面(LoginView.vue),否则继续访问首页。

App.vue中为普通页面加载了一个侧边栏(Sidebar.vue)用于在不同界面间导航。

用户点击登录时,Axios会向后端(https://xxx.xxx.eu.org/api/user/login)发送请求,后端返回JSON格式的响应数据,具体格式见下。

// 正常响应
{
    "result": 0,
    "data": {
        "uid": 12,
        "username": "admin",
        "nickname": "管理员",
        "power": [
            "manage_sv",
            "edit_user"
        ],
        "user_group": [
            "admin"
        ],
        "last_login_ip": "1.2.3.4",
        "email": "123@example.com",
        "preferences": {}
    }
}


// 错误响应
{
    "result": 105, // 错误代码,定义于 Return_Code.py
    "message": "用户名或密码错误" // 错误信息,定义于 Return_Code.py
}

登录成功后,会在浏览器设置两个cookie:一个是session,会话期间有效,用于短时间记录用户信息;另一个是remember_token,十年有效,用于长期保存用户登录状态。这里的用户信息会被Vuex保存,并被用于随后的前端用户信息查询。API的授权验证通过session这一cookie实现。