Files
plugins/GAuthenticator/Plugin.php
chorblack e75f275ef4
Some checks failed
定时更新GitHub源插件 / 自动更新GitHub插件 (push) Has been cancelled
Initial commit
2026-03-07 11:19:25 +08:00

150 lines
6.4 KiB
PHP

<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
* Google Authenticator for Typecho
*
* @package GAuthenticator
* @author WeiCN
* @version 0.0.6
* @link https://cuojue.org/read/Typecho_Google_Authenticator_02.html
*/
class GAuthenticator_Plugin implements Typecho_Plugin_Interface
{
private static $pluginName = 'GAuthenticator';
/**
* 激活插件方法,如果激活失败,直接抛出异常
*
* @access public
* @return void
* @throws Typecho_Plugin_Exception
*/
public static function activate()
{
Helper::addRoute('GAuthenticator', '/GAuthenticator', 'GAuthenticator_Action', 'Action');
Typecho_Plugin::factory('admin/menu.php')->navBar = array(__CLASS__, 'Authenticator_safe');
Typecho_Plugin::factory('admin/common.php')->begin = array(__CLASS__, 'Authenticator_verification');
return _t('当前两步验证还未启用,请进行<a href="options-plugin.php?config=' . self::$pluginName . '">初始化设置</a>');
}
/**
* 禁用插件方法,如果禁用失败,直接抛出异常
*
* @static
* @access public
* @return void
* @throws Typecho_Plugin_Exception
*/
public static function deactivate(){
Helper::removeRoute('GAuthenticator');
}
/**
* 获取插件配置面板
*
* @access public
* @param Typecho_Widget_Helper_Form $form 配置面板
* @return void'
*/
public static function config(Typecho_Widget_Helper_Form $form)
{
$qrurl = 'otpauth://totp/'.urlencode(Helper::options()->title.':'.Typecho_Widget::widget('Widget_User')->mail).'?secret=';
$element = new Typecho_Widget_Helper_Form_Element_Text('SecretKey', NULL, '', _t('SecretKey'), '
安装的时候自动计算密钥,手动修改无效,如需要修改请卸载重新安装或者手动修改数据库<br>
<div style="font-weight: bold; color: #000; text-align: center; display: block;padding: 30px 0 30px 0;font-size: 24px;">
请扫描下面的二维码绑定<br>
<div style="width: 300px; height: 300px; margin: 20px auto; padding: 20px; background-color: #fff"><span id="qrcode"></span></div>
</div>
<script>
window.onload = function () {
// https://github.com/jeromeetienne/jquery-qrcode/
$.getScript("'. Helper::options()->pluginUrl .'/GAuthenticator/jquery.qrcode.min.js", function () {
$("#qrcode").qrcode({width: 300, height: 300, text: "'. $qrurl .'"+$("input[name=SecretKey]").val()});
});
}
</script>');
$form->addInput($element);
$element = new Typecho_Widget_Helper_Form_Element_Text('SecretQRurl', NULL, '', _t('二维码的网址'), '本选项已过时,保留只是为了向下兼容。和上面图片的地址是相同的');
$form->addInput($element);
$element = new Typecho_Widget_Helper_Form_Element_Text('SecretTime', NULL, 2, _t('容差时间'), '允许的容差时间,单位为30秒的倍数,如果这里是2 那么就是 2* 30 sec 一分钟.');
$form->addInput($element);
$element = new Typecho_Widget_Helper_Form_Element_Text('SecretCode', NULL, '', _t('客户端代码'), '输入你APP或者其他什么鬼上面显示的六位数字。<br>用兼容的APP上面的扫描二维码或者手动输入第一行的SecretKey即可生成');
$form->addInput($element);
$element = new Typecho_Widget_Helper_Form_Element_Radio('SecretOn', array('1' => '开启','0' => '关闭'), 0, _t('插件开关'), '这里关掉了,就不需要验证即可登录。');
$form->addInput($element);
}
/**
* 手动保存配置面板
* @param $config array 插件配置
* @param $is_init bool 是否初始化
*/
public static function configHandle($config, $is_init)
{
if ($is_init) {//如果是第一次初始化插件
require_once 'GoogleAuthenticator.php';
$Authenticator = new PHPGangsta_GoogleAuthenticator();//初始化生成类
$config['SecretKey'] = $Authenticator->createSecret();//生成一个随机安全密钥
$config['SecretQRurl'] = 'http://qr.liantu.com/api.php?text='.urlencode('otpauth://totp/'.urlencode(Helper::options()->title.':'.Typecho_Widget::widget('Widget_User')->mail).'?secret='.$config['SecretKey']);//生成安全密钥的二维码网址
}else{
$config_old = Helper::options()->plugin(self::$pluginName);
if(($config['SecretCode']!='' && $config['SecretOn']==1) || $config['SecretOn']==1){//如果启用,并且验证码不为空
require_once 'GoogleAuthenticator.php';
$Authenticator = new PHPGangsta_GoogleAuthenticator();
if($Authenticator->verifyCode($config['SecretKey'], $config['SecretCode'], $config['SecretTime'])){
$config['SecretOn'] = 1;//如果匹配,则启用
}else{
throw new Typecho_Plugin_Exception('两步验证代码校验失败,请重试或选择关闭');
}
}
$config['SecretKey'] = $config_old->SecretKey;//保持初始化SecretKey不被修改
$config['SecretQRurl'] = $config_old->SecretQRurl;//保持初始化SecretQRurl不被修改 过时选项 兼容保留
}
$config['SecretCode'] = '';//每次保存不保存验证码
Helper::configPlugin(self::$pluginName, $config);//保存插件配置
}
/**
* 个人用户的配置面板
*
* @access public
* @param Typecho_Widget_Helper_Form $form
* @return void
*/
public static function personalConfig(Typecho_Widget_Helper_Form $form){}
/**
* 插件实现方法
*
* @access public
* @return void
*/
public static function Authenticator_safe()
{
$config = Helper::options()->plugin(self::$pluginName);
if($config->SecretOn==1){
echo '<span class="message success">'.htmlspecialchars('已启用 Authenticator 验证').'</span>';
}else{
echo '<span class="message error">'.htmlspecialchars('未启用 Authenticator 验证').'</span>';
}
}
public static function Authenticator_verification()
{
if(isset($Authenticator_init))return;
$Authenticator_init = true;
if (!Typecho_Widget::widget('Widget_User')->hasLogin()){
return;//如果没登录则直接返回
}else{
//已经登录就验证
$config = Helper::options()->plugin(self::$pluginName);
if (isset($_SESSION['GAuthenticator'])&&$_SESSION['GAuthenticator']) return;//如果SESSION匹配则直接返回
if (Typecho_Cookie::get('__typecho_GAuthenticator') == md5($config->SecretKey.Typecho_Cookie::getPrefix().Typecho_Widget::widget('Widget_User')->uid)) return;//如果COOKIE匹配则直接返回
if($config->SecretOn==1){
$options = Helper::options();
$request = new Typecho_Request();
require_once 'verification.php';
}else{
return;//如果未开启插件则直接返回
}
}
}
}