Pool `MemoryStream`, `BinaryReader`, `BinaryWriter`, and `SHA256` instances
- #23 part 2 - reduce `byte[]` and `char[]` allocations because all have internal buffers - fortunately, only `MemoryStream` has an unbounded buffer
This commit is contained in:
parent
96063e2476
commit
0ddfa5f0d8
|
|
@ -0,0 +1,109 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.AspNetCore.Antiforgery
|
||||
{
|
||||
public class AntiforgerySerializationContext
|
||||
{
|
||||
// Avoid allocating 256 bytes (the default) and using 18 (the AntiforgeryToken minimum). 64 bytes is enough for
|
||||
// a short username or claim UID and some additional data. MemoryStream bumps capacity to 256 if exceeded.
|
||||
private const int InitialStreamSize = 64;
|
||||
|
||||
// Don't let the MemoryStream grow beyond 1 MB.
|
||||
private const int MaximumStreamSize = 0x100000;
|
||||
|
||||
private MemoryStream _memory;
|
||||
private BinaryReader _reader;
|
||||
private BinaryWriter _writer;
|
||||
private SHA256 _sha256;
|
||||
|
||||
public MemoryStream Stream
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_memory == null)
|
||||
{
|
||||
_memory = new MemoryStream(InitialStreamSize);
|
||||
}
|
||||
|
||||
return _memory;
|
||||
}
|
||||
private set
|
||||
{
|
||||
_memory = value;
|
||||
}
|
||||
}
|
||||
|
||||
public BinaryReader Reader
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_reader == null)
|
||||
{
|
||||
// Leave open to clean up correctly even if only one of the reader or writer has been created.
|
||||
_reader = new BinaryReader(Stream, Encoding.UTF8, leaveOpen: true);
|
||||
}
|
||||
|
||||
return _reader;
|
||||
}
|
||||
private set
|
||||
{
|
||||
_reader = value;
|
||||
}
|
||||
}
|
||||
|
||||
public BinaryWriter Writer
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_writer == null)
|
||||
{
|
||||
// Leave open to clean up correctly even if only one of the reader or writer has been created.
|
||||
_writer = new BinaryWriter(Stream, Encoding.UTF8, leaveOpen: true);
|
||||
}
|
||||
|
||||
return _writer;
|
||||
}
|
||||
private set
|
||||
{
|
||||
_writer = value;
|
||||
}
|
||||
}
|
||||
|
||||
public SHA256 Sha256
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_sha256 == null)
|
||||
{
|
||||
_sha256 = SHA256.Create();
|
||||
}
|
||||
|
||||
return _sha256;
|
||||
}
|
||||
private set
|
||||
{
|
||||
_sha256 = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
if (Stream.Capacity > MaximumStreamSize)
|
||||
{
|
||||
Stream = null;
|
||||
Reader = null;
|
||||
Writer = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
Stream.Position = 0L;
|
||||
Stream.SetLength(0L);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -72,8 +72,8 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
return false;
|
||||
}
|
||||
|
||||
Debug.Assert(this._data.Length == other._data.Length);
|
||||
return AreByteArraysEqual(this._data, other._data);
|
||||
Debug.Assert(_data.Length == other._data.Length);
|
||||
return AreByteArraysEqual(_data, other._data);
|
||||
}
|
||||
|
||||
public byte[] GetData()
|
||||
|
|
|
|||
|
|
@ -5,42 +5,54 @@ using System;
|
|||
using System.IO;
|
||||
using Microsoft.AspNetCore.DataProtection;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
|
||||
namespace Microsoft.AspNetCore.Antiforgery
|
||||
{
|
||||
public class DefaultAntiforgeryTokenSerializer : IAntiforgeryTokenSerializer
|
||||
{
|
||||
private static readonly string Purpose = "Microsoft.AspNetCore.Antiforgery.AntiforgeryToken.v1";
|
||||
|
||||
private readonly IDataProtector _cryptoSystem;
|
||||
private const byte TokenVersion = 0x01;
|
||||
|
||||
public DefaultAntiforgeryTokenSerializer(IDataProtectionProvider provider)
|
||||
private readonly IDataProtector _cryptoSystem;
|
||||
private readonly ObjectPool<AntiforgerySerializationContext> _pool;
|
||||
|
||||
public DefaultAntiforgeryTokenSerializer(
|
||||
IDataProtectionProvider provider,
|
||||
ObjectPool<AntiforgerySerializationContext> pool)
|
||||
{
|
||||
if (provider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(provider));
|
||||
}
|
||||
|
||||
if (pool == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(pool));
|
||||
}
|
||||
|
||||
_cryptoSystem = provider.CreateProtector(Purpose);
|
||||
_pool = pool;
|
||||
}
|
||||
|
||||
public AntiforgeryToken Deserialize(string serializedToken)
|
||||
{
|
||||
var serializationContext = _pool.Get();
|
||||
|
||||
Exception innerException = null;
|
||||
try
|
||||
{
|
||||
var tokenBytes = WebEncoders.Base64UrlDecode(serializedToken);
|
||||
using (var stream = new MemoryStream(_cryptoSystem.Unprotect(tokenBytes)))
|
||||
var unprotectedBytes = _cryptoSystem.Unprotect(tokenBytes);
|
||||
var stream = serializationContext.Stream;
|
||||
stream.Write(unprotectedBytes, 0, unprotectedBytes.Length);
|
||||
stream.Position = 0L;
|
||||
|
||||
var reader = serializationContext.Reader;
|
||||
var token = Deserialize(reader);
|
||||
if (token != null)
|
||||
{
|
||||
using (var reader = new BinaryReader(stream))
|
||||
{
|
||||
var token = DeserializeImpl(reader);
|
||||
if (token != null)
|
||||
{
|
||||
return token;
|
||||
}
|
||||
}
|
||||
return token;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -48,6 +60,10 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
// swallow all exceptions - homogenize error if something went wrong
|
||||
innerException = ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_pool.Return(serializationContext);
|
||||
}
|
||||
|
||||
// if we reached this point, something went wrong deserializing
|
||||
throw new InvalidOperationException(Resources.AntiforgeryToken_DeserializationFailed, innerException);
|
||||
|
|
@ -65,7 +81,7 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
* | `- Username: UTF-8 string with 7-bit integer length prefix
|
||||
* `- AdditionalData: UTF-8 string with 7-bit integer length prefix
|
||||
*/
|
||||
private static AntiforgeryToken DeserializeImpl(BinaryReader reader)
|
||||
private static AntiforgeryToken Deserialize(BinaryReader reader)
|
||||
{
|
||||
// we can only consume tokens of the same serialized version that we generate
|
||||
var embeddedVersion = reader.ReadByte();
|
||||
|
|
@ -113,33 +129,38 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
throw new ArgumentNullException(nameof(token));
|
||||
}
|
||||
|
||||
using (var stream = new MemoryStream())
|
||||
var serializationContext = _pool.Get();
|
||||
|
||||
try
|
||||
{
|
||||
using (var writer = new BinaryWriter(stream))
|
||||
var writer = serializationContext.Writer;
|
||||
writer.Write(TokenVersion);
|
||||
writer.Write(token.SecurityToken.GetData());
|
||||
writer.Write(token.IsCookieToken);
|
||||
|
||||
if (!token.IsCookieToken)
|
||||
{
|
||||
writer.Write(TokenVersion);
|
||||
writer.Write(token.SecurityToken.GetData());
|
||||
writer.Write(token.IsCookieToken);
|
||||
|
||||
if (!token.IsCookieToken)
|
||||
if (token.ClaimUid != null)
|
||||
{
|
||||
if (token.ClaimUid != null)
|
||||
{
|
||||
writer.Write(true /* isClaimsBased */);
|
||||
writer.Write(token.ClaimUid.GetData());
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write(false /* isClaimsBased */);
|
||||
writer.Write(token.Username);
|
||||
}
|
||||
|
||||
writer.Write(token.AdditionalData);
|
||||
writer.Write(true /* isClaimsBased */);
|
||||
writer.Write(token.ClaimUid.GetData());
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write(false /* isClaimsBased */);
|
||||
writer.Write(token.Username);
|
||||
}
|
||||
|
||||
writer.Flush();
|
||||
return WebEncoders.Base64UrlEncode(_cryptoSystem.Protect(stream.ToArray()));
|
||||
writer.Write(token.AdditionalData);
|
||||
}
|
||||
|
||||
writer.Flush();
|
||||
var stream = serializationContext.Stream;
|
||||
return WebEncoders.Base64UrlEncode(_cryptoSystem.Protect(stream.ToArray()));
|
||||
}
|
||||
finally
|
||||
{
|
||||
_pool.Return(serializationContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,9 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Cryptography;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
|
||||
namespace Microsoft.AspNetCore.Antiforgery
|
||||
{
|
||||
|
|
@ -15,6 +14,13 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
/// </summary>
|
||||
public class DefaultClaimUidExtractor : IClaimUidExtractor
|
||||
{
|
||||
private readonly ObjectPool<AntiforgerySerializationContext> _pool;
|
||||
|
||||
public DefaultClaimUidExtractor(ObjectPool<AntiforgerySerializationContext> pool)
|
||||
{
|
||||
_pool = pool;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string ExtractClaimUid(ClaimsIdentity claimsIdentity)
|
||||
{
|
||||
|
|
@ -25,16 +31,15 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
}
|
||||
|
||||
var uniqueIdentifierParameters = GetUniqueIdentifierParameters(claimsIdentity);
|
||||
var claimUidBytes = ComputeSHA256(uniqueIdentifierParameters);
|
||||
var claimUidBytes = ComputeSha256(uniqueIdentifierParameters);
|
||||
return Convert.ToBase64String(claimUidBytes);
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal static IEnumerable<string> GetUniqueIdentifierParameters(ClaimsIdentity claimsIdentity)
|
||||
{
|
||||
var nameIdentifierClaim = claimsIdentity.FindFirst(claim =>
|
||||
String.Equals(ClaimTypes.NameIdentifier,
|
||||
claim.Type, StringComparison.Ordinal));
|
||||
var nameIdentifierClaim = claimsIdentity.FindFirst(
|
||||
claim => string.Equals(ClaimTypes.NameIdentifier, claim.Type, StringComparison.Ordinal));
|
||||
if (nameIdentifierClaim != null && !string.IsNullOrEmpty(nameIdentifierClaim.Value))
|
||||
{
|
||||
return new string[]
|
||||
|
|
@ -47,7 +52,8 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
// We do not understand this ClaimsIdentity, fallback on serializing the entire claims Identity.
|
||||
var claims = claimsIdentity.Claims.ToList();
|
||||
claims.Sort((a, b) => string.Compare(a.Type, b.Type, StringComparison.Ordinal));
|
||||
var identifierParameters = new List<string>();
|
||||
|
||||
var identifierParameters = new List<string>(claims.Count * 2);
|
||||
foreach (var claim in claims)
|
||||
{
|
||||
identifierParameters.Add(claim.Type);
|
||||
|
|
@ -57,25 +63,29 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
return identifierParameters;
|
||||
}
|
||||
|
||||
private static byte[] ComputeSHA256(IEnumerable<string> parameters)
|
||||
private byte[] ComputeSha256(IEnumerable<string> parameters)
|
||||
{
|
||||
using (var stream = new MemoryStream())
|
||||
var serializationContext = _pool.Get();
|
||||
|
||||
try
|
||||
{
|
||||
using (var writer = new BinaryWriter(stream))
|
||||
var writer = serializationContext.Writer;
|
||||
foreach (string parameter in parameters)
|
||||
{
|
||||
foreach (string parameter in parameters)
|
||||
{
|
||||
writer.Write(parameter); // also writes the length as a prefix; unambiguous
|
||||
}
|
||||
|
||||
writer.Flush();
|
||||
|
||||
using (var sha256 = SHA256.Create())
|
||||
{
|
||||
var bytes = sha256.ComputeHash(stream.ToArray(), 0, checked((int)stream.Length));
|
||||
return bytes;
|
||||
}
|
||||
writer.Write(parameter); // also writes the length as a prefix; unambiguous
|
||||
}
|
||||
|
||||
writer.Flush();
|
||||
|
||||
var sha256 = serializationContext.Sha256;
|
||||
var stream = serializationContext.Stream;
|
||||
var bytes = sha256.ComputeHash(stream.ToArray(), 0, checked((int)stream.Length));
|
||||
|
||||
return bytes;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_pool.Return(serializationContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
|
||||
namespace Microsoft.AspNetCore.Antiforgery.Internal
|
||||
{
|
||||
public class AntiforgerySerializationContextPooledObjectPolicy
|
||||
: IPooledObjectPolicy<AntiforgerySerializationContext>
|
||||
{
|
||||
public AntiforgerySerializationContext Create()
|
||||
{
|
||||
return new AntiforgerySerializationContext();
|
||||
}
|
||||
|
||||
public bool Return(AntiforgerySerializationContext obj)
|
||||
{
|
||||
obj.Reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,9 @@
|
|||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Antiforgery;
|
||||
using Microsoft.AspNetCore.Antiforgery.Internal;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyInjection
|
||||
|
|
@ -30,6 +32,15 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
services.TryAddSingleton<IClaimUidExtractor, DefaultClaimUidExtractor>();
|
||||
services.TryAddScoped<IAntiforgeryContextAccessor, DefaultAntiforgeryContextAccessor>();
|
||||
services.TryAddSingleton<IAntiforgeryAdditionalDataProvider, DefaultAntiforgeryAdditionalDataProvider>();
|
||||
|
||||
services.TryAddSingleton<ObjectPoolProvider>(new DefaultObjectPoolProvider());
|
||||
services.TryAddSingleton<ObjectPool<AntiforgerySerializationContext>>(serviceProvider =>
|
||||
{
|
||||
var provider = serviceProvider.GetRequiredService<ObjectPoolProvider>();
|
||||
var policy = new AntiforgerySerializationContextPooledObjectPolicy();
|
||||
return provider.Create(policy);
|
||||
});
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@
|
|||
"Microsoft.AspNetCore.DataProtection": "1.0.0-*",
|
||||
"Microsoft.AspNetCore.Html.Abstractions": "1.0.0-*",
|
||||
"Microsoft.AspNetCore.Http.Abstractions": "1.0.0-*",
|
||||
"Microsoft.AspNetCore.WebUtilities": "1.0.0-*"
|
||||
"Microsoft.AspNetCore.WebUtilities": "1.0.0-*",
|
||||
"Microsoft.Extensions.ObjectPool": "1.0.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"dotnet5.4": { },
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Antiforgery.Internal;
|
||||
using Microsoft.AspNetCore.DataProtection;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -15,6 +17,8 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
private static readonly Mock<IDataProtectionProvider> _dataProtector = GetDataProtector();
|
||||
private static readonly BinaryBlob _claimUid = new BinaryBlob(256, new byte[] { 0x6F, 0x16, 0x48, 0xE9, 0x72, 0x49, 0xAA, 0x58, 0x75, 0x40, 0x36, 0xA6, 0x7E, 0x24, 0x8C, 0xF0, 0x44, 0xF0, 0x7E, 0xCF, 0xB0, 0xED, 0x38, 0x75, 0x56, 0xCE, 0x02, 0x9A, 0x4F, 0x9A, 0x40, 0xE0 });
|
||||
private static readonly BinaryBlob _securityToken = new BinaryBlob(128, new byte[] { 0x70, 0x5E, 0xED, 0xCC, 0x7D, 0x42, 0xF1, 0xD6, 0xB3, 0xB9, 0x8A, 0x59, 0x36, 0x25, 0xBB, 0x4C });
|
||||
private static readonly ObjectPool<AntiforgerySerializationContext> _pool =
|
||||
new DefaultObjectPoolProvider().Create(new AntiforgerySerializationContextPooledObjectPolicy());
|
||||
private const byte _salt = 0x05;
|
||||
|
||||
[Theory]
|
||||
|
|
@ -45,7 +49,7 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
public void Deserialize_BadToken_Throws(string serializedToken)
|
||||
{
|
||||
// Arrange
|
||||
var testSerializer = new DefaultAntiforgeryTokenSerializer(_dataProtector.Object);
|
||||
var testSerializer = new DefaultAntiforgeryTokenSerializer(_dataProtector.Object, _pool);
|
||||
|
||||
// Act & assert
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => testSerializer.Deserialize(serializedToken));
|
||||
|
|
@ -56,7 +60,7 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
public void Serialize_FieldToken_WithClaimUid_TokenRoundTripSuccessful()
|
||||
{
|
||||
// Arrange
|
||||
var testSerializer = new DefaultAntiforgeryTokenSerializer(_dataProtector.Object);
|
||||
var testSerializer = new DefaultAntiforgeryTokenSerializer(_dataProtector.Object, _pool);
|
||||
|
||||
//"01" // Version
|
||||
//+ "705EEDCC7D42F1D6B3B98A593625BB4C" // SecurityToken
|
||||
|
|
@ -86,7 +90,7 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
public void Serialize_FieldToken_WithUsername_TokenRoundTripSuccessful()
|
||||
{
|
||||
// Arrange
|
||||
var testSerializer = new DefaultAntiforgeryTokenSerializer(_dataProtector.Object);
|
||||
var testSerializer = new DefaultAntiforgeryTokenSerializer(_dataProtector.Object, _pool);
|
||||
|
||||
//"01" // Version
|
||||
//+ "705EEDCC7D42F1D6B3B98A593625BB4C" // SecurityToken
|
||||
|
|
@ -117,7 +121,7 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
public void Serialize_CookieToken_TokenRoundTripSuccessful()
|
||||
{
|
||||
// Arrange
|
||||
var testSerializer = new DefaultAntiforgeryTokenSerializer(_dataProtector.Object);
|
||||
var testSerializer = new DefaultAntiforgeryTokenSerializer(_dataProtector.Object, _pool);
|
||||
|
||||
//"01" // Version
|
||||
//+ "705EEDCC7D42F1D6B3B98A593625BB4C" // SecurityToken
|
||||
|
|
|
|||
|
|
@ -4,10 +4,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Antiforgery.Internal;
|
||||
using Microsoft.AspNetCore.DataProtection;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Internal;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
|
@ -16,6 +18,8 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
{
|
||||
public class DefaultAntiforgeryTokenStoreTest
|
||||
{
|
||||
private static readonly ObjectPool<AntiforgerySerializationContext> _pool =
|
||||
new DefaultObjectPoolProvider().Create(new AntiforgerySerializationContextPooledObjectPolicy());
|
||||
private readonly string _cookieName = "cookie-name";
|
||||
|
||||
[Fact]
|
||||
|
|
@ -182,7 +186,7 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
var exception = await Assert.ThrowsAsync<AntiforgeryValidationException>(
|
||||
async () => await tokenStore.GetRequestTokensAsync(httpContext));
|
||||
|
||||
// Assert
|
||||
// Assert
|
||||
Assert.Equal("The required antiforgery cookie \"cookie-name\" is not present.", exception.Message);
|
||||
}
|
||||
|
||||
|
|
@ -209,13 +213,13 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
|
||||
var tokenStore = new DefaultAntiforgeryTokenStore(
|
||||
optionsAccessor: new TestOptionsManager(options),
|
||||
tokenSerializer: new DefaultAntiforgeryTokenSerializer(new EphemeralDataProtectionProvider()));
|
||||
tokenSerializer: new DefaultAntiforgeryTokenSerializer(new EphemeralDataProtectionProvider(), _pool));
|
||||
|
||||
// Act
|
||||
var exception = await Assert.ThrowsAsync<AntiforgeryValidationException>(
|
||||
async () => await tokenStore.GetRequestTokensAsync(httpContext));
|
||||
|
||||
// Assert
|
||||
// Assert
|
||||
Assert.Equal("The required antiforgery form field \"form-field-name\" is not present.", exception.Message);
|
||||
}
|
||||
|
||||
|
|
@ -244,7 +248,7 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
|
||||
var tokenStore = new DefaultAntiforgeryTokenStore(
|
||||
optionsAccessor: new TestOptionsManager(options),
|
||||
tokenSerializer: new DefaultAntiforgeryTokenSerializer(new EphemeralDataProtectionProvider()));
|
||||
tokenSerializer: new DefaultAntiforgeryTokenSerializer(new EphemeralDataProtectionProvider(), _pool));
|
||||
|
||||
// Act
|
||||
var tokens = await tokenStore.GetRequestTokensAsync(httpContext);
|
||||
|
|
@ -279,7 +283,7 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
|
||||
var tokenStore = new DefaultAntiforgeryTokenStore(
|
||||
optionsAccessor: new TestOptionsManager(options),
|
||||
tokenSerializer: new DefaultAntiforgeryTokenSerializer(new EphemeralDataProtectionProvider()));
|
||||
tokenSerializer: new DefaultAntiforgeryTokenSerializer(new EphemeralDataProtectionProvider(), _pool));
|
||||
|
||||
// Act
|
||||
var tokens = await tokenStore.GetRequestTokensAsync(httpContext);
|
||||
|
|
@ -312,7 +316,7 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
|
||||
var tokenStore = new DefaultAntiforgeryTokenStore(
|
||||
optionsAccessor: new TestOptionsManager(options),
|
||||
tokenSerializer: new DefaultAntiforgeryTokenSerializer(new EphemeralDataProtectionProvider()));
|
||||
tokenSerializer: new DefaultAntiforgeryTokenSerializer(new EphemeralDataProtectionProvider(), _pool));
|
||||
|
||||
// Act
|
||||
var exception = await Assert.ThrowsAsync<AntiforgeryValidationException>(
|
||||
|
|
@ -349,7 +353,7 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
var exception = await Assert.ThrowsAsync<AntiforgeryValidationException>(
|
||||
async () => await tokenStore.GetRequestTokensAsync(httpContext));
|
||||
|
||||
// Assert
|
||||
// Assert
|
||||
Assert.Equal(
|
||||
"The required antiforgery request token was not provided in either form field \"form-field-name\" " +
|
||||
"or header value \"header-name\".",
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Antiforgery.Internal;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -11,11 +13,14 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
{
|
||||
public class DefaultClaimUidExtractorTest
|
||||
{
|
||||
private static readonly ObjectPool<AntiforgerySerializationContext> _pool =
|
||||
new DefaultObjectPoolProvider().Create(new AntiforgerySerializationContextPooledObjectPolicy());
|
||||
|
||||
[Fact]
|
||||
public void ExtractClaimUid_NullIdentity()
|
||||
{
|
||||
// Arrange
|
||||
IClaimUidExtractor extractor = new DefaultClaimUidExtractor();
|
||||
var extractor = new DefaultClaimUidExtractor(_pool);
|
||||
|
||||
// Act
|
||||
var claimUid = extractor.ExtractClaimUid(null);
|
||||
|
|
@ -28,7 +33,7 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
public void ExtractClaimUid_Unauthenticated()
|
||||
{
|
||||
// Arrange
|
||||
IClaimUidExtractor extractor = new DefaultClaimUidExtractor();
|
||||
var extractor = new DefaultClaimUidExtractor(_pool);
|
||||
|
||||
var mockIdentity = new Mock<ClaimsIdentity>();
|
||||
mockIdentity.Setup(o => o.IsAuthenticated)
|
||||
|
|
@ -49,7 +54,7 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
mockIdentity.Setup(o => o.IsAuthenticated)
|
||||
.Returns(true);
|
||||
|
||||
IClaimUidExtractor extractor = new DefaultClaimUidExtractor();
|
||||
var extractor = new DefaultClaimUidExtractor(_pool);
|
||||
|
||||
// Act
|
||||
var claimUid = extractor.ExtractClaimUid(mockIdentity.Object);
|
||||
|
|
|
|||
Loading…
Reference in New Issue