FluorineFx.NET的认证(Authentication )与授权(Authorization)和ASP.NET中的大同小异,核实用户的身份既为认证,授权则是确定一个用户是否有某种执行权限,应用程序可根据用户信息授予和拒绝执行。FluorineFx.NET的认证和授权使用.Net Framework基于角色的安全性的支持。
比如说我们需要自定义一个认证与授权的方案,指定那些远程服务上的那些方法将要被认证或授权以及授权用户角色组等,我们就需要自定义一个LoginCommand并实现ILoginCommand接口或者继承于FluorineFx.Security.GenericLoginCommand(此类实现了ILoginCommand接口)基类。接口定义如下:
1
namespace
FluorineFx.Security
2
{
3
public
interface
ILoginCommand
4
{
5
IPrincipal DoAuthentication(
string
username, Hashtable credentials);
6
bool
DoAuthorization(IPrincipal principal, IList roles);
7
bool
Logout(IPrincipal principal);
8
void
Start();
9
void
Stop();
10
}
11
}
网关通过调用该接口中的方法DoAuthentication()来实现验证,具体的验证规则我们可以自定义(重写方法的实现)。
1
///
<summary>
2
///
自定义 LoginCommand
3
///
</summary>
4
public
class
LoginCommand : GenericLoginCommand
5
{
6
public
override
IPrincipal DoAuthentication(
string
username, Hashtable credentials)
7
{
8
string
password
=
credentials[
"
password
"
]
as
string
;
9
if
(username
==
"
admin
"
&&
password
==
"
123456
"
)
10
{
11
//
用户标识
12
GenericIdentity identity
=
new
GenericIdentity(username);
13
//
角色数组
14
GenericPrincipal principal
=
new
GenericPrincipal(identity,
new
string
[] {
"
admin
"
,
"
privilegeduser
"
});
15
return
principal;
16
}
17
else
18
{
19
return
null
;
20
}
21
}
22
}
如上面代码块,检测用户是不是属于"admin"和"privilegeduser"两个角色组之一,否则则不能通过验证。要实现授权则是通过DoAuthorization()方法来实现,我们同样可以重写实现以满足自己的需求。
除此之外还需要service-config.xml,指定通过那一个LoginCommand来执行认证与授权,以及要被授权的方法和角色组,login-command的class指向自定义的LoginCommand.
<
security
>
<
security-constraint
id
="privileged-users"
>
<
auth-method
>
Login
</
auth-method
>
<
roles
>
<
role
>
admin
</
role
>
<
role
>
privilegeduser
</
role
>
</
roles
>
</
security-constraint
>
<
login-command
class
="FlexDotNet.ServiceLibrary.Authentication.LoginCommand"
server
="asp.net"
/>
</
security
>
要使Flex能够调用认证与授权,同样需要提供一个远程服务接口,并为该接口添加RemotingServiceAttribute描述:
1
namespace
FlexDotNet.ServiceLibrary.Authentication
2
{
3
///
<summary>
4
///
远程服务LoginService
5
///
</summary>
6
[RemotingService]
7
public
class
LoginService
8
{
9
public
LoginService()
10
{ }
11
12
///
<summary>
13
///
登录
14
///
</summary>
15
///
<returns></returns>
16
public
bool
Login(
string
userName,
string
password)
17
{
18
if
(userName
==
"
admin
"
&&
password
==
"
123456
"
)
19
{
20
//
do other
21
return
true
;
22
}
23
else
24
{
25
//
do other
26
return
false
;
27
}
28
}
29
30
///
<summary>
31
///
注销
32
///
</summary>
33
///
<param name="userName">
用户名
</param>
34
///
<returns></returns>
35
public
bool
Logout(
string
userName)
36
{
37
GenericIdentity identity
=
new
GenericIdentity(userName);
38
GenericPrincipal principal
=
new
GenericPrincipal(identity,
new
string
[] {
"
admin
"
,
"
privilegeduser
"
});
39
40
if
(
new
LoginCommand().Logout(principal))
41
return
true
;
42
return
false
;
43
}
44
}
45
}
在Flex或Flash端就可以通过RemoteObject来访问远程对象,Flex的访问配置如下代码块:
<
mx:RemoteObject id
=
"
loginService
"
destination
=
"
login
"
>
<
mx:method name
=
"
Login
"
result
=
"
onLoginResult(event)
"
fault
=
"
onLoginFault(event)
"
/>
</
mx:RemoteObject
>
通过配置RemoteObject指定访问login这个配置的远程服务,服务里配置了一远程方法Login,并分别定义了访问成功和失败的处理函数。上面的RemoteObject访问的目的地为login配置的目的地,详细配置在remoting-config.xml里,如下:
<destination id="login">
<properties>
<source>FlexDotNet.ServiceLibrary.Authentication.LoginService</source>
</properties>
</destination>
FlexDotNet.ServiceLibrary.Authentication.LoginService为自定义的一个远程服务(标记为RemotingService)接口,通过配置访问目的地,Flex远程对象组件利用此目的地通过FluorineFx网关调用远程服务接口方法。
布局Flex界面,模拟登录验证的调用,Flex通过setCredentials()方法请求,详细如下代码块:
private
function Login():
void
{
loginService.logout();
loginService.setCredentials(txtName.text,txtPassword.text);
loginService.Login();
}
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
import mx.utils.ObjectUtil;
import mx.controls.Alert;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
private function Login():void
{
loginService.logout();
loginService.setCredentials(txtName.text,txtPassword.text);
loginService.Login();
}
private function Logout():void
{
loginService.logout();
}
private function onLoginResult(evt:ResultEvent):void
{
var result:Boolean = evt.result as Boolean;
if(result)
Alert.show("登录验证成功");
}
private function onLoginFault(evt:FaultEvent):void
{
Alert.show(ObjectUtil.toString(evt.fault),"登录验证失败");
}
]]>
</mx:Script>
<mx:RemoteObject id="loginService" destination="login">
<mx:method name="Login" result="onLoginResult(event)" fault="onLoginFault(event)"/>
</mx:RemoteObject>
<mx:Panel x="124" y="102" width="250" height="200" layout="absolute" fontSize="12" title="用户登录">
<mx:Label x="19" y="28" text="用户名:"/>
<mx:Label x="19" y="72" text="密 码:"/>
<mx:TextInput x="75" y="26" width="131" id="txtName"/>
<mx:TextInput x="75" y="69" width="131" id="txtPassword" displayAsPassword="true"/>
<mx:HBox x="75" y="107" width="131" height="30">
<mx:Button label="登 录" click="Login()"/>
<mx:Button label="清 空"/>
</mx:HBox>
</mx:Panel>
</mx:Application>