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

  • 相关阅读:
    宿主机( win 7 系统) ping 虚拟机VMware( cent os 6.6 ) 出现“请求超时”或者“无法访问目标主机”的解决方法
    Java实现 LeetCode 23 合并K个排序链表
    Java实现 LeetCode 23 合并K个排序链表
    Java实现 LeetCode 23 合并K个排序链表
    Java实现 LeetCode 22 括号生成
    Java实现 LeetCode 22 括号生成
    Java实现 LeetCode 22 括号生成
    Java实现 LeetCode 21 合并两个有序链表
    Java实现 LeetCode 21 合并两个有序链表
    Java实现 LeetCode 21 合并两个有序链表
  • 原文地址:https://www.cnblogs.com/chenxizhang/p/1259103.html
Copyright © 2011-2022 走看看