我有一个从 Drupal 页面托管的 Flash 应用程序。Flash 应用程序的某些部分应该可供所有用户使用,但有些部分应该只对登录用户可用。(具体角色无关紧要,只要他们是站点的任何授权用户)。
在 Flash 中,我可以通过屏幕抓取“?q=user”页面来检测用户是否登录,但这非常脆弱。这样做的“正确”方法是什么?如有必要,我可以安装其他模块,但它们需要与 Drupal 6 兼容,而不是 5。
同样,如果当前没有用户登录,我如何获取他们提供给我的用户名和密码并登录(或确定密码错误)?
我有一个从 Drupal 页面托管的 Flash 应用程序。Flash 应用程序的某些部分应该可供所有用户使用,但有些部分应该只对登录用户可用。(具体角色无关紧要,只要他们是站点的任何授权用户)。
在 Flash 中,我可以通过屏幕抓取“?q=user”页面来检测用户是否登录,但这非常脆弱。这样做的“正确”方法是什么?如有必要,我可以安装其他模块,但它们需要与 Drupal 6 兼容,而不是 5。
同样,如果当前没有用户登录,我如何获取他们提供给我的用户名和密码并登录(或确定密码错误)?
您可能想查看类似服务模块的内容。基本上,您希望向您的 Flash 应用程序公开用户服务,因此您可以发送请求(通过 XML-RPC 或您选择的任何实现)以获取诸如“当前登录用户具有什么访问权限”或“登录此用户”之类的信息使用用户名 x 和密码 y" 等...
如果您熟悉模块开发,则可以快速创建自己的模块以获得所需的功能,而无需通过“真正的”Web 服务层。这是一个简单的示例,创建一个名为“myservices”的模块:
<?php
// myservices.info
name = My Services
description = Expose basic services
core = 6.x
<?php
// myservices.module
function myservices_menu() {
$items['myservices/user'] = array(
'title' => 'Get auth',
'page callback' => 'myservices_get_user',
'access arguments' => array('access content'),
);
return $items;
}
function myservices_get_user() {
global $user;
if (in_array('authenticated user', $user->roles) ) {
print 'yes';
} else {
print 'no';
}
}
将这两个文件放在模块目录中的目录“myservices”中,激活它,然后转到http://yourdomain.com/myservices/user
如果您通过了身份验证,它只会返回yes
,如果没有no
,等等...您可以在您的 Flash 应用程序中获取。
我能够使用 Drupal 的“系统”和“用户”服务来做到这一点:
在撰写本文时,AMFPHP 服务还没有移植到 Drupal 6,所以我使用了 XMLRPC。为了使用 ActionScript 中的 XMLRPC,我使用了as3-rpclib的帮助程序库。该库是为 ActionScript2 编写的,因此将它与 Flex3 一起使用需要我对其进行修补,如本页所述(向下滚动页面并搜索“jameshyu”于 2008 年 5 月 10 日发表的评论)。
处理完所有这些先决条件后,您可以检查当前登录的用户(如果有)和/或使用如下代码登录用户。
这是实际实现登录的模块:
package
{
import com.ak33m.rpc.xmlrpc.XMLRPCObject;
import flash.events.*;
import flash.net.*;
import mx.collections.ItemResponder;
import mx.rpc.AsyncToken;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
public class DrupalLogin
{
private var _api:XMLRPCObject;
public function DrupalLogin( url:String )
{
_api = new XMLRPCObject();
_api.endpoint = url;
_api.destination = "";
}
public function set LoginResult( fn:Function ):void {_handleLoginResult = fn; }
public function set CheckResult( fn:Function ):void {_handleCheckResult = fn; }
public function set LogoutResult( fn:Function ):void {_handleLogoutResult = fn; }
public function get User():String { return _user; }
public function set TraceResult( fn:Function ):void {_handleTrace = fn; }
private var _handleLoginResult:Function;
private var _handleCheckResult:Function;
private var _handleLogoutResult:Function;
private var _handleTrace:Function;
private function onTrace( st:String ):void
{
_handleTrace(st);
}
private var _firstCheckDone:Boolean = false;
private var _loggedIn:Boolean = false;
// The logged-in user's ID (if any)
private var _user:String = "";
// *****************************************
// doLogin
// *****************************************
// Function doLogin kicks off the process.
public function doLogin( user:String, pwd:String ):void
{
onTrace( "******************* doLogin ********************" );
if( !_firstCheckDone )
{
_handleLoginResult( false, "ALWAYS CALL doCheck() FIRST TO SEE IF YOU NEED TO LOG IN OR NOT" );
return;
}
if( _loggedIn )
{
_handleLoginResult( true, "YOU ARE ALREADY LOGGED IN" );
return;
}
var token:AsyncToken = _api.call( "user.login", _sid, user, pwd );
var tresponder:ItemResponder = new ItemResponder(this.onLoginInfo,this.onLoginFault);
token.addResponder(tresponder);
}
private function onLoginInfo (event:ResultEvent,token:Object = null):void
{
onTrace( "... got onLoginInfo" );
_user = event.result.user.name;
_loggedIn = true;
_handleLoginResult( true, "logged in ok" );
}
private function onLoginFault (event:FaultEvent, token:Object=null):void
{
onTrace( " got onLoginFault" );
_loggedIn = false;
_handleLoginResult( false, "Fault: " + event.fault.faultString + " -- " + event.fault.faultCode);
}
// *****************************************
// doLogout
// *****************************************
public function doLogout():void
{
onTrace( "******************* doLogout ********************" );
if( !_firstCheckDone )
{
_handleLogoutResult( false, "ALWAYS CALL doCheck() FIRST TO SEE IF YOU ARE ABLE TO LOG OUT OR NOT" );
return;
}
if( !_loggedIn )
{
_handleLogoutResult( true, "YOU ARE ALREADY LOGGED OUT" );
return;
}
var token:AsyncToken = _api.call( "user.logout", _sid );
var tresponder:ItemResponder = new ItemResponder(this.onLogoutInfo,this.onLogoutFault);
token.addResponder(tresponder);
}
private function onLogoutInfo (event:ResultEvent,token:Object = null):void
{
onTrace( "got onLogoutInfo" );
_loggedIn = false;
_handleLogoutResult( true, "logged out ok" );
}
private function onLogoutFault (event:FaultEvent, token:Object=null):void
{
onTrace( "got onLogoutFault" );
_loggedIn = false;
_handleLogoutResult( false, "Fault: " + event.fault.faultString + " -- " + event.fault.faultCode);
}
// *****************************************
// doCheckLogin
// *****************************************
private var _sid:String;
public function doCheckLogin():void
{
onTrace( "******************* doCheckLogin ********************" );
var token:AsyncToken = _api.call( "system.connect" );
var tresponder:ItemResponder = new ItemResponder(this.onCheckInfo,this.onCheckFault);
token.addResponder(tresponder);
}
private function onCheckInfo (event:ResultEvent,token:Object = null):void
{
onTrace( "got onCheckInfo" );
_user = event.result.user.name;
_sid = event.result.user.sid;
var roles:Object = event.result.user.roles;
_loggedIn = false;
for( var i:int=0; i<10; i++ )
{
var tmp:String = roles[i.toString()];
if( tmp == "authenticated user" )
_loggedIn = true;
}
trace( "user = " + _user + ", sid=" + _sid + ", loggedIn=" + _loggedIn );
_firstCheckDone = true;
_handleCheckResult( _loggedIn, _loggedIn?("Currently logged in as " + _user):"Not logged in yet" );
}
private function onCheckFault (event:FaultEvent, token:Object=null):void
{
onTrace( "got onCheckFault" );
_handleCheckResult( false, "Fault: " + event.fault.faultString + " -- " + event.fault.faultCode);
}
}
}
这是一个使用它的例子:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script source="LoginExample.as" />
<mx:Button id="btnGoodLogin" click="btnGoodLogin_onClick()" label="Good Login" enabled="true" y="28"/>
<mx:Button id="btnBadLogin" click="btnBadLogin_onClick()" label="Bad Login" enabled="true" y="28" x="112"/>
<mx:Button id="btnLogout" click="btnLogout_onClick()" label="Logout" enabled="true" y="28" x="219"/>
<mx:Button id="btnCheck" click="btnCheck_onClick()" label="Check" enabled="true" y="28" x="325"/>
<mx:Text id="txtResult" y="58" width="263"/>
</mx:Application>
import flash.events.*;
import flash.net.*;
private var _login:DrupalLogin;
private function setup():void
{
if( _login==null )
{
var url:String = "http://myserver/mydrupal?q=services/xmlrpc";
_login = new DrupalLogin(url);
_login.CheckResult = handleCheckResult;
_login.LoginResult = handleLoginResult;
_login.LogoutResult = handleLogoutResult;
_login.TraceResult = handleTraceResult;
}
}
private function btnGoodLogin_onClick():void
{
setup();
_login.doLogin( "goodname", "goodpwd" );
}
private function btnBadLogin_onClick():void
{
setup();
_login.doLogin( "badname", "badpwd" );
}
private function btnLogout_onClick():void
{
setup();
_login.doLogout();
}
private function btnCheck_onClick():void
{
setup();
_login.doCheckLogin();
}
private function showResult( result:String):void
{
trace( "showResult: " + result );
txtResult.text = result;
}
private function handleTraceResult( text:String ):void
{
trace( text );
}
private function handleCheckResult( loggedIn:Boolean, txt:String="" ):void
{
if( txt != "" )
txt = " (" + txt + ")";
if( loggedIn )
showResult( "ALREADY LOGGED IN AS " + _login.User + txt);
else
showResult( "NOT LOGGED IN YET" + txt );
}
private function handleLoginResult( loggedIn:Boolean, txt:String="" ):void
{
if( txt != "" )
txt = " (" + txt + ")";
if( loggedIn )
showResult( "LOGIN ATTEMPT SUCCEEDED" + txt);
else
showResult( "LOGIN ATTEMPT FAILED" + txt );
}
private function handleLogoutResult( loggedOut:Boolean, txt:String="" ):void
{
if( txt != "" )
txt = " (" + txt + ")";
if( loggedOut )
showResult( "LOGOUT ATTEMPT SUCCEEDED" + txt );
else
showResult( "LOGOUT ATTEMPT FAILED" + txt);
}
我知道这距离这篇文章最初的发布还有很长的路要走,但如果你仍然对此感兴趣并且从未花时间研究它,我想出了如何通过 Flash 文档成功处理登录。(就此而言,它是嵌入式的或外部的。)它甚至不需要在系统上安装 AMFPHP。(这很好,因为我上次检查了 AMFPHP 所依赖的服务模块还没有推荐状态。)
我在这里设置了一个演示页面:AS3 Login Demo Page
你可以登录和注销,它会检测你是否已经登录。它仍在进行中,但你需要的大部分东西都已经为你准备好了。
如果您想查看文档并想要一份源代码的副本,所有这些都可以在此处获得:www.andrewnprice.com
我希望这会有所帮助。我应该在下周的某个时间对该演示进行更新,所以如果你想要我在帖子中提到的其他一些功能,请回来查看。