Browse Source

fix(identity-server): Fixed identityServer login model

- Modify base class source
pull/1222/head
colin 8 months ago
parent
commit
fdcf4d7b01
  1. 179
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web.IdentityServer/Pages/Account/TwoFactorSupportedLoginModel.cs

179
aspnet-core/modules/account/LINGYUN.Abp.Account.Web.IdentityServer/Pages/Account/TwoFactorSupportedLoginModel.cs

@ -1,14 +1,23 @@
using IdentityServer4.Services;
using IdentityServer4.Events;
using IdentityServer4.Models;
using IdentityServer4.Services;
using IdentityServer4.Stores;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Account.Settings;
using Volo.Abp.Account.Web;
using Volo.Abp.Account.Web.Pages.Account;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Identity;
using Volo.Abp.IdentityServer.AspNetIdentity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Settings;
using IdentityOptions = Microsoft.AspNetCore.Identity.IdentityOptions;
namespace LINGYUN.Abp.Account.Web.IdentityServer.Pages.Account
@ -17,20 +26,161 @@ namespace LINGYUN.Abp.Account.Web.IdentityServer.Pages.Account
/// 重写登录模型,实现双因素登录
/// </summary>
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(LoginModel), typeof(IdentityServerSupportedLoginModel))]
public class TwoFactorSupportedLoginModel : IdentityServerSupportedLoginModel
[ExposeServices(
typeof(LINGYUN.Abp.Account.Web.Pages.Account.LoginModel),
typeof(IdentityServerSupportedLoginModel))]
public class TwoFactorSupportedLoginModel : LINGYUN.Abp.Account.Web.Pages.Account.LoginModel
{
protected IIdentityServerInteractionService Interaction { get; }
protected IEventService IdentityServerEvents { get; }
protected IClientStore ClientStore { get; }
public TwoFactorSupportedLoginModel(
IAuthenticationSchemeProvider schemeProvider,
IOptions<AbpAccountOptions> accountOptions,
IAuthenticationSchemeProvider schemeProvider,
IOptions<AbpAccountOptions> accountOptions,
IOptions<IdentityOptions> identityOptions,
IIdentityServerInteractionService interaction,
IdentityDynamicClaimsPrincipalContributorCache identityDynamicClaimsPrincipalContributorCache,
IClientStore clientStore,
IEventService identityServerEvents)
: base(schemeProvider, accountOptions, identityOptions, identityDynamicClaimsPrincipalContributorCache, interaction, clientStore, identityServerEvents)
IIdentityServerInteractionService interaction,
IEventService identityServerEvents,
IClientStore clientStore)
: base(schemeProvider, accountOptions, identityOptions, identityDynamicClaimsPrincipalContributorCache)
{
Interaction = interaction;
ClientStore = clientStore;
IdentityServerEvents = identityServerEvents;
}
public override async Task<IActionResult> OnGetAsync()
{
LoginInput = new LoginInputModel();
var context = await Interaction.GetAuthorizationContextAsync(ReturnUrl);
if (context != null)
{
// TODO: Find a proper cancel way.
// ShowCancelButton = true;
LoginInput.UserNameOrEmailAddress = context.LoginHint;
//TODO: Reference AspNetCore MultiTenancy module and use options to get the tenant key!
var tenant = context.Parameters[TenantResolverConsts.DefaultTenantKey];
if (!string.IsNullOrEmpty(tenant))
{
CurrentTenant.Change(Guid.Parse(tenant));
Response.Cookies.Append(TenantResolverConsts.DefaultTenantKey, tenant);
}
}
if (context?.IdP != null)
{
LoginInput.UserNameOrEmailAddress = context.LoginHint;
ExternalProviders = new[] { new ExternalProviderModel { AuthenticationScheme = context.IdP } };
return Page();
}
var providers = await GetExternalProviders();
ExternalProviders = providers.ToList();
EnableLocalLogin = await SettingProvider.IsTrueAsync(AccountSettingNames.EnableLocalLogin);
if (context?.Client?.ClientId != null)
{
var client = await ClientStore.FindEnabledClientByIdAsync(context?.Client?.ClientId);
if (client != null)
{
EnableLocalLogin = client.EnableLocalLogin;
if (client.IdentityProviderRestrictions != null && client.IdentityProviderRestrictions.Any())
{
providers = providers.Where(provider => client.IdentityProviderRestrictions.Contains(provider.AuthenticationScheme)).ToList();
}
}
}
if (IsExternalLoginOnly)
{
return await base.OnPostExternalLogin(providers.First().AuthenticationScheme);
}
return Page();
}
public override async Task<IActionResult> OnPostAsync(string action)
{
var context = await Interaction.GetAuthorizationContextAsync(ReturnUrl);
if (action == "Cancel")
{
if (context == null)
{
return Redirect("~/");
}
await Interaction.GrantConsentAsync(context, new ConsentResponse()
{
Error = AuthorizationError.AccessDenied
});
return Redirect(ReturnUrl);
}
await CheckLocalLoginAsync();
ValidateModel();
await IdentityOptions.SetAsync();
ExternalProviders = await GetExternalProviders();
EnableLocalLogin = await SettingProvider.IsTrueAsync(AccountSettingNames.EnableLocalLogin);
await ReplaceEmailToUsernameOfInputIfNeeds();
var result = await SignInManager.PasswordSignInAsync(
LoginInput.UserNameOrEmailAddress,
LoginInput.Password,
LoginInput.RememberMe,
true
);
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{
Identity = IdentitySecurityLogIdentityConsts.Identity,
Action = result.ToIdentitySecurityLogAction(),
UserName = LoginInput.UserNameOrEmailAddress,
ClientId = context?.Client?.ClientId
});
if (result.RequiresTwoFactor)
{
return await TwoFactorLoginResultAsync();
}
if (result.IsLockedOut)
{
return await HandleUserLockedOut();
}
if (result.IsNotAllowed)
{
return await HandleUserNotAllowed();
}
if (!result.Succeeded)
{
return await HandleUserNameOrPasswordInvalid();
}
//TODO: Find a way of getting user's id from the logged in user and do not query it again like that!
var user = await UserManager.FindByNameAsync(LoginInput.UserNameOrEmailAddress) ??
await UserManager.FindByEmailAsync(LoginInput.UserNameOrEmailAddress);
Debug.Assert(user != null, nameof(user) + " != null");
await IdentityServerEvents.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id.ToString(), user.UserName)); //TODO: Use user's name once implemented
// Clear the dynamic claims cache.
await IdentityDynamicClaimsPrincipalContributorCache.ClearAsync(user.Id, user.TenantId);
return await RedirectSafelyAsync(ReturnUrl, ReturnUrlHash);
}
protected async override Task<List<ExternalProviderModel>> GetExternalProviders()
@ -53,16 +203,5 @@ namespace LINGYUN.Abp.Account.Web.IdentityServer.Pages.Account
return providers;
}
protected override Task<IActionResult> TwoFactorLoginResultAsync()
{
// 重定向双因素认证页面
return Task.FromResult<IActionResult>(RedirectToPage("SendCode", new
{
returnUrl = ReturnUrl,
returnUrlHash = ReturnUrlHash,
rememberMe = LoginInput.RememberMe
}));
}
}
}

Loading…
Cancel
Save