Managing Credentials Within ChannelFactory Cache

281 views Asked by At

I've converted an old library to .NET Core and implemented a ChannelFactory caching solution. The services which it connects to require basic authorization added to each request's HTTP headers. The header is added to each request with a ClientMesageInspector. Because the ClientMessageInspector is immutable once the first channel is created the ChannelFactory cache stores each instance in a dictionary with a key based on the ChannelFactory endpoint, username and password combination. Also, due to the overhead of creating the ChannelFactory I do not dispose of them. My concern is the usernames and passwords are kept in memory within the dictionary keys and also within the ClientMesageInspector added to the ChannelFactory. Is there a better solution to this? I've already asked the question over on the dotnet/wcf GitHub page and wanted to open it up to a bigger audience.

Thanks in advance.

Bob.

1

There are 1 answers

0
Bobmonga On BEST ANSWER

I had some great help from the dotnet/wcf team via my question. After some discussion I ended up using AsyncLocal variables to store the username and password.

In the wrapper class we have the two AsyncLocal variables which are set via the constructor.

internal static AsyncLocal<string> Username = new AsyncLocal<string>();
internal static AsyncLocal<string> Password = new AsyncLocal<string>();

public WCFWrapper(string username, string password) : this()
{
    Username.Value = username;
    Password.Value = password;
}

In the IClientMessageInspector BeforeSendRequest method, we simply use the variables.

public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
    HttpRequestMessageProperty httpRequestProperty = new HttpRequestMessageProperty();
    httpRequestProperty.Headers[System.Net.HttpRequestHeader.Authorization] =  
        "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(WCFWrapper.Username.Value + ":" + WCFWrapper.Password.Value));
    request.Properties[HttpRequestMessageProperty.Name] = httpRequestProperty;

    return null;
}