Browse Source

Merge pull request #1229 from colinin/refactor-register

feat(account): 重写注册页面
pull/1238/head
yx lin 10 months ago
committed by GitHub
parent
commit
1867f7df5b
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 53
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web/Pages/Account/Register.cshtml
  2. 291
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web/Pages/Account/Register.cshtml.cs

53
aspnet-core/modules/account/LINGYUN.Abp.Account.Web/Pages/Account/Register.cshtml

@ -0,0 +1,53 @@
@page
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.Account.Localization
@model LINGYUN.Abp.Account.Web.Pages.Account.RegisterModel
@inject IHtmlLocalizer<AccountResource> L
<div class="card mt-3 shadow-sm rounded">
<div class="card-body p-5">
<h4>@L["Register"]</h4>
<strong>
@L["AlreadyRegistered"]
<a href="@Url.Page("./Login", new {returnUrl = Model.ReturnUrl, returnUrlHash = Model.ReturnUrlHash})" class="text-decoration-none">@L["Login"]</a>
</strong>
<form method="post" class="mt-4">
@if (Model.EnableLocalRegister || Model.IsExternalLogin)
{
<abp-input asp-for="Input.UserName" auto-focus="true" />
}
@if (Model.EnableLocalRegister || Model.IsExternalLogin)
{
<abp-input asp-for="Input.EmailAddress" />
}
@if (!Model.IsExternalLogin && Model.EnableLocalRegister)
{
<abp-input asp-for="Input.Password" />
}
@if (Model.EnableLocalRegister || Model.IsExternalLogin)
{
<div class="d-grid gap-2">
<abp-button button-type="Primary" type="submit" class="btn-lg mt-4">@L["Register"]</abp-button>
</div>
}
</form>
@if (!Model.IsExternalLogin && Model.VisibleExternalProviders.Any())
{
<div class="mt-2">
<h5>@L["OrRegisterWith"]</h5>
<form asp-page="./Login" asp-page-handler="ExternalLogin" asp-route-returnUrl="@Model.ReturnUrl" asp-route-returnUrlHash="@Model.ReturnUrlHash" method="post">
@foreach (var provider in Model.VisibleExternalProviders)
{
@await Component.InvokeAsync(provider.ComponentType, provider);
}
</form>
</div>
}
</div>
</div>

291
aspnet-core/modules/account/LINGYUN.Abp.Account.Web/Pages/Account/Register.cshtml.cs

@ -0,0 +1,291 @@
using LINGYUN.Abp.Account.Web.ExternalProviders;
using LINGYUN.Abp.Account.Web.Models;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Account;
using Volo.Abp.Account.Settings;
using Volo.Abp.Account.Web;
using Volo.Abp.Account.Web.Pages.Account;
using Volo.Abp.Auditing;
using Volo.Abp.Identity;
using Volo.Abp.Reflection;
using Volo.Abp.Security.Claims;
using Volo.Abp.Settings;
using Volo.Abp.Validation;
using IAbpAccountAppService = Volo.Abp.Account.IAccountAppService;
using IdentityUser = Volo.Abp.Identity.IdentityUser;
namespace LINGYUN.Abp.Account.Web.Pages.Account;
public class RegisterModel : AccountPageModel
{
[BindProperty(SupportsGet = true)]
public string ReturnUrl { get; set; }
[BindProperty(SupportsGet = true)]
public string ReturnUrlHash { get; set; }
[BindProperty]
public PostInput Input { get; set; }
[BindProperty(SupportsGet = true)]
public bool IsExternalLogin { get; set; }
[BindProperty(SupportsGet = true)]
public string ExternalLoginAuthSchema { get; set; }
public IEnumerable<ExternalLoginProviderModel> ExternalProviders { get; set; }
public IEnumerable<ExternalLoginProviderModel> VisibleExternalProviders => ExternalProviders.Where(x => !string.IsNullOrWhiteSpace(x.DisplayName));
public bool EnableLocalRegister { get; set; }
public bool IsExternalLoginOnly => EnableLocalRegister == false && ExternalProviders?.Count() == 1;
public string ExternalLoginScheme => IsExternalLoginOnly ? ExternalProviders?.SingleOrDefault()?.AuthenticationScheme : null;
protected IExternalProviderService ExternalProviderService { get; }
protected IAuthenticationSchemeProvider SchemeProvider { get; }
protected AbpAccountOptions AccountOptions { get; }
protected IdentityDynamicClaimsPrincipalContributorCache IdentityDynamicClaimsPrincipalContributorCache { get; }
public RegisterModel(
IExternalProviderService externalProviderService,
IAbpAccountAppService accountAppService,
IAuthenticationSchemeProvider schemeProvider,
IOptions<AbpAccountOptions> accountOptions,
IdentityDynamicClaimsPrincipalContributorCache identityDynamicClaimsPrincipalContributorCache)
{
ExternalProviderService = externalProviderService;
SchemeProvider = schemeProvider;
IdentityDynamicClaimsPrincipalContributorCache = identityDynamicClaimsPrincipalContributorCache;
AccountAppService = accountAppService;
AccountOptions = accountOptions.Value;
}
public virtual async Task<IActionResult> OnGetAsync()
{
ExternalProviders = await GetExternalProviders();
if (!await CheckSelfRegistrationAsync())
{
if (IsExternalLoginOnly)
{
return await OnPostExternalLogin(ExternalLoginScheme);
}
Alerts.Warning(L["SelfRegistrationDisabledMessage"]);
}
await TrySetEmailAsync();
return Page();
}
protected virtual async Task TrySetEmailAsync()
{
if (IsExternalLogin)
{
var externalLoginInfo = await SignInManager.GetExternalLoginInfoAsync();
if (externalLoginInfo == null)
{
return;
}
if (!externalLoginInfo.Principal.Identities.Any())
{
return;
}
var identity = externalLoginInfo.Principal.Identities.First();
var emailClaim = identity.FindFirst(AbpClaimTypes.Email) ?? identity.FindFirst(ClaimTypes.Email);
if (emailClaim == null)
{
return;
}
var userName = await UserManager.GetUserNameFromEmailAsync(emailClaim.Value);
Input = new PostInput { UserName = userName, EmailAddress = emailClaim.Value };
}
}
public virtual async Task<IActionResult> OnPostAsync()
{
try
{
ExternalProviders = await GetExternalProviders();
if (!await CheckSelfRegistrationAsync())
{
throw new UserFriendlyException(L["SelfRegistrationDisabledMessage"]);
}
if (IsExternalLogin)
{
var externalLoginInfo = await SignInManager.GetExternalLoginInfoAsync();
if (externalLoginInfo == null)
{
Logger.LogWarning("External login info is not available");
return RedirectToPage("./Login");
}
if (Input.UserName.IsNullOrWhiteSpace())
{
Input.UserName = await UserManager.GetUserNameFromEmailAsync(Input.EmailAddress);
}
await RegisterExternalUserAsync(externalLoginInfo, Input.UserName, Input.EmailAddress);
}
else
{
await RegisterLocalUserAsync();
}
return Redirect(ReturnUrl ?? "~/"); //TODO: How to ensure safety? IdentityServer requires it however it should be checked somehow!
}
catch (BusinessException e)
{
Alerts.Danger(GetLocalizeExceptionMessage(e));
return Page();
}
}
protected virtual async Task RegisterLocalUserAsync()
{
ValidateModel();
var userDto = await AccountAppService.RegisterAsync(
new RegisterDto
{
AppName = "MVC",
EmailAddress = Input.EmailAddress,
Password = Input.Password,
UserName = Input.UserName
}
);
var user = await UserManager.GetByIdAsync(userDto.Id);
await SignInManager.SignInAsync(user, isPersistent: true);
// Clear the dynamic claims cache.
await IdentityDynamicClaimsPrincipalContributorCache.ClearAsync(user.Id, user.TenantId);
}
protected virtual async Task RegisterExternalUserAsync(ExternalLoginInfo externalLoginInfo, string userName, string emailAddress)
{
await IdentityOptions.SetAsync();
var user = new IdentityUser(GuidGenerator.Create(), userName, emailAddress, CurrentTenant.Id);
(await UserManager.CreateAsync(user)).CheckErrors();
(await UserManager.AddDefaultRolesAsync(user)).CheckErrors();
var userLoginAlreadyExists = user.Logins.Any(x =>
x.TenantId == user.TenantId &&
x.LoginProvider == externalLoginInfo.LoginProvider &&
x.ProviderKey == externalLoginInfo.ProviderKey);
if (!userLoginAlreadyExists)
{
(await UserManager.AddLoginAsync(user, new UserLoginInfo(
externalLoginInfo.LoginProvider,
externalLoginInfo.ProviderKey,
externalLoginInfo.ProviderDisplayName
))).CheckErrors();
}
await SignInManager.SignInAsync(user, isPersistent: true, ExternalLoginAuthSchema);
// Clear the dynamic claims cache.
await IdentityDynamicClaimsPrincipalContributorCache.ClearAsync(user.Id, user.TenantId);
}
protected virtual async Task<bool> CheckSelfRegistrationAsync()
{
EnableLocalRegister = await SettingProvider.IsTrueAsync(AccountSettingNames.EnableLocalLogin) &&
await SettingProvider.IsTrueAsync(AccountSettingNames.IsSelfRegistrationEnabled);
if (IsExternalLogin)
{
return true;
}
if (!EnableLocalRegister)
{
return false;
}
return true;
}
protected async virtual Task<List<ExternalLoginProviderModel>> GetExternalProviders()
{
var schemes = await SchemeProvider.GetAllSchemesAsync();
var externalProviders = await ExternalProviderService.GetAllAsync();
var externalProviderModels = new List<ExternalLoginProviderModel>();
foreach (var scheme in schemes)
{
if (TryGetExternalLoginProvider(scheme, externalProviders, out var externalLoginProvider) ||
scheme.Name.Equals(AccountOptions.WindowsAuthenticationSchemeName, StringComparison.OrdinalIgnoreCase))
{
externalProviderModels.Add(new ExternalLoginProviderModel
{
Name = externalLoginProvider.Name,
AuthenticationScheme = scheme.Name,
DisplayName = externalLoginProvider.DisplayName,
ComponentType = externalLoginProvider.ComponentType,
});
}
}
return externalProviderModels;
}
protected virtual bool TryGetExternalLoginProvider(AuthenticationScheme scheme, List<ExternalLoginProviderModel> externalProviders, out ExternalLoginProviderModel externalLoginProvider)
{
if (ReflectionHelper.IsAssignableToGenericType(scheme.HandlerType, typeof(RemoteAuthenticationHandler<>)))
{
externalLoginProvider = externalProviders.FirstOrDefault(x => x.Name == scheme.Name);
return externalLoginProvider != null;
}
externalLoginProvider = null;
return false;
}
protected virtual async Task<IActionResult> OnPostExternalLogin(string provider)
{
var redirectUrl = Url.Page("./Login", pageHandler: "ExternalLoginCallback", values: new { ReturnUrl, ReturnUrlHash });
var properties = SignInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
properties.Items["scheme"] = provider;
return await Task.FromResult(Challenge(properties, provider));
}
public class PostInput
{
[Required]
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxUserNameLength))]
public string UserName { get; set; }
[Required]
[EmailAddress]
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxEmailLength))]
public string EmailAddress { get; set; }
[Required]
[DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxPasswordLength))]
[DataType(DataType.Password)]
[DisableAuditing]
public string Password { get; set; }
}
}
Loading…
Cancel
Save