Monday, September 22, 2008

What's wrong with Spring.Net Interceptors?

When I began using of Spring.Net interceptors part of my code stopped working! For example such code:


public class POBlo
{
    private IDataProvider _dataProvider = null;
    // Yes, I know about auto property :)
    protected virtual IDataProvider DataProvider
    {
        get { return _dataProvider; }
        set { _dataProvider = value; }
    }
 
    public virtual void Save (Entity entity)
    {
        // Here we have NullReferenceException :(
        DataProvider.Save (entity);
    }
}

Before I added interceptor all were OK. I could save entity and no exception was occurred.

After some investigation I've found the problem: intercepted target object has right value of this property but proxy object does not expose it!
Finally I opened Spring.Net sources and found the Spring.Proxy.AbstractProxyTypeBuilder's InheritType method the proxies my class:



protected virtual void InheritType(TypeBuilder typeBuilder,
            IProxyMethodBuilder proxyMethodBuilder, Type type, bool declaredMembersOnly)
{
    IDictionary methodMap = new Hashtable();
    IList finalMethods = new ArrayList();
 
    BindingFlags bindingFlags = BindingFlags.Public  BindingFlags.Instance;
    if (declaredMembersOnly)
    {
        bindingFlags = BindingFlags.DeclaredOnly;
    }
 
    // override virtual methods
    MethodInfo[] methods = type.GetMethods(bindingFlags);
    foreach (MethodInfo method in methods)
    {
        if (method.IsVirtual && !method.IsFinal)
        {
            MethodBuilder methodBuilder = proxyMethodBuilder.BuildProxyMethod(method, null);
            ApplyMethodAttributes(methodBuilder, method);
            methodMap[method.Name] = methodBuilder;
        }
    }
    // override virtual properties
    foreach (PropertyInfo property in type.GetProperties(bindingFlags))
    {
        ImplementProperty(typeBuilder, type, property, methodMap);
    }
    // override virtual events
    foreach (EventInfo evt in type.GetEvents(bindingFlags))
    {
        ImplementEvent(typeBuilder, type, evt, methodMap);
    }
}

As you can see, Spring's default implementation creates proxy just for publicly published interfaces of the class. So first obvious solution is to mark all properties "public" instead of "protected". But this is unacceptable because of different reasons: huge reworking and (what is more important) encapsulation violation.

So I've decided to just reimplement this solution. This is quite easy with DI and Spring.Net. Simply follow the steps:
1. Create custom ProxyTypeBuilder.
2. Create custom ProxyFactory
3. Register ProxyFactory in configs.




Create custom ProxyTypeBuilder

Create custom proxy type builder where we define necessary binding flags.



 
using System;
using System.Collections;
using System.Reflection;
using System.Reflection.Emit;
using Spring.Aop;
using Spring.Aop.Framework;
using Spring.Aop.Framework.DynamicProxy;
using Spring.Proxy;

namespace Qulix.Spring.Aop
{
    /// 
    /// Implements proxy type builder that uses inheritance and exposes not only public methods
    /// 
    [CLSCompliant(false)]
    public class CustomInheritanceProxyTypeBuilder : DecoratorAopProxyTypeBuilder
    {
        #region IProxyTypeBuilder Members
        [CLSCompliant(false)]
        protected override void InheritType(TypeBuilder typeBuilder,
                                            IProxyMethodBuilder proxyMethodBuilder, Type type, bool declaredMembersOnly)
        {
            IDictionary methodMap = new Hashtable();
            BindingFlags bindingFlags = BindingFlags.NonPublic  BindingFlags.Public  BindingFlags.Instance;
            if (declaredMembersOnly)
            {
                bindingFlags = BindingFlags.DeclaredOnly;
            }
            // override virtual methods
            MethodInfo[] methods = type.GetMethods(bindingFlags);
            foreach (MethodInfo method in methods)
            {
                if (method.IsVirtual && !method.IsFinal)
                {
                    MethodBuilder methodBuilder = proxyMethodBuilder.BuildProxyMethod(method, null);
                    ApplyMethodAttributes(methodBuilder, method);
                    methodMap[method.Name] = methodBuilder;
                }
            }
            // override virtual properties
            foreach (PropertyInfo property in type.GetProperties(bindingFlags))
            {
                ImplementProperty(typeBuilder, type, property, methodMap);
            }
            // override virtual events
            foreach (EventInfo evt in type.GetEvents(bindingFlags))
            {
                ImplementEvent(typeBuilder, type, evt, methodMap);
            }
        }
        #endregion
    }
}


As you can see I've added extra BindingFlags. This will allow to find and proxy not only public properties and methods.


Create custom proxy factory


Just inherit from one of the implemented Proxy factories and reimplement CreateAopProxy method:



[Serializable]
[CLSCompliant(false)]
public class InheritanceAopProxyFactory : DefaultAopProxyFactory
{
    [CLSCompliant(false)]
    public override IAopProxy CreateAopProxy(AdvisedSupport advisedSupport)
    {
        if (advisedSupport == null)
        {
            throw new AopConfigException("Cannot create IAopProxy with null ProxyConfig");
        }
        if (advisedSupport.Advisors.Length == 0 && advisedSupport.TargetSource == EmptyTargetSource.Empty)
        {
            throw new AopConfigException("Cannot create IAopProxy with no advisors and no target source");
        }
 
        IProxyTypeBuilder typeBuilder = new CustomInheritanceProxyTypeBuilder(advisedSupport);
        Type aopProxy = BuildProxyType(typeBuilder);
        ConstructorInfo constructor = aopProxy.GetConstructor(new Type[] { typeof(IAdvised) });
        return (IAopProxy)constructor.Invoke(new object[] { advisedSupport });
    }
}

Here we just replace creation of ProxyTypeBuilder with our own CustomInheritanceProxyTypeBuilder. Of course, you can parametrize you ProxyFaxtory to accept type of the ProxyTypeBuilder. I do not implement this functionality for simplicity.


Register ProxyFactory in cofig


As last step we need to define what IAopProxyFactory implementation will be used. For this purpose write in the configuration file the following:


 
<object id="IAopProxyFactory" type="Qulix.Spring.Aop.InheritanceAopProxyFactory, Qulix.Spring" />
 

That's it. Now we just need to define the reference to our ProxyFactory implementation. For example:



<object id="POBloProxier" type="Spring.Aop.Framework.AutoProxy.ObjectNameAutoProxyCreator, Spring.Aop">
    <property name="AopProxyFactory" ref="IAopProxyFactory" />
...

I hope this will help you. And you will help me to find easier and more clearer solution.

kick it on DotNetKicks.com
Share this Post:

Facebook
Digg DelIcioUs

Wednesday, September 17, 2008

Security implementation tips

How do you implement security in your ASP.NET application?

I propose to use AOP and interceptors. Short sample.

You have business logic methods like:

public List<Action> GetActions();
public void ExecuteAction(Action action, object data);


And you don't care about security there. You just do your job: create list of all supported actions and return it in GetActions and execute any supported actions in ExecuteAction. Smart, clear and straightforward.

But where is security? In interceptors.

You create interceptor that wraps these two methods. These interceptor knows about allowed actions and has access to such list of actions.

On every execute of GetActions it intersects List of returned actions with list of allowed actions and returns the result of intersection.

On every execute of ExecuteAction it checks whether action is allowed or not.

So you:
1. Have separate security mechanism that works independently.
2. Do not care about security during business logic development.
3. Can split these tasks and divide them between different people.
4. Can use other tips mentioned below :)


And few more tips with security:

1. Always try to separate logic from security as much as possible. This allows you to separate concerns, divide work and allows developers to concentrate on their narrow task.

2. Add possibility to switch off the security. Sometimes it's necessary to test if error occurred because of business logic failure or security failure. It's hard to do if there is no possibility to switch off security. It's not a hard task but it could save time during testing and stabilization.

3. Remove possibility to switch off security from production version. There is a risk that somebody could change your configuration parameter directly or indirectly and in such way perform leverage privileges attack. To avoid this, remove security switch off from production code. But do not delete code! Just use the following:


private bool IsSecurityEnabled
{
    get
    {
#if DEBUG
        return Configuration.IsSecurityEnabled;
#else
        return true;
#endif
    }
}

4. Avoid possibility to delete last administrator. To prevent system from being "unadministrable" add code that will check all delete operation on subject of is there any administrators in the system or last one is deleted. Or select one "Super Administrator" that could be removed from the system.

5. Make security as fast as possible. Create User permissions tickets to save all user allowed actions, cache actions etc. Security should be quick because may be used often.

6. Check security on business logic level. Do not rely on GUI. On UI level you should concentrate on UI as much as possible and do not make security checks where allowed. Or GUI could be even compromised, or UI developer could forget to exclude operation from UI. Moreover, later customer could ask you to write another client based on current application logic level.


To be continued... :)

kick it on DotNetKicks.com




Share this Post:

Facebook


Digg


DelIcioUs

How to be with config files

Often (more precisely - always) we meet the situation where we should store information in configuration files. But when we commit this files to our Version Control System other developers obtain our settings and try to connect to our DB, web service etc.

How to avoid such situation?

Just use templates.

Instead of commiting Web.config, for example, you create Web.config.template that is the copy of Web.config and commit it.

Then every developer during first obtaining of sources renames template file into necessary one and change configuration parameters.

It also helps with build automation - you store config file with the settings that are good for automation server. During every commit (or by schedule - it depends on how you configure you Continuous Integration server) scripts rename files and compilation and unit testing passed successfully.

One tip: templates should contain such default values that allow to build and run tests successfully without changing them in standard environment.

How to implement a task

Here is I tried to describe what I require from my subordinaries for task implementation.

During obtaining the task it's necessary to do the following:
1. Listen attentively.
2. Think
3. Write a letter in which you should indicate the following:
a) Task description
b) Splitting task to subtasks with short description of solution (if non trivial)
c) Estimation of the task with division to subtasks
4. Send e-mail and start implementation (but only after you fix remarks and bugs or write tests)
5. Approve the task (by receiving comments and approval of estimation)

Task is considered as completed if:
1. Unit tests are written
2. Task is implemented completely.
3. Whats New information file is filled
4. Files are commited to Version Control System.
5. If necessary, correspondent paragraph is added to project knowledge base.

Before starting implementation of the task (after writing task description letter to manager), following steps should be performed:
1. Fix all Critical and Major errors.
2. Fix all remarks that are not marked as POSTPONED

I hope this will help you to organize your work.

Please, advice me what could be improved here.

Thanks.