关于 c#:Register ISecureDataFormat<AuthenticationTicket> using Autofac

Register ISecureDataFormat<AuthenticationTicket> using Autofac

如何使用 autofac 注册 ISecureDataFormat<AuthenticationTicket>

我尝试用这种方式注册:

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

但我得到了错误:

An error occurred when trying to create a controller of type 'AccountController'. Make sure that the controller has a parameterless public constructor.
....

InnerException":{"Message":"An error has occurred.","ExceptionMessage":"None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'Microsoft.Owin.Security.DataHandler.SecureDataFormat`1[Microsoft.Owin.Security.AuthenticationTicket]' can be invoked with the available services and parameters

AccountController.cs

1
2
3
4
5
6
7
8
public AccountController(ApplicationUserManager _userManager,
                         IAuthenticationManager authenticationManager,
                         ISecureDataFormat<AuthenticationTicket> accessTokenFormat)
{
    this._userManager = _userManager;
    this._authenticationManager = authenticationManager;
    this._accessTokenFormat =  accessTokenFormat;
}

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

安全数据格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#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);
    }
}

身份验证票

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#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; }
    }
}


我想跟进@Cyril 的回答。我们有一个服务器场,它使用机器密钥来保护数据,所以我们的注册,在经历了很多挫折之后,看起来像这样:(我们使用 Autofac 进行注册,所以在这方面它可能看起来有点不同)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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

的简单package器

1
2
3
4
5
6
7
8
9
10
11
12
13
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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);
    }
}

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

您似乎没有为 SecureDataFormat<AuthenticationTicket> 注册所需的服务。您可以像这样注册它们:

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