Add CreateProtector convenience extension method
This commit is contained in:
parent
6637cb264f
commit
ab18f52e98
|
|
@ -2,6 +2,8 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.AspNet.Cryptography;
|
||||
|
||||
namespace Microsoft.AspNet.Security.DataProtection
|
||||
{
|
||||
|
|
@ -21,6 +23,37 @@ namespace Microsoft.AspNet.Security.DataProtection
|
|||
?? new TimeLimitedDataProtector(protector.CreateProtector(TimeLimitedDataProtector.PurposeString));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an IDataProtector given an array of purposes.
|
||||
/// </summary>
|
||||
/// <param name="provider">The provider from which to generate the purpose chain.</param>
|
||||
/// <param name="purposes">
|
||||
/// This is a convenience method used for chaining several purposes together
|
||||
/// in a single call to CreateProtector. See the documentation of
|
||||
/// IDataProtectionProvider.CreateProtector for more information.
|
||||
/// </param>
|
||||
/// <returns>An IDataProtector tied to the provided purpose chain.</returns>
|
||||
public static IDataProtector CreateProtector([NotNull] this IDataProtectionProvider provider, params string[] purposes)
|
||||
{
|
||||
if (purposes == null || purposes.Length == 0)
|
||||
{
|
||||
throw new ArgumentException(Resources.DataProtectionExtensions_NullPurposesArray, nameof(purposes));
|
||||
}
|
||||
|
||||
IDataProtectionProvider retVal = provider;
|
||||
foreach (string purpose in purposes)
|
||||
{
|
||||
if (String.IsNullOrEmpty(purpose))
|
||||
{
|
||||
throw new ArgumentException(Resources.DataProtectionExtensions_NullPurposesArray, nameof(purposes));
|
||||
}
|
||||
retVal = retVal.CreateProtector(purpose) ?? CryptoUtil.Fail<IDataProtector>("CreateProtector returned null.");
|
||||
}
|
||||
|
||||
Debug.Assert(retVal is IDataProtector); // CreateProtector is supposed to return an instance of this interface
|
||||
return (IDataProtector)retVal;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cryptographically protects a piece of plaintext data.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -186,6 +186,22 @@ namespace Microsoft.AspNet.Security.DataProtection
|
|||
return string.Format(CultureInfo.CurrentCulture, GetString("TimeLimitedDataProtector_PayloadExpired"), p0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The purposes array cannot be null or empty and cannot contain null or empty elements.
|
||||
/// </summary>
|
||||
internal static string DataProtectionExtensions_NullPurposesArray
|
||||
{
|
||||
get { return GetString("DataProtectionExtensions_NullPurposesArray"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The purposes array cannot be null or empty and cannot contain null or empty elements.
|
||||
/// </summary>
|
||||
internal static string FormatDataProtectionExtensions_NullPurposesArray()
|
||||
{
|
||||
return GetString("DataProtectionExtensions_NullPurposesArray");
|
||||
}
|
||||
|
||||
private static string GetString(string name, params string[] formatterNames)
|
||||
{
|
||||
var value = _resourceManager.GetString(name);
|
||||
|
|
|
|||
|
|
@ -150,4 +150,7 @@
|
|||
<data name="TimeLimitedDataProtector_PayloadExpired" xml:space="preserve">
|
||||
<value>The payload expired at {0}.</value>
|
||||
</data>
|
||||
<data name="DataProtectionExtensions_NullPurposesArray" xml:space="preserve">
|
||||
<value>The purposes array cannot be null or empty and cannot contain null or empty elements.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -39,6 +39,43 @@ namespace Microsoft.AspNet.Security.DataProtection.Test
|
|||
Assert.Same(innerProtector, timeLimitedProtector.InnerProtector);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(new object[] { null })]
|
||||
[InlineData(new object[] { new string[0] })]
|
||||
[InlineData(new object[] { new string[] { null } })]
|
||||
[InlineData(new object[] { new string[] { "the next value is bad", "" } })]
|
||||
public void CreateProtector_Chained_FailureCases(string[] purposes)
|
||||
{
|
||||
// Arrange
|
||||
var mockProtector = new Mock<IDataProtector>();
|
||||
mockProtector.Setup(o => o.CreateProtector(It.IsAny<string>())).Returns(mockProtector.Object);
|
||||
var provider = mockProtector.Object;
|
||||
|
||||
// Act & assert
|
||||
var ex = Assert.Throws<ArgumentException>(() => provider.CreateProtector(purposes));
|
||||
ex.AssertMessage("purposes", Resources.DataProtectionExtensions_NullPurposesArray);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateProtector_Chained_SuccessCase()
|
||||
{
|
||||
// Arrange
|
||||
var finalExpectedProtector = new Mock<IDataProtector>().Object;
|
||||
|
||||
var thirdMock = new Mock<IDataProtector>();
|
||||
thirdMock.Setup(o => o.CreateProtector("third")).Returns(finalExpectedProtector);
|
||||
var secondMock = new Mock<IDataProtector>();
|
||||
secondMock.Setup(o => o.CreateProtector("second")).Returns(thirdMock.Object);
|
||||
var firstMock = new Mock<IDataProtector>();
|
||||
firstMock.Setup(o => o.CreateProtector("first")).Returns(secondMock.Object);
|
||||
|
||||
// Act
|
||||
var retVal = firstMock.Object.CreateProtector("first", "second", "third");
|
||||
|
||||
// Assert
|
||||
Assert.Same(finalExpectedProtector, retVal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Protect_InvalidUtf_Failure()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Security.DataProtection.Test
|
||||
{
|
||||
internal static class ExceptionHelpers
|
||||
{
|
||||
public static void AssertMessage(this ArgumentException exception, string parameterName, string message)
|
||||
{
|
||||
Assert.Equal(parameterName, exception.ParamName);
|
||||
|
||||
// We'll let ArgumentException handle the message formatting for us and treat it as our control value
|
||||
var controlException = new ArgumentException(message, parameterName);
|
||||
Assert.Equal(controlException.Message, exception.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue