ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

公开还是私密?StoryBooks 文章可见性权限控制的 3 层实现原理

公开还是私密?StoryBooks 文章可见性权限控制的 3 层实现原理 公开还是私密StoryBooks 文章可见性权限控制的 3 层实现原理【免费下载链接】storybooksNode.js app with Google OAuth项目地址: https://gitcode.com/gh_mirrors/st/storybooksStoryBooks 是一个基于 Node.js Express MongoDB 构建的个人故事分享应用支持 Google OAuth 登录。它的核心特性是用户发布的每一篇文章Story都可以自由选择公开public或私密private可见状态。这个看似简单的功能实际上贯穿了数据层、查询层和访问控制层三个层面。本文带你完整拆解这套文章可见性权限控制的实现原理。权限控制全景3 层防线一图看懂层级位置职责第 1 层 · 数据层models/Story.js用status字段定义并约束文章的公开/私密属性第 2 层 · 查询层routes/stories.js列表、用户主页、搜索接口默认只返回公开文章第 3 层 · 访问控制层routes/stories.js单篇文章详情按作者身份 可见状态双重判断越权一律返回 404三层各司其职数据层保证状态合法查询层保证默认只给公开的访问控制层兜底就算拿到链接也看不了私密的。这种纵深防御的思路是很多 Node.js 权限控制方案的通用范式。第 1 层数据层用枚举字段约束可见状态打开 models/Story.js故事的 Mongoose Schema 中有一个关键的status字段status: { type: String, default: public, enum: [public, private], }这里有两个设计细节值得新手学习默认公开default: public让文章默认面向所有人符合社交类应用鼓励分享的产品逻辑枚举约束enum: [public, private]确保数据库里只会出现这两种合法值。如果有人尝试提交status: hiddenMongoose 的校验器会直接拒绝从根源上杜绝非法状态。另外每条故事都通过user字段ObjectId 引用关联到 models/User.js 中的作者这正是后面判断作者身份的基础。用户在前端如何选择状态呢在 views/stories/add.hbs 的新增表单里有一个下拉框提供 Public / Private 两个选项提交后由后端统一写入数据库前端无法绕过校验随意传值。第 2 层查询层列表与搜索默认只返回公开文章第二层防线在 routes/stories.js 的三个读取类接口中它们的查询条件里都带有status: public全部文章列表GET /storiesStory.find({ status: public })只把公开文章展示在首页列表中某位用户的故事GET /stories/user/:userIdStory.find({ user: userId, status: public })访问别人的主页时也只会看到其公开内容按标题搜索GET /stories/search/:queryStory.find({ title: RegExp, status: public })私密文章对搜索完全不可见。 对比一下 routes/index.js 中的个人 Dashboard 接口它查询的是Story.find({ user: req.user.id })没有status 过滤——所以作者在 Dashboard 里能同时看到自己公开和私密的全部文章状态徽章会直接显示在表格中。这正是自己看全部别人只看公开的产品设计落点。这一层的意义在于私密文章从一开始就不会出现在任何列表或搜索结果里普通用户根本无从得知它们的存在。第 3 层访问控制层绕过列表直接访问时的兜底判断光靠列表过滤还不够——如果有人猜到了某篇文章的 URL/stories/:id直接访问会怎样第三层防线就在单篇详情接口中routes/stories.jsif (story.user._id ! req.user.id story.status private) { res.render(error/404) }逻辑非常清晰用一个且关系做了双重判断是文章作者本人→ 放行无论文章是公开还是私密不是作者且文章是私密→ 返回 404 页面。这里有个值得注意的安全细节越权访问私密文章时应用返回的是404不存在而不是 403无权访问。对外不暴露这篇私密文章确实存在这一信息属于权限控制中的常见防探测技巧。同文件中的编辑、修改、删除三个写接口GET /stories/edit/:id、PUT /stories/:id、DELETE /stories/:id则执行更严格的身份校验只有story.user与当前登录用户一致时才允许操作否则直接重定向回文章列表。也就是说别人连你的私密文章改一个字都做不到。前置条件所有接口都建立在已登录之上值得一提的是上述所有文章路由都挂了 middleware/auth.js 中的ensureAuth中间件ensureAuth: function (req, res, next) { if (req.isAuthenticated()) return next() else res.redirect(/) }未登录用户会被重定向到登录页由 config/passport.js 配置的 Google OAuth 流程完成认证。所以可见性权限是建立在身份可信之上的——这正是完整权限链的第一块基石。前端的小心思让权限看得见权限控制不只是后端的事前端也配合得恰到好处views/stories/add.hbs发布时提供 Public / Private 下拉选择默认选中公开views/dashboard.hbsDashboard 表格中有独立的 Status 列用徽章直观标注每篇文章的状态helpers/hbs.js 中的editIcon辅助函数只有当前登录用户是作者本人时页面才会渲染编辑按钮——前端隐藏入口后端再做拦截双保险。总结新手可以抄作业的 3 层范式回顾 StoryBooks 的文章可见性权限控制本质上是一套非常经典的三层范式数据层枚举字段定义状态 默认值 校验器保证状态合法查询层面向他人的查询统一附加status: public过滤私密内容天然不可见访问控制层详情接口按作者 or 公开做最终裁决写操作仅限本人越权返回 404 防探测。再叠加 OAuth 登录 Session 身份认证作为前提就构成了一个完整、简洁且易于理解的权限体系。项目入口在 app.js配置文件位于 config/db.js 与 config/passport.js整体代码量不大非常适合新手通读学习。如果你正在做自己的博客、笔记或内容社区应用这套枚举状态 查询过滤 作者校验的方案几乎可以原样搬走使用。【免费下载链接】storybooksNode.js app with Google OAuth项目地址: https://gitcode.com/gh_mirrors/st/storybooks创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表