PostSharp的AOP设计在.NET Remoting中的应用

在.NET Remoting技术中实现用户的验证和授权并不那么容易,尤其是将其宿主在windows service这样的环境中的时候。大部分时候,我们都需要实现自定义的验证方式。具体来说也不是那么复杂,不外乎是在客户端请求的时候,提交一个相应的凭据(通过CallContext的SetData方法即可),而在服务端(或者准确地说是远程对象中),我们检查CallContext中是否有相应的凭据,并且确认其是否合法等等。

这里的一个关键是

1. 用来传递的凭据信息,如果我们封装为一个类的话,那么应该实现ILogicalThreadAffinative接口,并且可序列化

ok,搞清楚了这个逻辑,那么无外乎就是在远程对象中实现一个方法,叫做ValidateUser,然后根据CallContext中的信息去验证用户的身份,然后在每个方法中调用该ValidateUser方法先。大致如下

public string Helloworld() {

if(ValidateUser()){

return "Hello,world";

}

else

//throw exception here
}

public bool ValidateUser(){

//implement the validate logic

}

等等,这样是不是万事大吉了呢?每个方法里面都需要添加下面的代码,不是吗?

if(ValidateUser()){

//do something actually want to do

}

else

//throw exception here

我们就会想,类似用户验证这样的工作,是否可以统一编写,而无需影响我们方法本身的方法体设计呢?首先我们就会想到Attribute,如果说某些方法需要进行身份验证,那么我们就给它加一个Attribute,这样是不是就更好一些呢?

但关键在于Attribute如何触发一些操作呢?就是说凭什么说Attribute指定了,就可以进行一些操作呢?我们立即又想到了Attribute的构造函数,但相当让人失望的是,该构造函数并不会在方法调用的时候被调用,更不用说是在方法调用之前被调用了。那么Attribute的构造函数到底啥时候被调用呢? 很让人疑惑的是,它在我们用GetCustomerAttribute方法去取得它的实例的时候被调用。

Attribute这条路不通,我们就自然会想到能不能用事件来做呢?但问题在于,我们无法收到方法被调用的所谓事件。

带着这样的疑惑,我找了不少资料,也求教了不少的人。最后我找到的答案是:这种设计就是所谓的AOP:Aspect-oriented programming,有关它的一些介绍,请参考下面的链接

http://en.wikipedia.org/wiki/Aspect-oriented_programming

其中PostSharp是一套比较出名的,也是开源的框架。我利用它做出来如下的效果

 

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;

using PostSharp.Laos;

namespace BankLibrary
{
    public class Account:MarshalByRefObject
    {

        [Authentication]
        public string Helloworld() {

            return "Hello,world";
        }

    }


    [Serializable]
    public class AuthenticationAttribute:OnMethodBoundaryAspect{
        public override void OnEntry(MethodExecutionEventArgs eventArgs)
        {
            if (CallContext.GetData("Credential") == null)
            {
                throw new RemotingException("没有相应的凭据");
            }

            if (!ValidateUser((Credential)CallContext.GetData("Credential")))
            {
                throw new RemotingException("错误的凭据");
            }

            eventArgs.FlowBehavior = FlowBehavior.Continue;
        }

        private bool ValidateUser(Credential credential)
        {
            if (credential.UserName != "chenxizhang" || credential.Password != "password")
                return false;
            return true;
        }
    }

 

    [Serializable]
    public class Credential : ILogicalThreadAffinative
    {
        public string UserName{ get; set; }
        public string Password { get; set; }
    }
}

以上代码要能运行,你必须引用PostSharp.Laos和PostSharp.Public

PostSharp的网站是:

http://www.postsharp.org/

值得一说的是,你可以会担心用户信息传递之间的安全性,这一点,.NET 2.0已经支持对信道加密,所以无需特别设计。

实际上,PostSharp是改变了.NET 程序集的编译行为,你看看下面这个图就会明白了

image

微软的企业库从3.0这个版本开始也支持所谓的策略注入,依赖注入。但相对来说过于复杂了(我个人觉得)。

实际上,我觉得如果Attribute有一个专门的属性,就是指定是否要预先构造的话,那不就解决了所有的问题了么?为什么要这样麻烦去做注入呢?

posted @ 2008-08-03 10:03  陈希章  阅读(861)  评论(1编辑  收藏  举报