• 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有一个专门的属性,就是指定是否要预先构造的话,那不就解决了所有的问题了么?为什么要这样麻烦去做注入呢?

  • 相关阅读:
    [BZOJ 3282] Tree 【LCT】
    [BZOJ 2049] [Sdoi2008] Cave 洞穴勘测 【LCT】
    [BZOJ 1036] [ZJOI2008] 树的统计Count 【Link Cut Tree】
    [HDOJ
    Excel+DDT数据驱动实例
    jenkins+SVN配置
    [转]loadrunner:系统的平均并发用户数和并发数峰值如何估算
    loadrunner:Auto Correlate自动定位瓶颈
    loadrunner:判断是否服务器连接池瓶颈
    利用page_source抓取网页中的URL,进行链接测试
  • 原文地址:https://www.cnblogs.com/chenxizhang/p/1259103.html
Copyright © 2020-2023  润新知