Typecho 前台登陆的正确打开方式

快点击屏幕顶部或者右下角的 体验一下新的外观设置面板吧~面板底部靠左的按钮即可用于前台登陆。

现在许多主题都使用 PJAX 或者其他技术让整个站点变成了一个单页应用,主要目的是让浏览体验更加连贯。但是 Typecho 毕竟是比较传统的程序,某些 API 是缺乏的(Wordpress 有 REST API),许多东西还是要靠登陆后台完成,例如回复读者评论,总免不了要去登陆页面溜达一圈,有点烦人;为了安全性,也不建议将后台路径暴露出来。

我去年写了一篇Typecho 前台登录、Gist 页面上线,在页面上仿照 Typecho 的 admin.php 添加一个 form 来实现前台登陆,效果不错。但是后来发现 PJAX 切换页面后就不行了,需要刷新一下才能登陆……不过也没管了。

在 VOID 进入第三版之际我想把这个功能加回来,研究后发现其实很简单……Typecho 给每个页面分配的 loginAction 都不同,因此如果希望在某页面登陆后跳转回当前页面,loginAction 需要与页面链接、referer 相匹配。

如果 PJAX 的容器不包含 form 元素,那么切换页面后 loginAction 与 referer 都还是老的,因此处理时只需要检测页面是否经过了 PJAX 跳转,如果跳转了,那么这两个参数就要更新一下。更新也很简单,发起一个 AJAX 后台请求一下当前页面,从返回的 HTML 里把新的 loginAction 挑出来,并且把 referer 设置成当前页面。

以下是简单的代码说明。form 元素依旧与之前相同,并加上一个 id 方便区分:

<form action="<?php $this->options->loginAction(); ?>" id="login-form" method="post" name="login" role="form">
  <input type="text" name="name" autocomplete="username" placeholder="请输入用户名" required/>
  <input type="password" name="password" autocomplete="current-password" placeholder="请输入密码" required/>
  <input type="hidden" name="referer" value="<?php 
    if($this->is('index')) $this->options->siteUrl();
    else $this->permalink();
  ?>">
  
  <button class="btn btn-normal" type="submit">登录</button>                          
</form>

前台在 PJAX 完成时添加一个标志记录一下:

$(document).on('pjax:complete', function () {
  $('form#login-form').addClass('need-refresh');
});

然后在合适的时候(比如唤起登陆框时)执行以下更新代码:

if ($('#login-form').hasClass('need-refresh')) {
  $.get({
    url: location.href,
    success: function (data) {
      $('form#login-form').attr('action', $(data).find('form#login-form').attr('action'));
      $('form#login-form').removeClass('need-refresh');
    },
    error: function () {
      alert('请求登陆参数错误。请在刷新后尝试登陆。');
      setTimeout(function () {
        location.reload();
      }, 1000);
    }
  });
}

当然你可以写一些 CSS 来提示用户当前在请求新的登陆参数,需要稍等一下。比如:

form#login-form.need-refresh {
  opacity: 0.5;
}

上面的方法每次请求都要重载整个页面,给服务端带来了额外负担。经评论区提示,可改用 POST 请求当前页面地址,并在后端针对响应,免去执行其他无用代码。例如:

$.ajax({
  type: 'POST',
  url: window.location.href,
  data: {action: 'getLoginAction'},
  success: function (data) {
    $('form#loggin-form').attr('action', data);
    $('form#loggin-form').removeClass('need-refresh');
  },
  error: function () {
    alert('请求登陆参数错误。请在刷新后尝试登陆。');
    setTimeout(function () {
      location.reload();
    }, 1000);
  }
});

注意这里不要使用 GET 请求,因为参数不同生成的 loginAction 也不同,GET 请求不方便随意带参数。在后端主题代码的入口处(例如 header.php 或者 head.php 顶部)添加:

if (isset($_POST['action'])) {
  if ($_POST['action'] == 'getLoginAction') {
    echo $this->options->loginAction;
    exit;
  }
}

这也勉强算是 VOID 开发笔记的一篇吧……就酱。

添加新评论

本站现已启用评论投票,被点踩过多的评论将自动折叠。与本文无关评论请发留言板。请不要水评论,谢谢。

已有 16 条评论

好久没来了,好看了不少……

前台登陆对于个人博客我感觉不是很必要,不过管理起文章评论来感觉确实方便一些。

但是 Type­cho 毕竟是比较传统的程序,某些 API 是缺乏的(Word­press 有 REST API)

每次看到这就想吐槽typecho的接口(嘛 不过毕竟是小社区 ),有些文档没写的还是翻翻源码才行。不过这毕竟想开发的还是会去翻一翻的,毕竟代码也不多?(

引用忘了换行。。。强迫症表示在后台帮改一下

已经改了~

文档这方面,我真是羡慕 WordPress 开发者……当然,看看源码也是好的,可以作为学习资源。

现在这个排版真是爱了,这是什么神仙主题。

感谢大佬表扬~ 话说你那边关站维护了,是在憋大招吗?

Lesun Lesun 回复 @熊猫小A
0 0

哈哈,没有憋什么大招,这段时间比较忙,是真的在维护。。

期待回归~

大佬你好,如果我使用 Ajax 前台登陆,每次用 ajax 请求当前页面获得的 loginAction 地址为啥和直接刷新获得的不同。

这个地址是会改变的,否则就没意义了。Typecho 的具体处理我没有深究,也许是每个地址在一段时间内有效吧。

yiny yiny 回复 @yiny
0 0

找到原因了,改用 POST 请求即可,如果是 GET 则不能带参数。有一种更简单的实现方式。
在 header.php 头加入如下。

if (isset($_POST['action']) and $_POST['action']){
  echo $this->options->loginAction;
  exit;
}

只要 POST 的 data 带入 action 就可以直接返回当前的 action 地址,无需在解析。

原理是一样的啊,你这样可以少传输一点数据就是了。

Mark 一下,暑假写 Pure 2.0 的时候说不定有用,感谢大佬~
话说这图标是 Font-Awesome 吗,为什么返回顶部不用图标呢

是 Font Awesome 的子集。以前 VOID 没有图标,包括搜索按钮什么的都是用 CSS 画的,所以有些地方没有改。

测试了一下,黑夜模式很棒

熊猫小A 熊猫小A 回复 @心灵博客
0 0

谢谢喜欢。