PluggableAuth扩展如何无需展示表单即可接收$_POST隐藏数据实现自动登录
核心根因
HTTP协议的重定向请求不会自动携带原始POST参数,PluggableAuth触发的登录跳转流程会丢弃原始请求的POST数据,所以你在后续认证环节直接拿不到参数是正常现象。
实现方案
你可以通过MediaWiki的钩子在重定向发生前提前拦截并存储POST参数到Session,具体实现步骤如下:
- 第一步:注册两个钩子到你的扩展配置文件(
extension.json):
{ "hooks": { "BeforeInitialize": "MediaWiki\\Extension\\你的扩展类名\\Hooks::onBeforeInitialize", "PluggableAuthAfterLogin": "MediaWiki\\Extension\\你的扩展类名\\Hooks::onPluggableAuthAfterLogin" } }
- 第二步:实现
BeforeInitialize钩子,在请求早期、重定向触发前捕获POST参数存入Session:
public static function onBeforeInitialize( $title, $unused, $output, $user, $request, $mediaWiki ) { // 仅拦截携带指定认证参数的POST请求 if ( $request->wasPosted() && $request->hasVal( '自定义用户名参数名' ) && $request->hasVal( '自定义令牌参数名' ) ) { $session = $request->getSession(); // 存储认证参数,建议加独有的前缀避免和其他扩展/核心参数冲突 $session->set( 'my_auth_username', $request->getVal( '自定义用户名参数名' ) ); $session->set( 'my_auth_token', $request->getVal( '自定义令牌参数名' ) ); // 存储用户原始访问地址,登录完成后直接跳转 $session->set( 'my_auth_redirect_target', $title->getFullURL() ); $session->save(); } return true; }
- 第三步:在你的PluggableAuth认证实现类中,从Session读取参数完成校验,校验后立刻删除敏感参数:
public function authenticate( &$id, &$username, &$realname, &$email, &$errorMsg ) { $session = \RequestContext::getMain()->getRequest()->getSession(); $storedUsername = $session->get( 'my_auth_username' ); $storedToken = $session->get( 'my_auth_token' ); // 执行你的令牌校验逻辑 if ( !$storedUsername || !$this->yourTokenValidateMethod( $storedUsername, $storedToken ) ) { $errorMsg = '认证无效'; return false; } // 校验通过,查询匹配的本地用户 $user = \User::newFromName( $storedUsername ); if ( !$user || $user->getId() === 0 ) { $errorMsg = '用户不存在'; return false; } // 赋值用户信息 $id = $user->getId(); $username = $user->getName(); $realname = $user->getRealName(); $email = $user->getEmail(); // 用完立刻删除Session中的敏感参数,防止重放攻击 $session->remove( 'my_auth_username' ); $session->remove( 'my_auth_token' ); $session->save(); return true; }
- 第四步:实现
PluggableAuthAfterLogin钩子,登录成功后跳转到用户原始访问的页面:
public static function onPluggableAuthAfterLogin( $user, &$redirectUrl ) { $session = \RequestContext::getMain()->getRequest()->getSession(); $targetUrl = $session->get( 'my_auth_redirect_target' ); if ( $targetUrl ) { $redirectUrl = $targetUrl; $session->remove( 'my_auth_redirect_target' ); $session->save(); } return true; }
注意事项
- 该方案不需要修改外部系统的POST提交地址,外部系统依然可以直接把参数提交到用户要访问的目标页面,不需要专门提交到Special:UserLogin
- 自定义Session键必须使用独有的前缀,避免和MediaWiki核心、其他扩展的参数冲突
- 令牌必须设置单次有效,且校验完成后立刻清除Session中的存储内容,防止重放攻击
- 可按需增加请求来源域名校验逻辑,进一步提升安全性
内容的提问来源于stack exchange,提问作者Rafael Kasper
相关产品推荐
相关产品推荐

