Add nullability to antiforgery (#22279)

* Add nullability to antiforgery

Addresses #5680

* Rebase
This commit is contained in:
Pranav K 2020-06-11 20:23:33 -07:00 committed by GitHub
parent 4c4351e11c
commit 20770811a4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 154 additions and 141 deletions

View File

@ -0,0 +1,7 @@
<Project>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)..\, Directory.Build.props))\Directory.Build.props" />
<PropertyGroup>
<Nullable>annotations</Nullable>
</PropertyGroup>
</Project>

View File

@ -2,6 +2,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>$(DefaultNetCoreTargetFramework)</TargetFrameworks> <TargetFrameworks>$(DefaultNetCoreTargetFramework)</TargetFrameworks>
<Nullable>annotations</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'"> <ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'">
<Compile Include="Microsoft.AspNetCore.Antiforgery.netcoreapp.cs" /> <Compile Include="Microsoft.AspNetCore.Antiforgery.netcoreapp.cs" />

View File

@ -9,21 +9,21 @@ namespace Microsoft.AspNetCore.Antiforgery
public AntiforgeryOptions() { } public AntiforgeryOptions() { }
public Microsoft.AspNetCore.Http.CookieBuilder Cookie { get { throw null; } set { } } public Microsoft.AspNetCore.Http.CookieBuilder Cookie { get { throw null; } set { } }
public string FormFieldName { get { throw null; } set { } } public string FormFieldName { get { throw null; } set { } }
public string HeaderName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public string? HeaderName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
public bool SuppressXFrameOptionsHeader { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public bool SuppressXFrameOptionsHeader { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
} }
public partial class AntiforgeryTokenSet public partial class AntiforgeryTokenSet
{ {
public AntiforgeryTokenSet(string requestToken, string cookieToken, string formFieldName, string headerName) { } public AntiforgeryTokenSet(string? requestToken, string? cookieToken, string formFieldName, string? headerName) { }
public string CookieToken { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public string? CookieToken { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public string FormFieldName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public string FormFieldName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public string HeaderName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public string? HeaderName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public string RequestToken { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public string? RequestToken { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
} }
public partial class AntiforgeryValidationException : System.Exception public partial class AntiforgeryValidationException : System.Exception
{ {
public AntiforgeryValidationException(string message) { } public AntiforgeryValidationException(string message) { }
public AntiforgeryValidationException(string message, System.Exception innerException) { } public AntiforgeryValidationException(string message, System.Exception? innerException) { }
} }
public partial interface IAntiforgery public partial interface IAntiforgery
{ {

View File

@ -73,7 +73,7 @@ namespace Microsoft.AspNetCore.Antiforgery
/// Specifies the name of the header value that is used by the antiforgery system. If <c>null</c> then /// Specifies the name of the header value that is used by the antiforgery system. If <c>null</c> then
/// antiforgery validation will only consider form data. /// antiforgery validation will only consider form data.
/// </summary> /// </summary>
public string HeaderName { get; set; } = AntiforgeryTokenHeaderName; public string? HeaderName { get; set; } = AntiforgeryTokenHeaderName;
/// <summary> /// <summary>
/// Specifies whether to suppress the generation of X-Frame-Options header /// Specifies whether to suppress the generation of X-Frame-Options header

View File

@ -18,10 +18,10 @@ namespace Microsoft.AspNetCore.Antiforgery
/// <param name="formFieldName">The name of the form field used for the request token.</param> /// <param name="formFieldName">The name of the form field used for the request token.</param>
/// <param name="headerName">The name of the header used for the request token.</param> /// <param name="headerName">The name of the header used for the request token.</param>
public AntiforgeryTokenSet( public AntiforgeryTokenSet(
string requestToken, string? requestToken,
string cookieToken, string? cookieToken,
string formFieldName, string formFieldName,
string headerName) string? headerName)
{ {
if (formFieldName == null) if (formFieldName == null)
{ {
@ -37,7 +37,7 @@ namespace Microsoft.AspNetCore.Antiforgery
/// <summary> /// <summary>
/// Gets the request token. /// Gets the request token.
/// </summary> /// </summary>
public string RequestToken { get; } public string? RequestToken { get; }
/// <summary> /// <summary>
/// Gets the name of the form field used for the request token. /// Gets the name of the form field used for the request token.
@ -47,11 +47,11 @@ namespace Microsoft.AspNetCore.Antiforgery
/// <summary> /// <summary>
/// Gets the name of the header used for the request token. /// Gets the name of the header used for the request token.
/// </summary> /// </summary>
public string HeaderName { get; } public string? HeaderName { get; }
/// <summary> /// <summary>
/// Gets the cookie token. /// Gets the cookie token.
/// </summary> /// </summary>
public string CookieToken { get; } public string? CookieToken { get; }
} }
} }

View File

@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Antiforgery
/// </summary> /// </summary>
/// <param name="message">The message that describes the error.</param> /// <param name="message">The message that describes the error.</param>
/// <param name="innerException">The inner <see cref="Exception"/>.</param> /// <param name="innerException">The inner <see cref="Exception"/>.</param>
public AntiforgeryValidationException(string message, Exception innerException) public AntiforgeryValidationException(string message, Exception? innerException)
: base(message, innerException) : base(message, innerException)
{ {
} }

View File

@ -10,23 +10,23 @@ namespace Microsoft.AspNetCore.Antiforgery
{ {
public bool HaveDeserializedCookieToken { get; set; } public bool HaveDeserializedCookieToken { get; set; }
public AntiforgeryToken CookieToken { get; set; } public AntiforgeryToken? CookieToken { get; set; }
public bool HaveDeserializedRequestToken { get; set; } public bool HaveDeserializedRequestToken { get; set; }
public AntiforgeryToken RequestToken { get; set; } public AntiforgeryToken? RequestToken { get; set; }
public bool HaveGeneratedNewCookieToken { get; set; } public bool HaveGeneratedNewCookieToken { get; set; }
// After HaveGeneratedNewCookieToken is true, remains null if CookieToken is valid. // After HaveGeneratedNewCookieToken is true, remains null if CookieToken is valid.
public AntiforgeryToken NewCookieToken { get; set; } public AntiforgeryToken? NewCookieToken { get; set; }
// After HaveGeneratedNewCookieToken is true, remains null if CookieToken is valid. // After HaveGeneratedNewCookieToken is true, remains null if CookieToken is valid.
public string NewCookieTokenString { get; set; } public string? NewCookieTokenString { get; set; }
public AntiforgeryToken NewRequestToken { get; set; } public AntiforgeryToken? NewRequestToken { get; set; }
public string NewRequestTokenString { get; set; } public string? NewRequestTokenString { get; set; }
// Always false if NewCookieToken is null. Never store null cookie token or re-store cookie token from request. // Always false if NewCookieToken is null. Never store null cookie token or re-store cookie token from request.
public bool HaveStoredNewCookieToken { get; set; } public bool HaveStoredNewCookieToken { get; set; }

View File

@ -8,15 +8,15 @@ namespace Microsoft.AspNetCore.Antiforgery
{ {
internal static class AntiforgeryLoggerExtensions internal static class AntiforgeryLoggerExtensions
{ {
private static readonly Action<ILogger, Exception> _failedToDeserialzeTokens; private static readonly Action<ILogger, Exception?> _failedToDeserialzeTokens;
private static readonly Action<ILogger, string, Exception> _validationFailed; private static readonly Action<ILogger, string, Exception?> _validationFailed;
private static readonly Action<ILogger, Exception> _validated; private static readonly Action<ILogger, Exception?> _validated;
private static readonly Action<ILogger, string, Exception> _missingCookieToken; private static readonly Action<ILogger, string?, Exception?> _missingCookieToken;
private static readonly Action<ILogger, string, string, Exception> _missingRequestToken; private static readonly Action<ILogger, string, string?, Exception?> _missingRequestToken;
private static readonly Action<ILogger, Exception> _newCookieToken; private static readonly Action<ILogger, Exception?> _newCookieToken;
private static readonly Action<ILogger, Exception> _reusedCookieToken; private static readonly Action<ILogger, Exception?> _reusedCookieToken;
private static readonly Action<ILogger, Exception> _tokenDeserializeException; private static readonly Action<ILogger, Exception?> _tokenDeserializeException;
private static readonly Action<ILogger, Exception> _responseCacheHeadersOverridenToNoCache; private static readonly Action<ILogger, Exception?> _responseCacheHeadersOverridenToNoCache;
static AntiforgeryLoggerExtensions() static AntiforgeryLoggerExtensions()
{ {
@ -28,11 +28,11 @@ namespace Microsoft.AspNetCore.Antiforgery
LogLevel.Debug, LogLevel.Debug,
new EventId(2, "Validated"), new EventId(2, "Validated"),
"Antiforgery successfully validated a request."); "Antiforgery successfully validated a request.");
_missingCookieToken = LoggerMessage.Define<string>( _missingCookieToken = LoggerMessage.Define<string?>(
LogLevel.Warning, LogLevel.Warning,
new EventId(3, "MissingCookieToken"), new EventId(3, "MissingCookieToken"),
"The required antiforgery cookie '{CookieName}' is not present."); "The required antiforgery cookie '{CookieName}' is not present.");
_missingRequestToken = LoggerMessage.Define<string, string>( _missingRequestToken = LoggerMessage.Define<string, string?>(
LogLevel.Warning, LogLevel.Warning,
new EventId(4, "MissingRequestToken"), new EventId(4, "MissingRequestToken"),
"The required antiforgery request token was not provided in either form field '{FormFieldName}' " "The required antiforgery request token was not provided in either form field '{FormFieldName}' "
@ -71,12 +71,12 @@ namespace Microsoft.AspNetCore.Antiforgery
_validated(logger, null); _validated(logger, null);
} }
public static void MissingCookieToken(this ILogger logger, string cookieName) public static void MissingCookieToken(this ILogger logger, string? cookieName)
{ {
_missingCookieToken(logger, cookieName, null); _missingCookieToken(logger, cookieName, null);
} }
public static void MissingRequestToken(this ILogger logger, string formFieldName, string headerName) public static void MissingRequestToken(this ILogger logger, string formFieldName, string? headerName)
{ {
_missingRequestToken(logger, formFieldName, headerName, null); _missingRequestToken(logger, formFieldName, headerName, null);
} }

View File

@ -23,11 +23,11 @@ namespace Microsoft.AspNetCore.Antiforgery
// Don't let _chars grow beyond 512k characters. // Don't let _chars grow beyond 512k characters.
private const int MaximumCharsLength = 0x80000; private const int MaximumCharsLength = 0x80000;
private char[] _chars; private char[]? _chars;
private MemoryStream _stream; private MemoryStream? _stream;
private BinaryReader _reader; private BinaryReader? _reader;
private BinaryWriter _writer; private BinaryWriter? _writer;
private SHA256 _sha256; private SHA256? _sha256;
public MemoryStream Stream public MemoryStream Stream
{ {
@ -126,9 +126,9 @@ namespace Microsoft.AspNetCore.Antiforgery
{ {
if (Stream.Capacity > MaximumStreamSize) if (Stream.Capacity > MaximumStreamSize)
{ {
Stream = null; _stream = null;
Reader = null; _reader = null;
Writer = null; _writer = null;
} }
else else
{ {

View File

@ -10,7 +10,7 @@ namespace Microsoft.AspNetCore.Antiforgery
private string _additionalData = string.Empty; private string _additionalData = string.Empty;
private string _username = string.Empty; private string _username = string.Empty;
private BinaryBlob _securityToken; private BinaryBlob? _securityToken;
public string AdditionalData public string AdditionalData
{ {
@ -21,11 +21,11 @@ namespace Microsoft.AspNetCore.Antiforgery
} }
} }
public BinaryBlob ClaimUid { get; set; } public BinaryBlob? ClaimUid { get; set; }
public bool IsCookieToken { get; set; } public bool IsCookieToken { get; set; }
public BinaryBlob SecurityToken public BinaryBlob? SecurityToken
{ {
get get
{ {
@ -41,7 +41,7 @@ namespace Microsoft.AspNetCore.Antiforgery
} }
} }
public string Username public string? Username
{ {
get { return _username; } get { return _username; }
set set

View File

@ -59,12 +59,12 @@ namespace Microsoft.AspNetCore.Antiforgery
} }
} }
public override bool Equals(object obj) public override bool Equals(object? obj)
{ {
return Equals(obj as BinaryBlob); return Equals(obj as BinaryBlob);
} }
public bool Equals(BinaryBlob other) public bool Equals(BinaryBlob? other)
{ {
if (other == null) if (other == null)
{ {

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -125,9 +126,7 @@ namespace Microsoft.AspNetCore.Antiforgery
} }
// Extract cookie & request tokens // Extract cookie & request tokens
AntiforgeryToken deserializedCookieToken; if (!TryDeserializeTokens(httpContext, tokens, out var deserializedCookieToken, out var deserializedRequestToken))
AntiforgeryToken deserializedRequestToken;
if (!TryDeserializeTokens(httpContext, tokens, out deserializedCookieToken, out deserializedRequestToken))
{ {
return false; return false;
} }
@ -137,7 +136,7 @@ namespace Microsoft.AspNetCore.Antiforgery
httpContext, httpContext,
deserializedCookieToken, deserializedCookieToken,
deserializedRequestToken, deserializedRequestToken,
out string message); out var message);
if (result) if (result)
{ {
@ -145,7 +144,7 @@ namespace Microsoft.AspNetCore.Antiforgery
} }
else else
{ {
_logger.ValidationFailed(message); _logger.ValidationFailed(message!);
} }
return result; return result;
@ -210,12 +209,11 @@ namespace Microsoft.AspNetCore.Antiforgery
out deserializedRequestToken); out deserializedRequestToken);
// Validate // Validate
string message;
if (!_tokenGenerator.TryValidateTokenSet( if (!_tokenGenerator.TryValidateTokenSet(
httpContext, httpContext,
deserializedCookieToken, deserializedCookieToken,
deserializedRequestToken, deserializedRequestToken,
out message)) out var message))
{ {
throw new AntiforgeryValidationException(message); throw new AntiforgeryValidationException(message);
} }
@ -306,7 +304,7 @@ namespace Microsoft.AspNetCore.Antiforgery
return antiforgeryFeature; return antiforgeryFeature;
} }
AntiforgeryToken cookieToken; AntiforgeryToken? cookieToken;
if (antiforgeryFeature.HaveDeserializedCookieToken) if (antiforgeryFeature.HaveDeserializedCookieToken)
{ {
cookieToken = antiforgeryFeature.CookieToken; cookieToken = antiforgeryFeature.CookieToken;
@ -319,7 +317,7 @@ namespace Microsoft.AspNetCore.Antiforgery
antiforgeryFeature.HaveDeserializedCookieToken = true; antiforgeryFeature.HaveDeserializedCookieToken = true;
} }
AntiforgeryToken newCookieToken; AntiforgeryToken? newCookieToken;
if (_tokenGenerator.IsCookieTokenValid(cookieToken)) if (_tokenGenerator.IsCookieTokenValid(cookieToken))
{ {
// No need for the cookie token from the request after it has been verified. // No need for the cookie token from the request after it has been verified.
@ -338,7 +336,7 @@ namespace Microsoft.AspNetCore.Antiforgery
return antiforgeryFeature; return antiforgeryFeature;
} }
private AntiforgeryToken GetCookieTokenDoesNotThrow(HttpContext httpContext) private AntiforgeryToken? GetCookieTokenDoesNotThrow(HttpContext httpContext)
{ {
try try
{ {
@ -367,7 +365,7 @@ namespace Microsoft.AspNetCore.Antiforgery
var cookieToken = antiforgeryFeature.NewCookieToken ?? antiforgeryFeature.CookieToken; var cookieToken = antiforgeryFeature.NewCookieToken ?? antiforgeryFeature.CookieToken;
antiforgeryFeature.NewRequestToken = _tokenGenerator.GenerateRequestToken( antiforgeryFeature.NewRequestToken = _tokenGenerator.GenerateRequestToken(
httpContext, httpContext,
cookieToken); cookieToken!);
} }
return antiforgeryFeature; return antiforgeryFeature;
@ -391,8 +389,7 @@ namespace Microsoft.AspNetCore.Antiforgery
private void LogCacheHeaderOverrideWarning(HttpResponse response) private void LogCacheHeaderOverrideWarning(HttpResponse response)
{ {
var logWarning = false; var logWarning = false;
CacheControlHeaderValue cacheControlHeaderValue; if (CacheControlHeaderValue.TryParse(response.Headers[HeaderNames.CacheControl].ToString(), out var cacheControlHeaderValue))
if (CacheControlHeaderValue.TryParse(response.Headers[HeaderNames.CacheControl].ToString(), out cacheControlHeaderValue))
{ {
if (!cacheControlHeaderValue.NoCache) if (!cacheControlHeaderValue.NoCache)
{ {
@ -434,7 +431,7 @@ namespace Microsoft.AspNetCore.Antiforgery
return new AntiforgeryTokenSet( return new AntiforgeryTokenSet(
antiforgeryFeature.NewRequestTokenString, antiforgeryFeature.NewRequestTokenString,
antiforgeryFeature.NewCookieTokenString, antiforgeryFeature.NewCookieTokenString!,
_options.FormFieldName, _options.FormFieldName,
_options.HeaderName); _options.HeaderName);
} }
@ -442,8 +439,8 @@ namespace Microsoft.AspNetCore.Antiforgery
private bool TryDeserializeTokens( private bool TryDeserializeTokens(
HttpContext httpContext, HttpContext httpContext,
AntiforgeryTokenSet antiforgeryTokenSet, AntiforgeryTokenSet antiforgeryTokenSet,
out AntiforgeryToken cookieToken, [NotNullWhen(true)] out AntiforgeryToken? cookieToken,
out AntiforgeryToken requestToken) [NotNullWhen(true)] out AntiforgeryToken? requestToken)
{ {
try try
{ {
@ -470,11 +467,11 @@ namespace Microsoft.AspNetCore.Antiforgery
if (antiforgeryFeature.HaveDeserializedCookieToken) if (antiforgeryFeature.HaveDeserializedCookieToken)
{ {
cookieToken = antiforgeryFeature.CookieToken; cookieToken = antiforgeryFeature.CookieToken!;
} }
else else
{ {
cookieToken = _tokenSerializer.Deserialize(antiforgeryTokenSet.CookieToken); cookieToken = _tokenSerializer.Deserialize(antiforgeryTokenSet.CookieToken!);
antiforgeryFeature.CookieToken = cookieToken; antiforgeryFeature.CookieToken = cookieToken;
antiforgeryFeature.HaveDeserializedCookieToken = true; antiforgeryFeature.HaveDeserializedCookieToken = true;
@ -482,11 +479,11 @@ namespace Microsoft.AspNetCore.Antiforgery
if (antiforgeryFeature.HaveDeserializedRequestToken) if (antiforgeryFeature.HaveDeserializedRequestToken)
{ {
requestToken = antiforgeryFeature.RequestToken; requestToken = antiforgeryFeature.RequestToken!;
} }
else else
{ {
requestToken = _tokenSerializer.Deserialize(antiforgeryTokenSet.RequestToken); requestToken = _tokenSerializer.Deserialize(antiforgeryTokenSet.RequestToken!);
antiforgeryFeature.RequestToken = requestToken; antiforgeryFeature.RequestToken = requestToken;
antiforgeryFeature.HaveDeserializedRequestToken = true; antiforgeryFeature.HaveDeserializedRequestToken = true;

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Security.Claims; using System.Security.Claims;
using System.Security.Principal; using System.Security.Principal;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
@ -89,7 +90,7 @@ namespace Microsoft.AspNetCore.Antiforgery
// Application says user is authenticated, but we have no identifier for the user. // Application says user is authenticated, but we have no identifier for the user.
throw new InvalidOperationException( throw new InvalidOperationException(
Resources.FormatAntiforgeryTokenValidator_AuthenticatedUserWithoutUsername( Resources.FormatAntiforgeryTokenValidator_AuthenticatedUserWithoutUsername(
authenticatedIdentity.GetType(), authenticatedIdentity?.GetType() ?? typeof(ClaimsIdentity),
nameof(IIdentity.IsAuthenticated), nameof(IIdentity.IsAuthenticated),
"true", "true",
nameof(IIdentity.Name), nameof(IIdentity.Name),
@ -101,7 +102,7 @@ namespace Microsoft.AspNetCore.Antiforgery
} }
/// <inheritdoc /> /// <inheritdoc />
public bool IsCookieTokenValid(AntiforgeryToken cookieToken) public bool IsCookieTokenValid(AntiforgeryToken? cookieToken)
{ {
return cookieToken != null && cookieToken.IsCookieToken; return cookieToken != null && cookieToken.IsCookieToken;
} }
@ -111,7 +112,7 @@ namespace Microsoft.AspNetCore.Antiforgery
HttpContext httpContext, HttpContext httpContext,
AntiforgeryToken cookieToken, AntiforgeryToken cookieToken,
AntiforgeryToken requestToken, AntiforgeryToken requestToken,
out string message) [NotNullWhen(false)] out string? message)
{ {
if (httpContext == null) if (httpContext == null)
{ {
@ -148,7 +149,7 @@ namespace Microsoft.AspNetCore.Antiforgery
// Is the incoming token meant for the current user? // Is the incoming token meant for the current user?
var currentUsername = string.Empty; var currentUsername = string.Empty;
BinaryBlob currentClaimUid = null; BinaryBlob? currentClaimUid = null;
var authenticatedIdentity = GetAuthenticatedIdentity(httpContext.User); var authenticatedIdentity = GetAuthenticatedIdentity(httpContext.User);
if (authenticatedIdentity != null) if (authenticatedIdentity != null)
@ -193,7 +194,7 @@ namespace Microsoft.AspNetCore.Antiforgery
return true; return true;
} }
private static BinaryBlob GetClaimUidBlob(string base64ClaimUid) private static BinaryBlob? GetClaimUidBlob(string? base64ClaimUid)
{ {
if (base64ClaimUid == null) if (base64ClaimUid == null)
{ {
@ -203,7 +204,7 @@ namespace Microsoft.AspNetCore.Antiforgery
return new BinaryBlob(256, Convert.FromBase64String(base64ClaimUid)); return new BinaryBlob(256, Convert.FromBase64String(base64ClaimUid));
} }
private static ClaimsIdentity GetAuthenticatedIdentity(ClaimsPrincipal claimsPrincipal) private static ClaimsIdentity? GetAuthenticatedIdentity(ClaimsPrincipal? claimsPrincipal)
{ {
if (claimsPrincipal == null) if (claimsPrincipal == null)
{ {

View File

@ -39,7 +39,7 @@ namespace Microsoft.AspNetCore.Antiforgery
{ {
var serializationContext = _pool.Get(); var serializationContext = _pool.Get();
Exception innerException = null; Exception? innerException = null;
try try
{ {
var count = serializedToken.Length; var count = serializedToken.Length;
@ -90,7 +90,7 @@ namespace Microsoft.AspNetCore.Antiforgery
* | `- Username: UTF-8 string with 7-bit integer length prefix * | `- Username: UTF-8 string with 7-bit integer length prefix
* `- AdditionalData: UTF-8 string with 7-bit integer length prefix * `- AdditionalData: UTF-8 string with 7-bit integer length prefix
*/ */
private static AntiforgeryToken Deserialize(BinaryReader reader) private static AntiforgeryToken? Deserialize(BinaryReader reader)
{ {
// we can only consume tokens of the same serialized version that we generate // we can only consume tokens of the same serialized version that we generate
var embeddedVersion = reader.ReadByte(); var embeddedVersion = reader.ReadByte();
@ -144,7 +144,7 @@ namespace Microsoft.AspNetCore.Antiforgery
{ {
var writer = serializationContext.Writer; var writer = serializationContext.Writer;
writer.Write(TokenVersion); writer.Write(TokenVersion);
writer.Write(token.SecurityToken.GetData()); writer.Write(token.SecurityToken!.GetData());
writer.Write(token.IsCookieToken); writer.Write(token.IsCookieToken);
if (!token.IsCookieToken) if (!token.IsCookieToken)
@ -157,7 +157,7 @@ namespace Microsoft.AspNetCore.Antiforgery
else else
{ {
writer.Write(false /* isClaimsBased */); writer.Write(false /* isClaimsBased */);
writer.Write(token.Username); writer.Write(token.Username!);
} }
writer.Write(token.AdditionalData); writer.Write(token.AdditionalData);

View File

@ -24,11 +24,11 @@ namespace Microsoft.AspNetCore.Antiforgery
_options = optionsAccessor.Value; _options = optionsAccessor.Value;
} }
public string GetCookieToken(HttpContext httpContext) public string? GetCookieToken(HttpContext httpContext)
{ {
Debug.Assert(httpContext != null); Debug.Assert(httpContext != null);
var requestCookie = httpContext.Request.Cookies[_options.Cookie.Name]; var requestCookie = httpContext.Request.Cookies[_options.Cookie.Name!];
if (string.IsNullOrEmpty(requestCookie)) if (string.IsNullOrEmpty(requestCookie))
{ {
// unable to find the cookie. // unable to find the cookie.
@ -42,7 +42,7 @@ namespace Microsoft.AspNetCore.Antiforgery
{ {
Debug.Assert(httpContext != null); Debug.Assert(httpContext != null);
var cookieToken = httpContext.Request.Cookies[_options.Cookie.Name]; var cookieToken = httpContext.Request.Cookies[_options.Cookie.Name!];
// We want to delay reading the form as much as possible, for example in case of large file uploads, // We want to delay reading the form as much as possible, for example in case of large file uploads,
// request token could be part of the header. // request token could be part of the header.
@ -84,7 +84,7 @@ namespace Microsoft.AspNetCore.Antiforgery
} }
} }
httpContext.Response.Cookies.Append(_options.Cookie.Name, token, options); httpContext.Response.Cookies.Append(_options.Cookie.Name!, token, options);
} }
} }
} }

View File

@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Antiforgery
} }
/// <inheritdoc /> /// <inheritdoc />
public string ExtractClaimUid(ClaimsPrincipal claimsPrincipal) public string? ExtractClaimUid(ClaimsPrincipal claimsPrincipal)
{ {
Debug.Assert(claimsPrincipal != null); Debug.Assert(claimsPrincipal != null);
@ -37,7 +37,7 @@ namespace Microsoft.AspNetCore.Antiforgery
return Convert.ToBase64String(claimUidBytes); return Convert.ToBase64String(claimUidBytes);
} }
public static IList<string> GetUniqueIdentifierParameters(IEnumerable<ClaimsIdentity> claimsIdentities) public static IList<string>? GetUniqueIdentifierParameters(IEnumerable<ClaimsIdentity> claimsIdentities)
{ {
var identitiesList = claimsIdentities as List<ClaimsIdentity>; var identitiesList = claimsIdentities as List<ClaimsIdentity>;
if (identitiesList == null) if (identitiesList == null)

View File

@ -1,8 +1,10 @@
using System.Diagnostics.CodeAnalysis;
namespace Microsoft.AspNetCore.Antiforgery namespace Microsoft.AspNetCore.Antiforgery
{ {
internal interface IAntiforgeryFeature internal interface IAntiforgeryFeature
{ {
AntiforgeryToken CookieToken { get; set; } AntiforgeryToken? CookieToken { get; set; }
bool HaveDeserializedCookieToken { get; set; } bool HaveDeserializedCookieToken { get; set; }
@ -12,14 +14,14 @@ namespace Microsoft.AspNetCore.Antiforgery
bool HaveStoredNewCookieToken { get; set; } bool HaveStoredNewCookieToken { get; set; }
AntiforgeryToken NewCookieToken { get; set; } AntiforgeryToken? NewCookieToken { get; set; }
string NewCookieTokenString { get; set; } string? NewCookieTokenString { get; set; }
AntiforgeryToken NewRequestToken { get; set; } AntiforgeryToken? NewRequestToken { get; set; }
string NewRequestTokenString { get; set; } string? NewRequestTokenString { get; set; }
AntiforgeryToken RequestToken { get; set; } AntiforgeryToken? RequestToken { get; set; }
} }
} }

View File

@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.Antiforgery namespace Microsoft.AspNetCore.Antiforgery
@ -29,7 +30,7 @@ namespace Microsoft.AspNetCore.Antiforgery
/// </summary> /// </summary>
/// <param name="cookieToken">A valid cookie token.</param> /// <param name="cookieToken">A valid cookie token.</param>
/// <returns><c>true</c> if the cookie token is valid, otherwise <c>false</c>.</returns> /// <returns><c>true</c> if the cookie token is valid, otherwise <c>false</c>.</returns>
bool IsCookieTokenValid(AntiforgeryToken cookieToken); bool IsCookieTokenValid(AntiforgeryToken? cookieToken);
/// <summary> /// <summary>
/// Attempts to validate a cookie and request token set for the given <paramref name="httpContext"/>. /// Attempts to validate a cookie and request token set for the given <paramref name="httpContext"/>.
@ -45,6 +46,6 @@ namespace Microsoft.AspNetCore.Antiforgery
HttpContext httpContext, HttpContext httpContext,
AntiforgeryToken cookieToken, AntiforgeryToken cookieToken,
AntiforgeryToken requestToken, AntiforgeryToken requestToken,
out string message); [NotNullWhen(false)] out string? message);
} }
} }

View File

@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Antiforgery
{ {
internal interface IAntiforgeryTokenStore internal interface IAntiforgeryTokenStore
{ {
string GetCookieToken(HttpContext httpContext); string? GetCookieToken(HttpContext httpContext);
/// <summary> /// <summary>
/// Gets the cookie and request tokens from the request. /// Gets the cookie and request tokens from the request.

View File

@ -15,6 +15,6 @@ namespace Microsoft.AspNetCore.Antiforgery
/// </summary> /// </summary>
/// <param name="claimsPrincipal">The <see cref="ClaimsPrincipal"/>.</param> /// <param name="claimsPrincipal">The <see cref="ClaimsPrincipal"/>.</param>
/// <returns>The claims identifier.</returns> /// <returns>The claims identifier.</returns>
string ExtractClaimUid(ClaimsPrincipal claimsPrincipal); string? ExtractClaimUid(ClaimsPrincipal claimsPrincipal);
} }
} }

View File

@ -7,6 +7,7 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>aspnetcore;antiforgery</PackageTags> <PackageTags>aspnetcore;antiforgery</PackageTags>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
<Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
Assert.Equal("additional data", token.AdditionalData); Assert.Equal("additional data", token.AdditionalData);
// Act & assert - 3 // Act & assert - 3
token.AdditionalData = null; token.AdditionalData = null!;
Assert.Equal("", token.AdditionalData); Assert.Equal("", token.AdditionalData);
} }
@ -91,7 +91,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
// Assert // Assert
Assert.NotNull(securityToken); Assert.NotNull(securityToken);
Assert.Equal(AntiforgeryToken.SecurityTokenBitLength, securityToken.BitLength); Assert.Equal(AntiforgeryToken.SecurityTokenBitLength, securityToken!.BitLength);
// check that we're not making a new one each property call // check that we're not making a new one each property call
Assert.Equal(securityToken, token.SecurityToken); Assert.Equal(securityToken, token.SecurityToken);
@ -123,10 +123,10 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
// Assert // Assert
Assert.NotNull(securityToken); Assert.NotNull(securityToken);
Assert.Equal(AntiforgeryToken.SecurityTokenBitLength, securityToken.BitLength); Assert.Equal(AntiforgeryToken.SecurityTokenBitLength, securityToken!.BitLength);
// check that we're not making a new one each property call // check that we're not making a new one each property call
Assert.Equal(securityToken, token.SecurityToken); Assert.Equal(securityToken, token.SecurityToken);
} }
} }
} }

View File

@ -57,7 +57,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
} }
[Theory] [Theory]
[InlineData((object[])null)] [InlineData((object[]?)null)]
[InlineData(new byte[] { 0x01, 0x02, 0x03 })] [InlineData(new byte[] { 0x01, 0x02, 0x03 })]
public void Ctor_Data_Bad(byte[] data) public void Ctor_Data_Bad(byte[] data)
{ {
@ -93,7 +93,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
{ {
// Arrange // Arrange
object blobA = new BinaryBlob(32); object blobA = new BinaryBlob(32);
object blobB = null; object? blobB = null;
// Act & assert // Act & assert
Assert.NotEqual(blobA, blobB); Assert.NotEqual(blobA, blobB);
@ -126,4 +126,4 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
Assert.Equal(expectedHashCode, actualHashCode); Assert.Equal(expectedHashCode, actualHashCode);
} }
} }
} }

View File

@ -509,7 +509,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
var antiforgeryFeature = new AntiforgeryFeature(); var antiforgeryFeature = new AntiforgeryFeature();
var context = CreateMockContext(new AntiforgeryOptions(), antiforgeryFeature: antiforgeryFeature); var context = CreateMockContext(new AntiforgeryOptions(), antiforgeryFeature: antiforgeryFeature);
string message; string? message;
context.TokenGenerator context.TokenGenerator
.Setup(o => o.TryValidateTokenSet( .Setup(o => o.TryValidateTokenSet(
context.HttpContext, context.HttpContext,
@ -543,7 +543,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
var context = CreateMockContext(new AntiforgeryOptions(), antiforgeryFeature: antiforgeryFeature); var context = CreateMockContext(new AntiforgeryOptions(), antiforgeryFeature: antiforgeryFeature);
context.HttpContext.Request.Method = "POST"; context.HttpContext.Request.Method = "POST";
string message; string? message;
context.TokenGenerator context.TokenGenerator
.Setup(o => o.TryValidateTokenSet( .Setup(o => o.TryValidateTokenSet(
context.HttpContext, context.HttpContext,
@ -583,7 +583,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
var context = CreateMockContext(new AntiforgeryOptions(), antiforgeryFeature: antiforgeryFeature); var context = CreateMockContext(new AntiforgeryOptions(), antiforgeryFeature: antiforgeryFeature);
context.HttpContext.Request.Method = "POST"; context.HttpContext.Request.Method = "POST";
string message; string? message;
context.TokenGenerator context.TokenGenerator
.Setup(o => o.TryValidateTokenSet( .Setup(o => o.TryValidateTokenSet(
context.HttpContext, context.HttpContext,
@ -622,7 +622,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
var context = CreateMockContext(new AntiforgeryOptions()); var context = CreateMockContext(new AntiforgeryOptions());
context.HttpContext.Request.Method = httpMethod; context.HttpContext.Request.Method = httpMethod;
string message; string? message;
context.TokenGenerator context.TokenGenerator
.Setup(o => o.TryValidateTokenSet( .Setup(o => o.TryValidateTokenSet(
context.HttpContext, context.HttpContext,
@ -659,7 +659,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
var context = CreateMockContext(new AntiforgeryOptions()); var context = CreateMockContext(new AntiforgeryOptions());
context.HttpContext.Request.Method = httpMethod; context.HttpContext.Request.Method = httpMethod;
string message; string? message;
context.TokenGenerator context.TokenGenerator
.Setup(o => o.TryValidateTokenSet( .Setup(o => o.TryValidateTokenSet(
context.HttpContext, context.HttpContext,
@ -718,7 +718,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
var antiforgeryFeature = new AntiforgeryFeature(); var antiforgeryFeature = new AntiforgeryFeature();
var context = CreateMockContext(new AntiforgeryOptions(), antiforgeryFeature: antiforgeryFeature); var context = CreateMockContext(new AntiforgeryOptions(), antiforgeryFeature: antiforgeryFeature);
string message; string? message;
context.TokenGenerator context.TokenGenerator
.Setup(o => o.TryValidateTokenSet( .Setup(o => o.TryValidateTokenSet(
context.HttpContext, context.HttpContext,
@ -859,7 +859,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
}; };
var context = CreateMockContext(new AntiforgeryOptions(), antiforgeryFeature: antiforgeryFeature); var context = CreateMockContext(new AntiforgeryOptions(), antiforgeryFeature: antiforgeryFeature);
string message; string? message;
context.TokenGenerator context.TokenGenerator
.Setup(o => o.TryValidateTokenSet( .Setup(o => o.TryValidateTokenSet(
context.HttpContext, context.HttpContext,
@ -1122,7 +1122,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
antiforgeryFeature: antiforgeryFeature); antiforgeryFeature: antiforgeryFeature);
var testTokenSet = new TestTokenSet var testTokenSet = new TestTokenSet
{ {
OldCookieTokenString = null OldCookieTokenString = null!
}; };
var nullTokenStore = GetTokenStore(context.HttpContext, testTokenSet, false); var nullTokenStore = GetTokenStore(context.HttpContext, testTokenSet, false);
@ -1135,7 +1135,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
antiforgery.SetCookieTokenAndHeader(context.HttpContext); antiforgery.SetCookieTokenAndHeader(context.HttpContext);
// Assert // Assert
context.TokenSerializer.Verify(s => s.Deserialize(null), Times.Never); context.TokenSerializer.Verify(s => s.Deserialize(null!), Times.Never);
} }
[Fact] [Fact]
@ -1159,7 +1159,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
antiforgeryFeature: antiforgeryFeature); antiforgeryFeature: antiforgeryFeature);
var testTokenSet = new TestTokenSet var testTokenSet = new TestTokenSet
{ {
OldCookieTokenString = null OldCookieTokenString = null!
}; };
var nullTokenStore = GetTokenStore(context.HttpContext, testTokenSet, false); var nullTokenStore = GetTokenStore(context.HttpContext, testTokenSet, false);
@ -1285,10 +1285,10 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
private DefaultAntiforgery GetAntiforgery( private DefaultAntiforgery GetAntiforgery(
HttpContext httpContext, HttpContext httpContext,
AntiforgeryOptions options = null, AntiforgeryOptions? options = null,
IAntiforgeryTokenGenerator tokenGenerator = null, IAntiforgeryTokenGenerator? tokenGenerator = null,
IAntiforgeryTokenSerializer tokenSerializer = null, IAntiforgeryTokenSerializer? tokenSerializer = null,
IAntiforgeryTokenStore tokenStore = null) IAntiforgeryTokenStore? tokenStore = null)
{ {
var optionsManager = new TestOptionsManager(); var optionsManager = new TestOptionsManager();
if (options != null) if (options != null)
@ -1299,9 +1299,9 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
var loggerFactory = httpContext.RequestServices.GetRequiredService<ILoggerFactory>(); var loggerFactory = httpContext.RequestServices.GetRequiredService<ILoggerFactory>();
return new DefaultAntiforgery( return new DefaultAntiforgery(
antiforgeryOptionsAccessor: optionsManager, antiforgeryOptionsAccessor: optionsManager,
tokenGenerator: tokenGenerator, tokenGenerator: tokenGenerator!,
tokenSerializer: tokenSerializer, tokenSerializer: tokenSerializer!,
tokenStore: tokenStore, tokenStore: tokenStore!,
loggerFactory: loggerFactory); loggerFactory: loggerFactory);
} }
@ -1313,7 +1313,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
return builder.BuildServiceProvider(); return builder.BuildServiceProvider();
} }
private HttpContext GetHttpContext(IAntiforgeryFeature antiforgeryFeature = null) private HttpContext GetHttpContext(IAntiforgeryFeature? antiforgeryFeature = null)
{ {
var httpContext = new DefaultHttpContext(); var httpContext = new DefaultHttpContext();
antiforgeryFeature = antiforgeryFeature ?? new AntiforgeryFeature(); antiforgeryFeature = antiforgeryFeature ?? new AntiforgeryFeature();
@ -1388,7 +1388,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
AntiforgeryOptions options, AntiforgeryOptions options,
bool useOldCookie = false, bool useOldCookie = false,
bool isOldCookieValid = true, bool isOldCookieValid = true,
IAntiforgeryFeature antiforgeryFeature = null) IAntiforgeryFeature? antiforgeryFeature = null)
{ {
// Arrange // Arrange
var httpContext = GetHttpContext(antiforgeryFeature); var httpContext = GetHttpContext(antiforgeryFeature);
@ -1445,32 +1445,32 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
private class TestTokenSet private class TestTokenSet
{ {
public AntiforgeryToken RequestToken { get; set; } public AntiforgeryToken RequestToken { get; set; } = default!;
public string FormTokenString { get; set; } public string FormTokenString { get; set; } = default!;
public AntiforgeryToken OldCookieToken { get; set; } public AntiforgeryToken OldCookieToken { get; set; } = default!;
public string OldCookieTokenString { get; set; } public string OldCookieTokenString { get; set; } = default!;
public AntiforgeryToken NewCookieToken { get; set; } public AntiforgeryToken NewCookieToken { get; set; } = default!;
public string NewCookieTokenString { get; set; } public string NewCookieTokenString { get; set; } = default!;
} }
private class AntiforgeryMockContext private class AntiforgeryMockContext
{ {
public AntiforgeryOptions Options { get; set; } public AntiforgeryOptions Options { get; set; } = default!;
public TestTokenSet TestTokenSet { get; set; } public TestTokenSet TestTokenSet { get; set; } = default!;
public HttpContext HttpContext { get; set; } public HttpContext HttpContext { get; set; } = default!;
public Mock<IAntiforgeryTokenGenerator> TokenGenerator { get; set; } public Mock<IAntiforgeryTokenGenerator> TokenGenerator { get; set; } = default!;
public Mock<IAntiforgeryTokenStore> TokenStore { get; set; } public Mock<IAntiforgeryTokenStore> TokenStore { get; set; } = default!;
public Mock<IAntiforgeryTokenSerializer> TokenSerializer { get; set; } public Mock<IAntiforgeryTokenSerializer> TokenSerializer { get; set; } = default!;
} }
private class TestOptionsManager : IOptions<AntiforgeryOptions> private class TestOptionsManager : IOptions<AntiforgeryOptions>

View File

@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#nullable disable
using System; using System;
using System.Security.Claims; using System.Security.Claims;
using System.Security.Cryptography; using System.Security.Cryptography;
@ -621,3 +622,4 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
} }
} }
} }
#nullable restore

View File

@ -282,7 +282,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
Assert.NotNull(cookies); Assert.NotNull(cookies);
Assert.Equal(_cookieName, cookies.Key); Assert.Equal(_cookieName, cookies.Key);
Assert.Equal("serialized-value", cookies.Value); Assert.Equal("serialized-value", cookies.Value);
Assert.True(cookies.Options.HttpOnly); Assert.True(cookies.Options!.HttpOnly);
Assert.Equal(defaultCookieSecureValue, cookies.Options.Secure); Assert.Equal(defaultCookieSecureValue, cookies.Options.Secure);
} }
@ -321,7 +321,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
Assert.NotNull(cookies); Assert.NotNull(cookies);
Assert.Equal(_cookieName, cookies.Key); Assert.Equal(_cookieName, cookies.Key);
Assert.Equal("serialized-value", cookies.Value); Assert.Equal("serialized-value", cookies.Value);
Assert.True(cookies.Options.HttpOnly); Assert.True(cookies.Options!.HttpOnly);
Assert.Equal(expectedCookiePath, cookies.Options.Path); Assert.Equal(expectedCookiePath, cookies.Options.Path);
} }
@ -361,7 +361,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
Assert.NotNull(cookies); Assert.NotNull(cookies);
Assert.Equal(_cookieName, cookies.Key); Assert.Equal(_cookieName, cookies.Key);
Assert.Equal("serialized-value", cookies.Value); Assert.Equal("serialized-value", cookies.Value);
Assert.True(cookies.Options.HttpOnly); Assert.True(cookies.Options!.HttpOnly);
Assert.Equal(expectedCookiePath, cookies.Options.Path); Assert.Equal(expectedCookiePath, cookies.Options.Path);
} }
@ -400,7 +400,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
Assert.NotNull(cookies); Assert.NotNull(cookies);
Assert.Equal(_cookieName, cookies.Key); Assert.Equal(_cookieName, cookies.Key);
Assert.Equal("serialized-value", cookies.Value); Assert.Equal("serialized-value", cookies.Value);
Assert.True(cookies.Options.HttpOnly); Assert.True(cookies.Options!.HttpOnly);
Assert.Equal("/vdir1", cookies.Options.Path); Assert.Equal("/vdir1", cookies.Options.Path);
Assert.Equal(expectedCookieDomain, cookies.Options.Domain); Assert.Equal(expectedCookieDomain, cookies.Options.Domain);
} }
@ -421,9 +421,9 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
private class MockResponseCookieCollection : IResponseCookies private class MockResponseCookieCollection : IResponseCookies
{ {
public string Key { get; set; } public string? Key { get; set; }
public string Value { get; set; } public string? Value { get; set; }
public CookieOptions Options { get; set; } public CookieOptions? Options { get; set; }
public int Count { get; set; } public int Count { get; set; }
public void Append(string key, string value, CookieOptions options) public void Append(string key, string value, CookieOptions options)

View File

@ -65,7 +65,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
var claimsIdentity = (ClaimsIdentity)identity; var claimsIdentity = (ClaimsIdentity)identity;
// Act // Act
var identiferParameters = DefaultClaimUidExtractor.GetUniqueIdentifierParameters(new ClaimsIdentity[] { claimsIdentity }) var identiferParameters = DefaultClaimUidExtractor.GetUniqueIdentifierParameters(new ClaimsIdentity[] { claimsIdentity })!
.ToArray(); .ToArray();
var claims = claimsIdentity.Claims.ToList(); var claims = claimsIdentity.Claims.ToList();
claims.Sort((a, b) => string.Compare(a.Type, b.Type, StringComparison.Ordinal)); claims.Sort((a, b) => string.Compare(a.Type, b.Type, StringComparison.Ordinal));
@ -258,4 +258,4 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
}, uniqueIdentifierParameters); }, uniqueIdentifierParameters);
} }
} }
} }

View File

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework> <TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>