
从XSS净化到OAuth登录Wri.pe安全设计完整清单与自查教程【免费下载链接】open-wripehttps://wri.pe source code项目地址: https://gitcode.com/gh_mirrors/op/open-wripeWri.pe 是一款开源的 Web 个人笔记应用https://wri.pe 的源代码核心能力包括 Markdown 笔记编辑、多端日历视图、页面分享以及 GitHub、Facebook、Evernote、Dropbox 等第三方登录与同步。对于笔记里存着敏感内容的产品来说安全设计不是可选项。本文带你用8 个真实代码点完整拆解 Wri.pe 的安全机制并附一份可直接抄走的自查清单。 Wri.pe 安全设计总览清单先给一张全景表后面逐项展开#安全维度Wri.pe 的做法关键文件1XSS 防护Markdown 渲染后二次净化 链接协议白名单app/models/page.rb2前端转义模板统一escape_htmlapp/assets/javascripts/shared/utils.js.coffee3CSRF 防护protect_from_forgery 失败降级处理app/controllers/application_controller.rb4会话管理session 只存用户 ID登出即重置app/controllers/sessions_controller.rb5OAuth 登录GitHub/Facebook 走 OAuth2Evernote 走 OAuth1.0alib/ghauth.rb、lib/evernote_auth.rb6密钥管理敏感配置独立 YAML按环境加载config/github-sample.yml7数据权限读/写/分享三级权限越权返回 403app/models/page.rb8并发安全lock_version乐观锁冲突返回 409app/controllers/pages_controller.rb️ 深度一XSS 净化——先渲染再消毒最后查户口笔记应用最大的风险是用户输入 Markdown → 渲染成 HTML → 危险标签被浏览器执行。Wri.pe 在 app/models/page.rb 的body_html方法里做了三道防线第一道渲染。用 Redcarpet 把 Markdown 转成 HTML开启lax_html_blocks等选项支持富文本。第二道净化。HTML 交给sanitize库清洗Sanitize.clean(html, Sanitize::Config::RELAXED)依据白名单移除script、onerror等危险节点和属性依赖声明在 Gemfile 中升级时建议同步关注安全公告。第三道链接协议白名单。用 Nokogiri 遍历所有a标签只保留http/https协议的 href其余比如javascript:alert(1)这种直接被降级为span并删掉 href——等于给每个链接查户口。前端也同步转义JS 模板中拼接用户数据前统一走escape_html底层是 lodash 的_.escape见 app/assets/javascripts/shared/utils.js.coffee例如日历面板里插入标题前先转义# app/assets/javascripts/app/calendar_panel.js.coffee li class\page\a href\\##{escape_html(p.key)}/edit\#{escape_html(p.title)}/a/li 自查要点凡是有用户输入 → HTML路径的地方问自己三个问题服务端净化了吗白名单是什么前端拼接转义了吗 深度二CSRF 与会话——给每个请求发防伪贴纸Wri.pe 的控制器全部继承自 app/controllers/application_controller.rb其中两处设计很值得借鉴全局开启 CSRF 防护protect_from_forgery一行代码所有表单和写操作都必须携带合法 token。失败的优雅降级handle_unverified_request抛出的InvalidAuthenticityToken被统一拦截——HTML 请求重定向回首页JSON 请求返回412 Precondition Failed。对单页应用SPA的 AJAX 调用特别友好前端能明确感知token 失效并引导重新登录。会话本身保持极简app/controllers/sessions_controller.rb 中 session 里只存authorized_user_id一个整数用户信息实时查库并校验active?状态。登出时调用reset_session彻底清空sessions_controller.rb避免 session 固定攻击。同时前端每次启动都会向服务端拉取最新的csrf_token用于后续 API 请求。 自查要点会话里是否存了不必要的敏感数据token 校验失败时接口返回是否能让前端做正确处理 深度三OAuth 登录——第三方账号的安全接入Wri.pe 支持四种第三方登录源码分布清晰服务协议授权模块回调控制器GitHubOAuth 2.0lib/ghauth.rbapp/controllers/ghauth_controller.rbFacebookOAuth 2.0lib/fbauth.rbapp/controllers/fbauth_controller.rbEvernoteOAuth 1.0alib/evernote_auth.rbapp/controllers/evernote_auth_controller.rbDropboxOAuth见模型 app/models/dropbox_user.rbapp/controllers/dropbox_auth_controller.rb以 GitHub 为例流程只有两步app/controllers/ghauth_controller.rb发起授权302 跳转到 GitHub 的授权页只申请最小权限scope: user:email——这是 OAuth 安全里最小权限原则的典型示范回调换 token拿code换取 access_token验证用户身份后把user.id写入 session 并跳转首页。两个细节很见功力控制器顶部rescue_from OAuth::Unauthorized授权异常统一重定向回首页不会把堆栈暴露给用户回调中的 token 交换用rescue e兜底失败只记日志 友好提示绝不把 token 或异常细节渲染到页面。密钥管理是 OAuth 安全的另一半client_id/client_secret放在独立 YAML 中且按环境隔离——仓库里只提供 config/github-sample.yml、config/evernote-sample.yml 等模板真实密钥通过 lib/ghauth.rb 里的YAML.load(...)[Rails.env]按当前环境加载。部署时替换模板即可模板文件本身不含任何秘密。 自查要点OAuth 权限范围是否最小化token 是否只出现在日志和内存中密钥是否随环境隔离且模板入库 深度四数据权限与并发——最后一道门即使前面全部做对谁能看什么也不能失守。Wri.pe 在 app/models/page.rb 定义了三级权限permit_read?本人、公开页SHARE_URL或被授权的协作者可读permit_write?/permit_share?本人或显式授予写/分享权限的用户。控制器里 app/controllers/pages_controller.rb 的show/update/destroy都在第一行就检查权限越权直接403 Forbidden先鉴权再干活。并发安全方面页面表带lock_version字段乐观锁更新时若客户端提交的版本号落后于服务端app/controllers/pages_controller.rb直接返回409 Conflict而不是盲目覆盖——多人协作场景下避免后写覆盖先写的数据丢失。另外用户的备份导出链接靠创建时随机生成的 96 位export-key保护app/models/user.rb相当于URL 即凭证无法被枚举猜测。✅ 安全自查教程5 问清单可直接套用到你的项目XSS所有用户输入 → HTML的路径服务端有白名单净化吗前端拼接有统一转义函数吗参考body_html的三道防线CSRF全局开了 forgery 防护吗token 失效时接口返回能驱动前端重新登录吗会话session 里存的最小化吗登出是否reset_session用户状态失效后旧会话是否立刻作废OAuthscope 最小化了吗异常路径会不会泄露 token/堆栈密钥是否入库权限与并发每个数据接口第一行是鉴权吗写操作有版本号或等价机制吗 延伸阅读核心模块路径数据模型与净化逻辑app/models/page.rb权限与会话基类app/controllers/application_controller.rb页面接口鉴权/乐观锁app/controllers/pages_controller.rbOAuth 模块lib/ghauth.rb、lib/fbauth.rb、lib/evernote_auth.rb会话管理app/controllers/sessions_controller.rb依赖声明Gemfile登录功能测试spec/features/Wri.pe 的安全设计没有炫技全是小步到位净化用白名单、授权用最小 scope、鉴权放在接口第一行、密钥按环境隔离。这正是开源项目最值得新手抄作业的地方——每一条防护都有对应的具体代码可以对照学习。【免费下载链接】open-wripehttps://wri.pe source code项目地址: https://gitcode.com/gh_mirrors/op/open-wripe创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考