使用Autofac注册ISecureDataFormat <authenticationticket>

时间:2017-04-04 15:55:20

标签: c# asp.net-web-api2 owin autofac

如何使用autofac注册ISecureDataFormat<AuthenticationTicket>

我尝试以这种方式注册:

builder.RegisterType<SecureDataFormat<AuthenticationTicket>>()
       .As<ISecureDataFormat<AuthenticationTicket>>()
       .InstancePerLifetimeScope();

但是我收到了错误:

  

尝试创建类型为&#39; AccountController&#39;的控制器时发生错误。确保控制器具有无参数的公共构造函数。   ....

     

InnerException&#34;:{&#34; Message&#34;:&#34;发生错误。&#34;,&#34; ExceptionMessage&#34;:&#34;没有找到构造函数与&#39; Autofac.Core.Activators.Reflection.DefaultConstructorFinder&#39; on type&#39; Microsoft.Owin.Security.DataHandler.SecureDataFormat`1 [Microsoft.Owin.Security.AuthenticationTicket]&#39;可以使用可用的服务和参数调用

AccountController.cs

public AccountController(ApplicationUserManager _userManager,
                         IAuthenticationManager authenticationManager,
                         ISecureDataFormat<AuthenticationTicket> accessTokenFormat)
{
    this._userManager = _userManager;
    this._authenticationManager = authenticationManager;
    this._accessTokenFormat =  accessTokenFormat;
}

在构造函数中没有ISecureDataFormat<AuthenticationTicket> accessTokenFormat,一切正常。

SecureDataFormat

#region 
Assembly Microsoft.Owin.Security, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
#endregion

using Microsoft.Owin.Security.DataHandler.Encoder;
using Microsoft.Owin.Security.DataHandler.Serializer;
using Microsoft.Owin.Security.DataProtection;

namespace Microsoft.Owin.Security.DataHandler
{
    public class SecureDataFormat<TData> : ISecureDataFormat<TData>
    {
        public SecureDataFormat(IDataSerializer<TData> serializer, IDataProtector protector, ITextEncoder encoder);

        public string Protect(TData data);
        public TData Unprotect(string protectedText);
    }
}

AuhenticationTicket

#region 
Assembly Microsoft.Owin.Security, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
#endregion

using System.Security.Claims;

namespace Microsoft.Owin.Security
{
    public class AuthenticationTicket
    {

        public AuthenticationTicket(ClaimsIdentity identity, AuthenticationProperties properties);

        public ClaimsIdentity Identity { get; }
        public AuthenticationProperties Properties { get; }
    }
}

2 个答案:

答案 0 :(得分:0)

错误消息说明 Autofac 无法创建SecureDataFormat<AuthenticationTicket>的实例,因为它无法找到具有可用服务的构造函数。

您似乎尚未为SecureDataFormat<AuthenticationTicket>注册所需的服务。您可以像这样注册:

builder.RegisterType<ITextEncoder, Base64UrlTextEncoder>();
builder.RegisterType<TicketSerializer>()
       .As<IDataSerializer<AuthenticationTicket>>();
builder.Register(c => new DpapiDataProtectionProvider().Create("ASP.NET Identity"))
       .As<IDataProtector>(); 

答案 1 :(得分:0)

我想跟进@Cyril的回答。我们有一个服务器场,该服务器场使用机器密钥进行数据保护,因此,经过很多挫败之后,我们的注册看起来像这样:(我们正在使用Autofac进行注册,因此在这方面可能看起来有些不同)

builder.RegisterType<Base64UrlTextEncoder>().As<ITextEncoder>().InstancePerLifetimeScope();

builder.RegisterType<TicketSerializer>()
     .As<IDataSerializer<AuthenticationTicket>>()
     .InstancePerLifetimeScope();

builder.Register(c =>
    new MachineKeyDataProtectionProvider().Create(
    typeof(OAuthAuthorizationServerMiddleware).Namespace,
    "Access_Token",
    "v1"))
    .As<IDataProtector>()
    .InstancePerLifetimeScope();

builder.RegisterType<SecureDataFormat<AuthenticationTicket>>()
       .As<ISecureDataFormat<AuthenticationTicket>>()
       .InstancePerLifetimeScope();

MachineKeyDataProtectionProviderMachineKeyDataProtector

的简单包装
public virtual MachineKeyDataProtector Create(params string[] purposes)
{
    return new MachineKeyDataProtector(purposes);
}

public virtual DataProtectionProviderDelegate ToOwinFunction()
{
    return purposes =>
    {
        MachineKeyDataProtector dataProtecter = Create(purposes);
        return new DataProtectionTuple(dataProtecter.Protect, dataProtecter.Unprotect);
    };
}

然后是MachineKeyDataProtector

internal class MachineKeyDataProtector : IDataProtector
{
    private readonly string[] _purposes;

    public MachineKeyDataProtector(params string[] purposes)
    {
        _purposes = purposes;
    }

    public virtual byte[] Protect(byte[] userData)
    {
        return MachineKey.Protect(userData, _purposes);
    }

    public virtual byte[] Unprotect(byte[] protectedData)
    {
        return MachineKey.Unprotect(protectedData, _purposes);
    }
}