Typecho 不改核心代码实现自定义登录、注册功能

写两个主题自定义页面扔主题目录里,然后在后台添加独立页面,而这两个页面就是自己编写的登录、注册功能页面。

登录界面咱们需要的就是一个表单,最少提交两个参数:name和password,至于remember则是记住我的功能,需不需要自己决定。

<form action="" method="post">
<input type="hidden" name="_" value="<?php echo $this->security->getToken($this->request->getRequestUrl());?>">
用户名:<input type="text" name="name">
密码:<input type="password" name="password">
<input type="submit" value="提交">
</form>

这里只是一个最基本的表单功能,要如何美化则靠自己啦,其中_这个参数是表单安全验证所用。
表单写好了,那提交到哪里呢?这里要看自己的需求,因为原版的登录过后,如果没有referer参数,则会跳转到后台,若您更改了后台路径,并且不想让别人知道,那就只能自己编写一个登录动作,然后提交到这里,如果不在意,则直接提交到原版登录动作就行!
要保护后台路径,那么直接在这个文件中编写代码:

// 已登录或不开启注册则跳转首页
if ( $this->user->hasLogin() ) $this->response->redirect($this->options->siteUrl);
// 如果有请求
if ( $this->request->isPost() ) {
  // 验证表单
  $this->security->protect();
  // 如果已经登录
  if ( $this->user->hasLogin() ) $this->response->redirect($this->options->siteUrl);
  // 初始化验证类
  $validator = new Typecho_Validate();
  $validator->addRule('name', 'required', _t('请输入用户名'));
  $validator->addRule('password', 'required', _t('请输入密码'));
  // 验证失败
  if ( $error = $validator->run($this->request->from('name', 'password')) )
     $this->response->redirect($this->options->siteUrl);
  // 验证用户
  $valid = $this->user->login($this->request->name, $this->request->password, false);
  // 验证成功
  if ( $valid ) $this->response->redirect($this->options->siteUrl);
  // 防止穷举, 休眠3秒
  sleep(3);
  // 失败跳转
   $this->response->redirect($this->options->siteUrl);
}

而注册页面也同样,建立一个表单,包含几个参数:name、mail、password、confirm,官方不支持自己输入密码,这里把password和confirm加入就能实现自定义密码了!
同样的,如果需要编写动作代码,则把官方的copy一份,不过其中有一点点小改动。

if ( $this->request->isPost() ) {
    // 表单验证
    $this->security->protect();
    // 如果已登录或未开启注册
    if ( $this->user->hasLogin() || !$this->options->allowRegister ) $this->response->redirect($this->options->siteUrl);
    // 初始化验证类
    $validator = new Typecho_Validate();
        // 加上这行, 初始化一个Users
    $user = $this->widget('Widget_Abstract_Users');
    $validator->addRule('name', 'required', _t('必须填写用户名称'));
    $validator->addRule('name', 'minLength', _t('用户名至少包含2个字符'), 2);
    $validator->addRule('name', 'maxLength', _t('用户名最多包含32个字符'), 32);
    $validator->addRule('name', 'xssCheck', _t('请不要在用户名中使用特殊字符'));
        // 这里有改动, 使用$this是无法调用的
    $validator->addRule('name', array($user, 'nameExists'), _t('用户名已经存在'));
    $validator->addRule('mail', 'required', _t('必须填写电子邮箱'));
        // 这里同上
    $validator->addRule('mail', array($user, 'mailExists'), _t('电子邮箱地址已经存在'));
    $validator->addRule('mail', 'email', _t('电子邮箱格式错误'));
    $validator->addRule('mail', 'maxLength', _t('电子邮箱最多包含200个字符'), 200);
    $validator->addRule('password', 'required', _t('必须填写密码'));
    $validator->addRule('password', 'minLength', _t('为了保证账户安全, 请输入至少八位的密码'), 8);
    $validator->addRule('password', 'maxLength', _t('为了便于记忆, 密码长度请不要超过十八位'), 18);
    $validator->addRule('confirm', 'confirm', _t('两次输入的密码不一致'), 'password');
    // 验证失败
    if ( $error = $validator->run($this->request->from('name', 'password', 'mail', 'confirm')) )
        $this->response->redirect($this->options->siteUrl);
    $hasher = new PasswordHash(8, true);
        // 由于是自定义密码, 所以这行可以注释了
        // $generatedPassword = Typecho_Common::randString(7);
    $dataStruct = array(
        'name' => $this->request->name,
        'mail' => $this->request->mail,
        'screenName' => $this->request->name,
                // 直接获取提交的密码并加密
        'password' => $hasher->HashPassword($this->request->password),
        'created' => $this->options->time,
        'group' => 'subscriber'
    );
        // 初始化一个Register
    $register = $this->widget('Widget_Register');
        // 插入用户数据
    $insertId = $register->insert($dataStruct);
        // 压入堆栈
    $register->db->fetchRow($register->select()->where('uid = ?', $insertId)->limit(1), array($register, 'push'));
        // 登录
    $this->user->login($this->request->name, $this->request->password);
    $this->response->redirect($this->options->siteUrl);
}

好了,代码写完了,把这两个文件扔到主题目录里,然后后台新建两个独立页面,再把登录、注册的链接更改为这两个独立页面地址。