# 简单的门户网站及管理端 **Repository Path**: ccwrt/SimplePortalSite ## Basic Information - **Project Name**: 简单的门户网站及管理端 - **Description**: 基于项目https://gitee.com/wanglonglongjm/PortalSite1修改,添加spring security,功能简单 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 50 - **Forks**: 24 - **Created**: 2021-01-11 - **Last Updated**: 2026-09-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 简单的门户网站及管理端(Simple Portal Site) #### 介绍 基于 PortalSite1 项目修改,原项目地址 。 - 升级了框架版本(Spring Boot 4.x + Java 25),前端以 Vue 3 + Vite 独立工程重构; - 使用 Spring Security 增强后台管理安全性(会话认证、方法级鉴权、CSRF、登录失败锁定、防账号枚举)和可配置性(角色/权限可在管理端维护); - 项目经过简单测试,可能存在其他测试未覆盖到的问题未处理。 [项目演示地址](https://www.wenruitao.top/sps) #### 软件架构 **后端(`SimplePortalSite/`,Maven 工程)** | 依赖 | 用途 | | --- | --- | | Spring Boot 4.1.0(Java 25,war 打包) | 核心框架 | | Spring Data JPA / Hibernate | 数据层(`ddl-auto: update`,首次运行自动建表) | | Spring Security | 认证与授权(Session 会话 + `@PreAuthorize` 方法级权限) | | MySQL Connector/J | 数据库驱动,推荐 MySQL 8.0 及以上版本 | | Jasypt | 配置文件数据库账号/密码加密(PBEWITHHMACSHA512ANDAES_256) | | Log4j2 | 日志(`log4j2-spring.xml`) | | Thumbnailator / Jsoup | 上传图片缩略图生成 / 富文本内容安全清洗 | | screw | 自动生成《数据库结构文档》(中文模板) | | Lombok、commons-lang3/collections4、Validation、Actuator、FreeMarker | 辅助组件 | 构建期插件:Checkstyle(google_checks)、Spotless(google-java-format 自动格式化)、maven-war-plugin、spring-boot-maven-plugin。 **前端(`frontend/`,Vue 3 + Vite 独立工程)** | 依赖 | 用途 | | --- | --- | | Vue 3 + Vue Router 4 | 页面框架与路由(history 模式) | | Element Plus | 组件库(unplugin 按需自动导入) | | Axios | 数据交互(统一封装于 `src/utils/axios.js`,接口集中于 `src/api/index.js`) | | TipTap 3 | 管理端富文本编辑器(`src/components/LazyEditor.vue`,按需懒加载) | | ECharts 6 | 管理端数据看板 | | DOMPurify | 富文本渲染前的 XSS 防护 | | qrcode | 二维码生成 | 数据库首次运行时由 Hibernate 自动建表,并自动初始化权限、角色与管理员账号(见下文"数据初始化")。 #### 项目结构 ``` SimplePortalSite/ # 仓库根目录 ├── SimplePortalSite/ # 后端 Spring Boot 工程 │ ├── src/main/java/com/wrt/sps/ │ │ ├── common/ # 常量(Constants) │ │ ├── config/ # CORS、数据库文档配置与静态资源映射 │ │ ├── entity/ # 通用返回对象(Results / PageResults / BaseEntity) │ │ ├── exception/ # 全局异常处理 │ │ ├── security/ # Spring Security 配置与 UserDetailsService │ │ ├── utils/ # 工具类 │ │ ├── mgt/ # 后台管理(controller/dao/entity/pojo/service/event/listener/task) │ │ └── web/ # 门户网站(controller/dao/service) │ └── src/main/resources/ # application.yml、application-{profile}.yml、log4j2-spring.xml ├── frontend/ # 前端 Vue 3 + Vite 工程 │ ├── src/views/ # 门户页面(首页/新闻/服务/技术/关于等) │ ├── src/views/mgt/ # 管理端页面(登录/看板/文章/用户/角色/改密) │ ├── src/api/ # 接口统一封装(含 types.d.ts 类型说明) │ ├── src/utils/ # axios、认证、权限工具 │ └── src/router/ # 路由与权限守卫 └── db-doc/ # 运行时生成的数据库结构文档(不入库) ``` 后端包命名约定:`*.entity` 领域实体、`*.pojo` 数据传输对象、`*.dao` 数据层、`*.service` 服务层、`*.controller` 接口层,代码均有 javadoc 注释。管理端接口路径以 `/mgt` 开头,门户接口以 `/web` 开头。 #### 功能与接口概览 **门户网站(无需登录,`/web/**` 全部放行)** - `GET /web/queryWriting`:按类型分页查询文章(news 新闻 / service 服务 / tech 技术) - `GET /web/getDetails`:文章详情 - `GET /web/file/{code}`:文章配图(含缩略图)访问 - `GET /`、`/html`:转发到门户首页静态资源 **后台管理端(`/mgt/**` 需登录)** - 认证:`POST /mgt/login`(form 参数 `loginName` / `password`)、`POST /mgt/logout`,基于 Session,全链路 JSON 交互 - 文章管理 `/mgt/writing`:query / detail / save / delete / display(排序) - 用户管理 `/mgt/user`:current(当前用户与权限)/ query / save / delete / disable / checkLoginName / changepwd - 角色管理 `/mgt/role`:query / detail / save / delete / permissions - 图片上传 `/mgt/upload/pic`(jpg/jpeg,单文件 ≤20MB) - 数据看板 `/mgt/statistics`:base / writing_type / system_info(ECharts 图表数据) - 数据库文档 `/mgt/db-doc`:status / generate(需 `user_authority` 权限),启动后 5 秒自动生成一次,文档浏览挂载在 `/mgt/db-doc/**`,复用登录认证 **权限模型** 共 13 个权限标识,粒度到"模块 × 操作": | 模块 | 权限标识 | | --- | --- | | 文章 | `writing_view` `writing_add` `writing_edit` `writing_del` | | 用户 | `user_view` `user_add` `user_edit` `user_del` | | 角色 | `role_view` `role_add` `role_edit` `role_del` | | 系统 | `user_authority`(权限设置,含数据库文档访问) | - 后端各接口以 `@PreAuthorize` 校验,防止水平/垂直越权; - 前端登录后经 `GET /mgt/user/current` 拉取权限列表,路由守卫、菜单与按钮统一按权限显隐(读写权限默认包含模块查看能力); - 登录安全:BCrypt 口令散列;用户不存在/密码错误/账号禁用统一文案并返回剩余次数提示,防止账号枚举;连续失败 5 次锁定账号 30 分钟,记录最后登录 IP 与时间。 **数据初始化** 启动时由三个 `ApplicationRunner`(`PermissionServiceImpl` / `RoleServiceImpl` / `UserServiceImpl`)自动完成: 1. 权限表:按名称比对,仅补插缺失的权限项; 2. 角色表:不存在"管理员"角色则创建,并将全部权限授予该角色; 3. 用户表:不存在 `admin` 账号则创建,初始密码取配置项 `system.default-password`(Jasypt 加密存储,明文不在文档/仓库中公开),已存在则跳过。 **定时任务** - 每日 23:00 清理未使用的上传文件(`UploadFileTask`,执行时间暂写死在代码中,后续计划提供上传文件管理与任务配置界面); - 上传文件在保存文章时通过事件(`UploadFileEvent`)标记为已使用/未使用。 #### 安装教程 1. **准备数据库**:创建 MySQL 数据库 `sps`(可改名,需同步修改配置),表结构与初始数据由系统运行时自动创建。 2. **配置后端**:修改 `src/main/resources/application.yml` 及对应 profile 的配置文件: - 端口默认 `8082`;`application.yml` 默认激活 `prod`(安全默认,避免忘记指定 profile 即以开发配置启动)。本地开发请显式激活 `test`(IDE 运行配置 `.vscode/launch.json` 已注入 `SPRING_PROFILES_ACTIVE=test`,命令行用 `--spring.profiles.active=test`);生产配置 `application-prod.yml` 不入库(在 `src/main/resources/.gitignore` 中排除),需在部署机上按环境创建; - 数据库账号/密码使用 Jasypt 加密为 `ENC(...)` 形式,可运行测试目录下的 `JasyptEncryptTest` 交互式生成; - **运行时必须提供 Jasypt 解密口令**(环境变量 `JASYPT_ENCRYPTOR_PASSWORD` 或启动参数 `--jasypt.encryptor.password=...`):`application.yml` 中所有 `ENC(...)`(数据库账号/密码、`system.default-password`)依赖其解密,口令缺失或错误时应用启动即失败(`system.default-password` 已去除明文兜底,不会回落到弱口令); - CORS 可信源通过 `app.cors.allowed-origins` 配置(逗号分隔,开发环境需包含 `http://localhost:5173`)。 3. **启动后端**: - IDE 直接运行 `src/main/java/com/wrt/sps/SimplePortalSiteApplication.java`; - 或 `mvn package` 打成 war 放入 Tomcat,亦可 `mvn spring-boot:run` 以内置容器运行。 4. **启动前端**(在 `frontend/` 目录): - 开发:`npm install && npm run dev`,Vite 默认 5173 端口,`/mgt`(含 `/mgt/db-doc` 独立代理,不带 SPA 回退)与 `/web` 已代理到 `http://localhost:8082`(见 `vite.config.js`),后台接口基址由 `.env.development` 的 `VITE_API_BASE_URL` 配置; - 部署:`npm run build` 产出 `dist/`,**推荐**独立部署到 Nginx 等 Web 服务器,由 Nginx 反向代理 `/mgt`、`/web` 到后端(生产接口为同源相对路径,见 `.env.production`)。构建同时产出 `.gz` 与 `.br` 预压缩文件,Nginx 需开 `gzip_static on` 与 `brotli_static on`(`ngx_brotli`)消费。 > 注:`SecurityConfig` 采用 fail-closed(未显式放行的路径需认证)。若改为将产物放入 `src/main/webapp` 随 war 发布,须在 `SecurityConfig` 中显式 `permitAll` 静态资源路径(`/`、`/assets/**`、`/favicon.ico`、`/img/**` 等),否则匿名访客将无法加载前端。 5. **生产部署清单**(上线前逐项核对): - 环境变量:`JASYPT_ENCRYPTOR_PASSWORD`(解密口令)、`SPRING_PROFILES_ACTIVE=prod`、`UPLOAD_BASE_PATH`(持久化上传目录,如 `/data/sps/uploads/img`)、`LOG_PATH`(如 `/var/log/sps`)、`DBDOC_OUTPUT_DIR`(可选),以及数据源 `SPRING_DATASOURCE_URL/USERNAME/PASSWORD`(或在 `application-prod.yml` 填 `ENC(...)`); - 首次部署建表:生产 `spring.jpa.hibernate.ddl-auto=validate`,空库首次启动前先以 `--spring.jpa.hibernate.ddl-auto=update` 运行一次自动建表(或预导入 schema),确认建表完成后改回 `validate`; - Nginx:SPA history 回退 `try_files $uri $uri/ /index.html;`;`index.html` 设 `Cache-Control: no-cache`,`/assets/` 因文件名含 hash 可长缓存;建议加 `Content-Security-Policy`(如 `default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; connect-src 'self'`)、`X-Content-Type-Options: nosniff`,并在边缘终结 HTTPS(HSTS 已由后端下发); - 首次登录 `admin` 后立即用"修改密码"更换默认口令; - `run.log`、`application-prod.yml` 均不入库(见 `.gitignore`),部署机上单独维护。 #### 使用说明 1. 门户首页:(或开发环境 ); 2. 管理端入口:(生产环境为部署域名下的 `/mgt/login`); 3. 默认管理员:用户名 `admin`,初始密码见配置项 `system.default-password`,**首次登录后请立即通过"修改密码"更换**; 4. 网站采用响应式布局,移动端显示效果仍在优化中; 5. 管理端"数据看板"查看文章统计与系统信息;具备 `user_authority` 权限的账号可在"数据库文档"中手动重新生成表结构文档(默认 60 分钟冷却)。 #### 参与贡献 1. Fork 本仓库 2. 新建 Feat_xxx 分支 3. 提交代码(提交前建议执行 `mvn spotless:apply` 统一 Java 代码格式) 4. 新建 Pull Request #### 许可证 详见 [LICENSE](./LICENSE)。