Cleanup logging in SignInManager

This commit is contained in:
Hao Kung 2015-06-10 15:13:28 -07:00
Родитель 4e5bba35da
Коммит e2d8bfe5cf
2 изменённых файлов: 77 добавлений и 128 удалений

Просмотреть файл

@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Hosting;
@ -90,14 +89,16 @@ namespace Microsoft.AspNet.Identity
{
if (Options.SignIn.RequireConfirmedEmail && !(await UserManager.IsEmailConfirmedAsync(user)))
{
return Logger.Log(false);
Logger.LogWarning("User {userId} cannot sign in without a confirmed email.", await UserManager.GetUserIdAsync(user));
return false;
}
if (Options.SignIn.RequireConfirmedPhoneNumber && !(await UserManager.IsPhoneNumberConfirmedAsync(user)))
{
return Logger.Log(false);
Logger.LogWarning("User {userId} cannot sign in without a confirmed phone number.", await UserManager.GetUserIdAsync(user));
return false;
}
return Logger.Log(true);
return true;
}
/// <summary>
@ -197,34 +198,32 @@ namespace Microsoft.AspNet.Identity
throw new ArgumentNullException(nameof(user));
}
using (await BeginLoggingScopeAsync(user))
var error = await PreSignInCheck(user);
if (error != null)
{
var error = await PreSignInCheck(user);
if (error != null)
{
return Logger.Log(error);
}
if (await IsLockedOut(user))
{
return Logger.Log(SignInResult.LockedOut);
}
if (await UserManager.CheckPasswordAsync(user, password))
{
await ResetLockout(user);
return Logger.Log(await SignInOrTwoFactorAsync(user, isPersistent));
}
if (UserManager.SupportsUserLockout && shouldLockout)
{
// If lockout is requested, increment access failed count which might lock out the user
await UserManager.AccessFailedAsync(user);
if (await UserManager.IsLockedOutAsync(user))
{
return Logger.Log(SignInResult.LockedOut);
}
}
return Logger.Log(SignInResult.Failed);
return error;
}
if (await IsLockedOut(user))
{
return await LockedOut(user);
}
if (await UserManager.CheckPasswordAsync(user, password))
{
await ResetLockout(user);
return await SignInOrTwoFactorAsync(user, isPersistent);
}
Logger.LogWarning("User {userId} failed to provide the correct password.", await UserManager.GetUserIdAsync(user));
if (UserManager.SupportsUserLockout && shouldLockout)
{
// If lockout is requested, increment access failed count which might lock out the user
await UserManager.AccessFailedAsync(user);
if (await UserManager.IsLockedOutAsync(user))
{
return await LockedOut(user);
}
}
return SignInResult.Failed;
}
/// <summary>
@ -315,34 +314,31 @@ namespace Microsoft.AspNet.Identity
return SignInResult.Failed;
}
using (await BeginLoggingScopeAsync(user))
var error = await PreSignInCheck(user);
if (error != null)
{
var error = await PreSignInCheck(user);
if (error != null)
{
return Logger.Log(error);
}
if (await UserManager.VerifyTwoFactorTokenAsync(user, provider, code))
{
// When token is verified correctly, clear the access failed count used for lockout
await ResetLockout(user);
// Cleanup external cookie
if (twoFactorInfo.LoginProvider != null)
{
Context.Authentication.SignOut(IdentityOptions.ExternalCookieAuthenticationScheme);
}
if (rememberClient)
{
await RememberTwoFactorClientAsync(user);
}
await UserManager.ResetAccessFailedCountAsync(user);
await SignInAsync(user, isPersistent, twoFactorInfo.LoginProvider);
return Logger.Log(SignInResult.Success);
}
// If the token is incorrect, record the failure which also may cause the user to be locked out
await UserManager.AccessFailedAsync(user);
return Logger.Log(SignInResult.Failed);
return error;
}
if (await UserManager.VerifyTwoFactorTokenAsync(user, provider, code))
{
// When token is verified correctly, clear the access failed count used for lockout
await ResetLockout(user);
// Cleanup external cookie
if (twoFactorInfo.LoginProvider != null)
{
Context.Authentication.SignOut(IdentityOptions.ExternalCookieAuthenticationScheme);
}
if (rememberClient)
{
await RememberTwoFactorClientAsync(user);
}
await UserManager.ResetAccessFailedCountAsync(user);
await SignInAsync(user, isPersistent, twoFactorInfo.LoginProvider);
return SignInResult.Success;
}
// If the token is incorrect, record the failure which also may cause the user to be locked out
await UserManager.AccessFailedAsync(user);
return SignInResult.Failed;
}
/// <summary>
@ -377,15 +373,12 @@ namespace Microsoft.AspNet.Identity
return SignInResult.Failed;
}
using (await BeginLoggingScopeAsync(user))
var error = await PreSignInCheck(user);
if (error != null)
{
var error = await PreSignInCheck(user);
if (error != null)
{
return Logger.Log(error);
}
return Logger.Log(await SignInOrTwoFactorAsync(user, isPersistent, loginProvider));
return error;
}
return await SignInOrTwoFactorAsync(user, isPersistent, loginProvider);
}
/// <summary>
@ -451,18 +444,6 @@ namespace Microsoft.AspNet.Identity
return properties;
}
/// <summary>
/// Starts a scope for wrapping log messages, as an asynchronous operation.
/// </summary>
/// <param name="user">The current user.</param>
/// <param name="methodName">The method that called this method.</param>
/// <returns>The task object representing the asynchronous operation.</returns>
protected virtual async Task<IDisposable> BeginLoggingScopeAsync(TUser user, [CallerMemberName] string methodName = null)
{
var state = Resources.FormatLoggingResultMessageForUser(methodName, await UserManager.GetUserIdAsync(user));
return Logger?.BeginScope(state);
}
/// <summary>
/// Creates a claims principal for the specified 2fa information.
/// </summary>
@ -538,6 +519,12 @@ namespace Microsoft.AspNet.Identity
return UserManager.SupportsUserLockout && await UserManager.IsLockedOutAsync(user);
}
private async Task<SignInResult> LockedOut(TUser user)
{
Logger.LogWarning("User {userId} is currently locked out.", await UserManager.GetUserIdAsync(user));
return SignInResult.LockedOut;
}
private async Task<SignInResult> PreSignInCheck(TUser user)
{
if (!await CanSignInAsync(user))
@ -546,7 +533,7 @@ namespace Microsoft.AspNet.Identity
}
if (await IsLockedOut(user))
{
return SignInResult.LockedOut;
return await LockedOut(user);
}
return null;
}

Просмотреть файл

@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Security.Claims;
using System.Text;
@ -77,7 +78,6 @@ namespace Microsoft.AspNet.Identity.Test
Assert.Throws<ArgumentNullException>("claimsFactory", () => new SignInManager<TestUser>(userManager, contextAccessor.Object, null, null, null));
}
//TODO: Mock fails in K (this works fine in net45)
//[Fact]
//public async Task EnsureClaimsPrincipalFactoryCreateIdentityCalled()
//{
@ -86,9 +86,8 @@ namespace Microsoft.AspNet.Identity.Test
// var userManager = MockHelpers.TestUserManager<TestUser>();
// var identityFactory = new Mock<IUserClaimsPrincipalFactory<TestUser>>();
// const string authType = "Test";
// var testIdentity = new ClaimsIdentity(authType);
// identityFactory.Setup(s => s.CreateAsync(userManager, user, authType)).ReturnsAsync(testIdentity).Verifiable();
// userManager.UserClaimsPrincipalFactory = identityFactory.Object;
// var testIdentity = new ClaimsPrincipal();
// identityFactory.Setup(s => s.CreateAsync(user)).ReturnsAsync(testIdentity).Verifiable();
// var context = new Mock<HttpContext>();
// var response = new Mock<HttpResponse>();
// context.Setup(c => c.Response).Returns(response.Object).Verifiable();
@ -126,10 +125,7 @@ namespace Microsoft.AspNet.Identity.Test
var claimsFactory = new UserClaimsPrincipalFactory<TestUser, TestRole>(manager.Object, roleManager.Object, options.Object);
var logStore = new StringBuilder();
var logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore);
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory, options.Object, null);
helper.Logger = logger.Object;
var expectedScope = string.Format("{0} for {1}: {2}", "PasswordSignInAsync", "user", user.Id);
var expectedLog = string.Format("{0} : {1}", "PasswordSignInAsync", "Lockedout");
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory, options.Object, logger.Object);
// Act
var result = await helper.PasswordSignInAsync(user.UserName, "bogus", false, false);
@ -137,8 +133,7 @@ namespace Microsoft.AspNet.Identity.Test
// Assert
Assert.False(result.Succeeded);
Assert.True(result.IsLockedOut);
Assert.NotEqual(-1, logStore.ToString().IndexOf(expectedLog));
Assert.NotEqual(-1, logStore.ToString().IndexOf(expectedScope));
Assert.True(logStore.ToString().Contains($"User {user.Id} is currently locked out."));
manager.Verify();
}
@ -162,10 +157,7 @@ namespace Microsoft.AspNet.Identity.Test
options.Setup(a => a.Options).Returns(identityOptions);
var claimsFactory = new UserClaimsPrincipalFactory<TestUser, TestRole>(manager, roleManager.Object, options.Object);
var sm = new SignInManager<TestUser>(manager, contextAccessor.Object, claimsFactory, options.Object, null);
if (logStore != null)
{
sm.Logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore).Object;
}
sm.Logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore ?? new StringBuilder()).Object;
return sm;
}
@ -185,18 +177,13 @@ namespace Microsoft.AspNet.Identity.Test
var auth = new Mock<AuthenticationManager>();
context.Setup(c => c.Authentication).Returns(auth.Object).Verifiable();
SetupSignIn(auth, user.Id, isPersistent);
var logStore = new StringBuilder();
var helper = SetupSignInManager(manager.Object, context.Object, logStore);
var expectedScope = string.Format("{0} for {1}: {2}", "PasswordSignInAsync", "user", user.Id);
var expectedLog = string.Format("{0} : {1}", "PasswordSignInAsync", "Succeeded");
var helper = SetupSignInManager(manager.Object, context.Object);
// Act
var result = await helper.PasswordSignInAsync(user.UserName, "password", isPersistent, false);
// Assert
Assert.True(result.Succeeded);
Assert.NotEqual(-1, logStore.ToString().IndexOf(expectedLog));
Assert.NotEqual(-1, logStore.ToString().IndexOf(expectedScope));
manager.Verify();
context.Verify();
auth.Verify();
@ -285,10 +272,7 @@ namespace Microsoft.AspNet.Identity.Test
It.Is<ClaimsPrincipal>(id => id.FindFirstValue(ClaimTypes.Name) == user.Id),
It.IsAny<AuthenticationProperties>())).Verifiable();
context.Setup(c => c.Authentication).Returns(auth.Object).Verifiable();
var logStore = new StringBuilder();
var helper = SetupSignInManager(manager.Object, context.Object, logStore);
var expectedScope = string.Format("{0} for {1}: {2}", "PasswordSignInAsync", "user", user.Id);
var expectedLog = string.Format("{0} : {1}", "PasswordSignInAsync", "RequiresTwoFactor");
var helper = SetupSignInManager(manager.Object, context.Object);
// Act
var result = await helper.PasswordSignInAsync(user.UserName, "password", false, false);
@ -296,8 +280,6 @@ namespace Microsoft.AspNet.Identity.Test
// Assert
Assert.False(result.Succeeded);
Assert.True(result.RequiresTwoFactor);
Assert.NotEqual(-1, logStore.ToString().IndexOf(expectedLog));
Assert.NotEqual(-1, logStore.ToString().IndexOf(expectedScope));
manager.Verify();
context.Verify();
auth.Verify();
@ -326,18 +308,13 @@ namespace Microsoft.AspNet.Identity.Test
var auth = new Mock<AuthenticationManager>();
context.Setup(c => c.Authentication).Returns(auth.Object).Verifiable();
SetupSignIn(auth, user.Id, isPersistent, loginProvider);
var logStore = new StringBuilder();
var helper = SetupSignInManager(manager.Object, context.Object, logStore);
var expectedScope = string.Format("{0} for {1}: {2}", "ExternalLoginSignInAsync", "user", user.Id);
var expectedLog = string.Format("{0} : {1}", "ExternalLoginSignInAsync", "Succeeded");
var helper = SetupSignInManager(manager.Object, context.Object);
// Act
var result = await helper.ExternalLoginSignInAsync(loginProvider, providerKey, isPersistent);
// Assert
Assert.True(result.Succeeded);
Assert.NotEqual(-1, logStore.ToString().IndexOf(expectedLog));
Assert.NotEqual(-1, logStore.ToString().IndexOf(expectedScope));
manager.Verify();
context.Verify();
auth.Verify();
@ -442,18 +419,13 @@ namespace Microsoft.AspNet.Identity.Test
}
auth.Setup(a => a.AuthenticateAsync(IdentityOptions.TwoFactorUserIdCookieAuthenticationScheme)).ReturnsAsync(authResult).Verifiable();
context.Setup(c => c.Authentication).Returns(auth.Object).Verifiable();
var logStore = new StringBuilder();
var helper = SetupSignInManager(manager.Object, context.Object, logStore);
var expectedScope = string.Format("{0} for {1}: {2}", "TwoFactorSignInAsync", "user", user.Id);
var expectedLog = string.Format("{0} : {1}", "TwoFactorSignInAsync", "Succeeded");
var helper = SetupSignInManager(manager.Object, context.Object);
// Act
var result = await helper.TwoFactorSignInAsync(provider, code, isPersistent, rememberClient);
// Assert
Assert.True(result.Succeeded);
Assert.NotEqual(-1, logStore.ToString().IndexOf(expectedLog));
Assert.NotEqual(-1, logStore.ToString().IndexOf(expectedScope));
manager.Verify();
context.Verify();
auth.Verify();
@ -535,8 +507,7 @@ namespace Microsoft.AspNet.Identity.Test
auth.Setup(a => a.SignOut(IdentityOptions.TwoFactorUserIdCookieAuthenticationScheme)).Verifiable();
auth.Setup(a => a.SignOut(IdentityOptions.ExternalCookieAuthenticationScheme)).Verifiable();
IdentityOptions.ApplicationCookieAuthenticationScheme = authenticationScheme;
var logStore = new StringBuilder();
var helper = SetupSignInManager(manager.Object, context.Object, logStore);
var helper = SetupSignInManager(manager.Object, context.Object);
// Act
helper.SignOut();
@ -558,15 +529,12 @@ namespace Microsoft.AspNet.Identity.Test
var context = new Mock<HttpContext>();
var logStore = new StringBuilder();
var helper = SetupSignInManager(manager.Object, context.Object, logStore);
var expectedScope = string.Format("{0} for {1}: {2}", "PasswordSignInAsync", "user", user.Id);
var expectedLog = string.Format("{0} : {1}", "PasswordSignInAsync", "Failed");
// Act
var result = await helper.PasswordSignInAsync(user.UserName, "bogus", false, false);
// Assert
Assert.False(result.Succeeded);
Assert.NotEqual(-1, logStore.ToString().IndexOf(expectedLog));
Assert.NotEqual(-1, logStore.ToString().IndexOf(expectedScope));
Assert.True(logStore.ToString().Contains($"User {user.Id} failed to provide the correct password."));
manager.Verify();
context.Verify();
}
@ -641,8 +609,6 @@ namespace Microsoft.AspNet.Identity.Test
identityOptions.SignIn.RequireConfirmedEmail = true;
var logStore = new StringBuilder();
var helper = SetupSignInManager(manager.Object, context.Object, logStore, identityOptions);
var expectedScope = string.Format("{0} for {1}: {2}", "PasswordSignInAsync", "user", user.Id);
var expectedLog = string.Format("{0} : {1}", "CanSignInAsync", confirmed.ToString());
// Act
var result = await helper.PasswordSignInAsync(user, "password", false, false);
@ -651,8 +617,7 @@ namespace Microsoft.AspNet.Identity.Test
Assert.Equal(confirmed, result.Succeeded);
Assert.NotEqual(confirmed, result.IsNotAllowed);
Assert.NotEqual(-1, logStore.ToString().IndexOf(expectedLog));
Assert.NotEqual(-1, logStore.ToString().IndexOf(expectedScope));
Assert.Equal(confirmed, !logStore.ToString().Contains($"User {user.Id} cannot sign in without a confirmed email."));
manager.Verify();
context.Verify();
@ -690,8 +655,6 @@ namespace Microsoft.AspNet.Identity.Test
identityOptions.SignIn.RequireConfirmedPhoneNumber = true;
var logStore = new StringBuilder();
var helper = SetupSignInManager(manager.Object, context.Object, logStore, identityOptions);
var expectedScope = string.Format("{0} for {1}: {2}", "PasswordSignInAsync", "user", user.Id);
var expectedLog = string.Format("{0} : {1}", "CanSignInAsync", confirmed.ToString());
// Act
var result = await helper.PasswordSignInAsync(user, "password", false, false);
@ -699,8 +662,7 @@ namespace Microsoft.AspNet.Identity.Test
// Assert
Assert.Equal(confirmed, result.Succeeded);
Assert.NotEqual(confirmed, result.IsNotAllowed);
Assert.NotEqual(-1, logStore.ToString().IndexOf(expectedLog));
Assert.NotEqual(-1, logStore.ToString().IndexOf(expectedScope));
Assert.Equal(confirmed, !logStore.ToString().Contains($"User {user.Id} cannot sign in without a confirmed phone number."));
manager.Verify();
context.Verify();
auth.Verify();