某莔の异次元空间
登录、评论模块设计与踩坑
更新于:2 年前 标签:Web

又是一番捣鼓折腾,Fix登录评论功能上线了!(暂不支持注册)

当然,过程并非一帆风顺,产生了不少疑问,踩了一些坑。本文记录我在设计这两个模块时的构想和遇到的种种坑。

登录模块

设计构想

起初我把这个模块放在了首页右侧(也就是现在的个性签名位置)。但仔细一想,登录功能除了发评论写留言之外貌似没有其他的用武之地,博客没有必要的登录需求,所以也就没有把这个功能放在显眼位置,只有当用户准备发评论留言的时候才会出现。最后的理想状态是不刷新界面以弹出表单小组件的形式出现,但因为一些设计需要,暂时把路由设置为了 /login

填坑

1、login method

先来写个登录请求,照搬老套路,对表单的用户名密码发出POST请求。可是问题来了,后端接收不到请求的具体内容。在网上爬了多篇文章后,大致弄清了这个问题出现的原因:

归根结底,不管PHPJava亦或是Node.js。想要在后台接收到POST的数据,都需要POST在发送时使用编码格式application/x-www-form-urlencoded。浏览器的原生的<form>表单,如果不设置 enctype 属性,那么最终就会以这种方式提交数据。

然而,Vue.js推荐使用的 HTTP 库axios默认的Content-type设置的为application/json,通过这种方式发送的数据后台无法通过正常方式获取。解决方法是在nuxt.config.jsserverMiddleware属性中加入body-parser中间件:

serverMiddleware: [
    // parse application/json,封装 req.body。
    bodyParser.json(),
    // API middleware
    '~/api/index.js'
]

2、路由跳转

先来设计个admin界面,设定是只有登录者可见,如果未登录用户直接访问 /admin 则要跳转到 /login。根据Nuxt的流程图,需要用到middleware,于是我新建authenticated.js中间件来帮助我完成这部分操作。同样,也需要在nuxt.config.js中进行配置。

router: {
    middleware: 'authenticated'
}

我们先来实现完成跳转的路由。由于SSR的特殊性,在判别服务器请求和客户端请求时需要用到不同的方法:

const path = process.server ? req.originalUrl : route.path
if (path.includes('admin')) {
    redirect('/login')
}

3、路由鉴权

跳转的路由搞定了,剩下就是鉴权了。根据习惯,后端我用了express-session中间件。设定完成过期期限,登录成功时录入session后。回到刚才的middleware判断req.session,问题又来了……

if (process.server) {
    if (req.session.user) {
        let path = req.originalUrl
        if (path.indexOf('admin') > 0) {
            redirect('/login')
        }
    }
}

服务器请求好办,客户端请求上下文中没有req,如何判别登陆状态?

一时没想到什么解决方法,回归官网文档,发现最好的办法是使用Vuex状态树。刚开始有些头皮发麻,感觉牵扯到 Vuex 的项目都会变得很复杂,尝试后感觉条例还算清晰,实现起来并不复杂,判断 session 在store中进行。最终完整的判断逻辑如下(store 部分内容省略):

export default function ({ store, req, redirect, route }) { // {} 引用来自 context
  if (!store.state.authUser) { // 没有登陆的用户全部重定向到登陆界面
    const path = process.server ? req.originalUrl : route.path
    if (path.includes('admin')) {
      redirect('/login')
    }
  }
}

评论模块

效果

如本文下方评论所示

填坑

关于评论的数据库存储,起初的构想是存储在article的表里,每条 article 对应一个 comment,嵌套数组实现,用子文档查询。为了达到高内聚低耦合的设计理念,我改用了新的存储格式,全部存储在新的comment表里。因为从最开始就没使用Mongoose框架,各种手动造轮子,所以在引用的展开上遇到了一些小麻烦。最后给 Mongoose 的 populate() 造了个轮子完美解决。

开源

评论的后端存储结构的演示和转换返回结果已经作为 AraComment 项目在GitHub开源。

总结

好了,博客的开发到此暂时告一段落,返校学习之余,是时候潜水一波准备4个月后的那场日本语能力测试了。

点评一下
Powered By AraComment
快来抢沙发吧~
文章索引