Initial commit
Some checks failed
定时更新GitHub源插件 / 自动更新GitHub插件 (push) Has been cancelled

This commit is contained in:
chorblack
2026-03-07 11:19:25 +08:00
commit e75f275ef4
4484 changed files with 645480 additions and 0 deletions

195
Sinauth/AuthorizeAction.php Normal file
View File

@@ -0,0 +1,195 @@
<?php
/**
* Sinauth Plugin
*
* @copyright Copyright (c) 2015 jimmy.chaw (http://x3d.cnblogs.com)
* @license GNU General Public License 2.0
*
*/
class Sinauth_AuthorizeAction extends Typecho_Widget implements Widget_Interface_Do
{
private $db;
private $config;
private static $pluginName = 'Sinauth';
private static $tableName = 'users_oauth';
public function __construct($request, $response, $params = NULL)
{
parent::__construct($request, $response, $params);
$this->config = Helper::options()->plugin(self::$pluginName);
$this->db = Typecho_Db::get();
}
public function action(){
//跳转
if (!class_exists('SaeTOAuthV2')) {
require_once 'saetv2.ex.class.php';
}
$saeto_client = new SaeTOAuthV2($this->config->client_id, $this->config->client_secret);
$authorize_url = $saeto_client->getAuthorizeURL($this->config->callback_url, 'code');
$this->response->redirect($authorize_url);
exit;
}
/**
* 授权回调地址
*/
public function callback(){
if(empty($_GET['code'])) {
throw new Typecho_Exception(_t('无效请求!'));
}
//跳转
if (!class_exists('SaeTOAuthV2')) {
require_once 'saetv2.ex.class.php';
}
$saeto_client = new SaeTOAuthV2($this->config->client_id, $this->config->client_secret);
//取access_token
$access_token = $saeto_client->getAccessToken('code', array('code' => trim($_GET['code']), 'redirect_uri' => $this->config->callback_url));
if (empty($access_token) || !is_array($access_token) || empty($access_token['uid'])) {
throw new Typecho_Exception(_t('获取access_token失败请返回重新授权'));
}
$table = $this->db->getPrefix() . self::$tableName;
$query = $this->db->query("SELECT * FROM {$table} WHERE openid='{$access_token['uid']}' AND plateform='sina'");
$users_oauth = $this->db->fetchRow($query);
if (!empty($users_oauth['uid'])) { //该新浪帐号已经绑定了用户
if (Typecho_Widget::widget('Widget_User')->hasLogin()) { /** 直接返回 */
$this->response->redirect(Typecho_Widget::widget('Widget_Options')->index);
} else { //让其直接登陆
$this->setUserLogin($users_oauth['uid']);
if (!Typecho_Widget::widget('Widget_User')->pass('contributor', true)) {
/** 不允许普通用户直接跳转后台 */
$this->response->redirect(Typecho_Widget::widget('Widget_Options')->profileUrl);
} else {
$this->response->redirect(Typecho_Widget::widget('Widget_Options')->adminUrl);
}
}
exit;
}
//该新浪帐号未绑定过
/** 如果已经登录 */
if (Typecho_Widget::widget('Widget_User')->hasLogin()) {
/** 直接绑定 */
$cookieUid = Typecho_Cookie::get('__typecho_uid');
$this->bindOauthUser($cookieUid, $access_token['uid'], 'sina', $access_token['expires_in']);
$this->response->redirect(Typecho_Widget::widget('Widget_Options')->index);
} else {
//取用户信息
$saetc_client = new SaeTClientV2($this->config->client_id, $this->config->client_secret, $access_token['access_token']);
$weibo_user = $saetc_client->show_user_by_id($access_token['uid']);
//创建用户
$uid = $this->registerFromWeiboUser($weibo_user);
if (!$uid) {
throw new Typecho_Exception(_t('创建帐号失败,请联系管理员!'));
}
$this->setUserLogin($uid);
$this->bindOauthUser($uid, $access_token['uid'], 'sina', $access_token['expires_in']);
$this->response->redirect(Typecho_Widget::widget('Widget_Options')->profileUrl);
}
//构造用户帐号
exit;
}
/**
* 根据微博用户信息创建帐号
*/
protected function registerFromWeiboUser(&$weibo_user) {
$hasher = new PasswordHash(8, true);
$generatedPassword = Typecho_Common::randString(7);
//TODO 用户名重复的问题
$uname = $weibo_user['name'];
$i = 0;
if (!Typecho_Widget::widget('Widget_Abstract_Users')->nameExists($uname)) { //用户名存在
echo 'here';
for ($i = 1; $i < 999; $i++) {
echo $i;
if (Typecho_Widget::widget('Widget_Abstract_Users')->nameExists($uname . '_' . $i)) {
$uname = $uname . '_' . $i;
break;
}
}
}
$dataStruct = array(
'name' => $uname,
'mail' => $weibo_user['idstr'] . ($i ? '_' . $i : '') . '@localhost.local',
'screenName'=> $weibo_user['screen_name'] . ($i ? '_' . $i : ''),
'password' => $hasher->HashPassword($generatedPassword),
'created' => time(),
'url' => $weibo_user['url'],
'group' => 'subscriber'
);
$insertId = Typecho_Widget::widget('Widget_Abstract_Users')->insert($dataStruct);
return $insertId;
}
public function nameExists($name)
{
$select = $this->db->select()
->from('table.users')
->where('name = ?', $name)
->limit(1);
$user = $this->db->fetchRow($select);
return $user ? false : true;
}
/**
* 设置用户登陆状态
*/
protected function setUserLogin($uid, $expire = 30243600) {
Typecho_Widget::widget('Widget_User')->simpleLogin($uid);
$authCode = function_exists('openssl_random_pseudo_bytes') ?
bin2hex(openssl_random_pseudo_bytes(16)) : sha1(Typecho_Common::randString(20));
Typecho_Cookie::set('__typecho_uid', $uid, time() + $expire);
Typecho_Cookie::set('__typecho_authCode', Typecho_Common::hash($authCode), time() + $expire);
//更新最后登录时间以及验证码
$this->db->query($this->db
->update('table.users')
->expression('logged', 'activated')
->rows(array('authCode' => $authCode))
->where('uid = ?', $uid));
}
public function bindOauthUser($uid, $openid, $plateform = 'sina', $expires_in = 0) {
$rows = array(
'openid' => $openid,
'uid' => $uid,
'plateform' => $plateform,
'bind_time' => time(),
'expires_in' => $expires_in
);
return $this->db->query($this->db->insert('table.users_oauth')->rows($rows));
}
}

129
Sinauth/Plugin.php Normal file
View File

@@ -0,0 +1,129 @@
<?php
/**
* Sina 微博登陆插件
*
* @package Sinauth
* @author jimmy chaw
* @version 1.0.0 Beta
* @link http://x3d.cnblogs.com
*/
class Sinauth_Plugin implements Typecho_Plugin_Interface
{
private static $pluginName = 'Sinauth';
private static $tableName = 'users_oauth';
/**
* 激活插件方法,如果激活失败,直接抛出异常
*
* @access public
* @return void
* @throws Typecho_Plugin_Exception
*/
public static function activate()
{
$meg = self::install();
Typecho_Plugin::factory('Widget_User')->___sinauthAuthorizeIcon = array('Sinauth_Plugin', 'authorizeIcon');
Helper::addAction('sinauthAuthorize', 'Sinauth_AuthorizeAction');
Helper::addRoute('sinauthAuthorize', '/sinauthAuthorize/', 'Sinauth_AuthorizeAction', 'action');
Helper::addRoute('sinauthCallback', '/sinauthCallback/', 'Sinauth_AuthorizeAction', 'callback');
Helper::addPanel(1, 'Sinauth/panel.php', 'Sinauth', 'Sinauth用户管理', 'administrator');
return _t($meg.'。请进行<a href="options-plugin.php?config='.self::$pluginName.'">初始化设置</a>');
}
public static function install()
{
$installDb = Typecho_Db::get();
$type = array_pop(explode('_',$installDb->getAdapterName()));
$prefix = $installDb->getPrefix();
$oauthTable = $prefix. self::$tableName;
try {
$installDb->query("CREATE TABLE `$oauthTable` (
`moid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`plateform` varchar(45) NOT NULL DEFAULT 'sina',
`uid` int(10) unsigned NOT NULL,
`openid` varchar(80) NOT NULL,
`bind_time` int(10) unsigned NOT NULL,
`expires_in` int(10) unsigned DEFAULT NULL,
`refresh_token` varchar(300) DEFAULT NULL,
PRIMARY KEY (`moid`),
KEY `uid` (`uid`),
KEY `plateform` (`plateform`),
KEY `openid` (`openid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8");
return('表创建成功, 插件已经被激活!');
} catch (Typecho_Db_Exception $e) {
$code = $e->getCode();
if(('Mysql' == $type && (1050||'42S01') == $code)) {
$script = 'SELECT `moid` from `' . $oauthTable . '`';
$installDb->query($script, Typecho_Db::READ);
return '数据表已存在,插件启用成功';
} else {
throw new Typecho_Plugin_Exception('数据表'.$oauthTable.'建立失败,插件启用失败。错误号:'.$code);
}
}
}
//在前台登陆页面增加oauth跳转图标
public static function authorizeIcon() {
return '<a href="' . Helper::options()->index . '/sinauthAuthorize">新浪登陆</a>';
}
/**
* 禁用插件方法,如果禁用失败,直接抛出异常
*
* @static
* @access public
* @return void
* @throws Typecho_Plugin_Exception
*/
public static function deactivate(){
Helper::removeRoute('sinauthAuthorize');
Helper::removeRoute('sinauthCallback');
Helper::removeAction('sinauthAuthorize');
Helper::removePanel(1, 'Sinauth/panel.php');
}
/**
* 获取插件配置面板
*
* @access public
* @param Typecho_Widget_Helper_Form $form 配置面板
* @return void
*/
public static function config(Typecho_Widget_Helper_Form $form)
{
$client_id = new Typecho_Widget_Helper_Form_Element_Text('client_id', NULL,'', _t('App Key'),'请在微博开放平台查看http://open.weibo.com');
$form->addInput($client_id);
$client_secret = new Typecho_Widget_Helper_Form_Element_Text('client_secret', NULL,'', _t('App Secret'),'请在微博开放平台查看http://open.weibo.com');
$form->addInput($client_secret);
$callback_url = new Typecho_Widget_Helper_Form_Element_Text('callback_url', NULL,'http://', _t('回调地址'),'请与微博开放平台中设置一致');
$form->addInput($callback_url);
//$callback_url = new Typecho_Widget_Helper_Form_Element_Text('email_domain', NULL,'v.sina.com', _t('虚拟email后缀'),'创建用户帐号时构造一个虚拟email如uid@v.sina.com');
//$form->addInput($callback_url);
}
/**
* 个人用户的配置面板
*
* @access public
* @param Typecho_Widget_Helper_Form $form
* @return void
*/
public static function personalConfig(Typecho_Widget_Helper_Form $form){
}
}

39
Sinauth/README.md Normal file
View File

@@ -0,0 +1,39 @@
# 新浪OAuth2登陆插件
基于最新新浪sae维护的sdk lib https://github.com/xiaosier/libweibo。
> 修正登录路径、面板兼容和数据库检测问题,更新文档。
实现功能:
* 新用户进入授权流程后,自动创建帐号并登陆
* 已登陆但未绑定过的用户进入授权流程后,会绑定当前帐号
* 已绑定过用户授权直接登陆
* 后台微信授权用户简易列表
安装插件后还需要进行一些设置。
第一步需要设定好微博开放平台的回调地址:
去微博开放平台打开你的应用,切换到“接口管理”|“授权机制”页面看到“OAuth2.0 授权设置”点击编辑设置相应url
授权回调页http://你的域名/sinauthCallback
取消授权回调页http://你的域名/sinauthCancel 这个暂时没有实现,不影响基本使用
建议启用路径重写否则上述url需要稍作调整加上入口文件。
第二步需要在模板中相应地方增加相应链接:
/app_path/usr/themes/default/sidebar.php
```php
<li class="last"><?php $this->user->sinauthAuthorizeIcon(); ?>
```
也可以在后台登陆页面加一个:
/app_path/admin/login.php
```php
<?php echo $user->sinauthAuthorizeIcon(); ?>&bull;
```

78
Sinauth/panel.php Normal file
View File

@@ -0,0 +1,78 @@
<?php
include 'header.php';
include 'menu.php';
?>
<div class="main">
<div class="body container">
<?php include 'page-title.php'; ?>
<div class="container typecho-page-main" role="form">
<div id="MostCacheMain" class="col-mb-12 typecho-list">
<div id="tab-cacheman" class="tab-content">
<div class="typecho-table-wrap">
<table class="typecho-list-table">
<colgroup>
<col width="40%"/>
<col width="20%"/>
<col width="20%"/>
<col width="10%"/>
<col width="10%"/>
</colgroup>
<thead>
<tr>
<th><?php _e('用户'); ?></th>
<th><?php _e('openid'); ?></th>
<th><?php _e('创建时间'); ?> </th>
<th><?php _e('过期时间'); ?> </th>
<th><?php _e('操作'); ?></th>
</tr>
</thead>
<tbody>
<?php $page = isset($request->page) ? $request->page : 1 ; ?>
<?php $users = $db->fetchAll($db->select()->from('table.users_oauth')->join('table.users', 'table.users_oauth.uid=table.users.uid')->page($page, 15)->order('table.users_oauth.bind_time', Typecho_Db::SORT_DESC)); ?>
<?php foreach($users as $user): ?>
<tr class="even" >
<td>
[<?php echo $user['uid']; ?>] <?php echo $user['name']; ?>
</td>
<td>
<?php echo $user['openid']; ?>
</td>
<td>
<?php echo date('Y-m-d H:i:s', $user['bind_time']); ?>
</td>
<td><?php if($user['expires_in']) {echo date('H:i:s', $user['expires_in']);} ?></td>
<td>
-
</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
</div>
<div class="typecho-pager">
<div class="typecho-pager-content">
<ul>
<?php $total = $db->fetchObject($db->select(array('COUNT(uid)' => 'num'))->from('table.users_oauth'))->num; ?>
<?php for($i=1;$i<=ceil($total/15);$i++): ?>
<li class='current'><a href="<?php $options->adminUrl('extending.php?panel=Sinauth%2Fpanel.php&page='.$i); ?>" style= 'cursor:pointer;' title='第 <?php _e($i); ?> 页'> <?php _e($i); ?> </a></li>
<?php endfor; ?>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<?php
include 'copyright.php';
include 'common-js.php';
include 'footer.php';
include 'table-js.php';
?>

3295
Sinauth/saetv2.ex.class.php Normal file

File diff suppressed because it is too large Load Diff