Skip to content

Commit

Permalink
Merge pull request #1129 from colinin/scan-code-login-openiddict
Browse files Browse the repository at this point in the history
feat(openiddict): 增加扫码登录实现
  • Loading branch information
colinin authored Mar 5, 2025
2 parents db44d57 + 9a785f7 commit dd1c8cc
Show file tree
Hide file tree
Showing 36 changed files with 1,025 additions and 4 deletions.
21 changes: 21 additions & 0 deletions aspnet-core/LINGYUN.MicroService.SingleProject.sln
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Gdpr.HttpApi.Cl
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Gdpr.Web", "modules\gdpr\LINGYUN.Abp.Gdpr.Web\LINGYUN.Abp.Gdpr.Web.csproj", "{00868838-6891-B034-AAB7-AADAA3ECDCB3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Identity.QrCode", "modules\identity\LINGYUN.Abp.Identity.QrCode\LINGYUN.Abp.Identity.QrCode.csproj", "{E40CB92D-6C03-4A61-9A47-057CA504A46B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.OpenIddict.QrCode", "modules\openIddict\LINGYUN.Abp.OpenIddict.QrCode\LINGYUN.Abp.OpenIddict.QrCode.csproj", "{4C7594CE-FB2F-4309-B95C-D4460892CF6E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Identity.AspNetCore.QrCode", "modules\identity\LINGYUN.Abp.Identity.AspNetCore.QrCode\LINGYUN.Abp.Identity.AspNetCore.QrCode.csproj", "{C9266D5D-3860-09C3-F566-489BBB57A534}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -1738,6 +1744,18 @@ Global
{00868838-6891-B034-AAB7-AADAA3ECDCB3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{00868838-6891-B034-AAB7-AADAA3ECDCB3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{00868838-6891-B034-AAB7-AADAA3ECDCB3}.Release|Any CPU.Build.0 = Release|Any CPU
{E40CB92D-6C03-4A61-9A47-057CA504A46B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E40CB92D-6C03-4A61-9A47-057CA504A46B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E40CB92D-6C03-4A61-9A47-057CA504A46B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E40CB92D-6C03-4A61-9A47-057CA504A46B}.Release|Any CPU.Build.0 = Release|Any CPU
{4C7594CE-FB2F-4309-B95C-D4460892CF6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4C7594CE-FB2F-4309-B95C-D4460892CF6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4C7594CE-FB2F-4309-B95C-D4460892CF6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4C7594CE-FB2F-4309-B95C-D4460892CF6E}.Release|Any CPU.Build.0 = Release|Any CPU
{C9266D5D-3860-09C3-F566-489BBB57A534}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C9266D5D-3860-09C3-F566-489BBB57A534}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C9266D5D-3860-09C3-F566-489BBB57A534}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C9266D5D-3860-09C3-F566-489BBB57A534}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -2057,6 +2075,9 @@ Global
{B080B644-A835-42EE-EBF5-C47B6D075588} = {4F837B81-EA7D-472A-8482-3D5A730DF810}
{170F4C72-BED2-C77A-64B0-F4CB9A232026} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
{00868838-6891-B034-AAB7-AADAA3ECDCB3} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
{E40CB92D-6C03-4A61-9A47-057CA504A46B} = {D94D6AFE-20BD-4F21-8708-03F5E34F49FC}
{4C7594CE-FB2F-4309-B95C-D4460892CF6E} = {7C714185-D3D9-4D94-B5CB-D857A0091F04}
{C9266D5D-3860-09C3-F566-489BBB57A534} = {D94D6AFE-20BD-4F21-8708-03F5E34F49FC}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {711A43C0-A2F8-4E5C-9B9F-F2551E4B3FF1}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using LINGYUN.Abp.Account.Emailing;
using LINGYUN.Abp.Account.Web.ProfileManagement;
using LINGYUN.Abp.Identity;
using LINGYUN.Abp.Identity.AspNetCore.QrCode;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Account.Localization;
using Volo.Abp.Account.Web.Pages.Account;
Expand All @@ -21,6 +22,7 @@ namespace LINGYUN.Abp.Account.Web;
typeof(VoloAbpAccountWebModule),
typeof(AbpIdentityDomainModule),
typeof(AbpAccountEmailingModule),
typeof(AbpIdentityAspNetCoreQrCodeModule),
typeof(AbpAccountApplicationContractsModule))]
public class AbpAccountWebModule : AbpModule
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace LINGYUN.Abp.Account.Web.Areas.Account.Controllers.Models;

public class GenerateQrCodeResult
{
public string Key { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using LINGYUN.Abp.Identity.QrCode;

namespace LINGYUN.Abp.Account.Web.Areas.Account.Controllers.Models;

public class QrCodeInfoResult
{
public string Key { get; set; }
public QrCodeStatus Status { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace LINGYUN.Abp.Account.Web.Areas.Account.Controllers.Models;

public class QrCodeUserInfoResult : QrCodeInfoResult
{
public string UserId { get; set; }
public string UserName { get; set; }
public string Picture { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
using Asp.Versioning;
using LINGYUN.Abp.Account.Web.Areas.Account.Controllers.Models;
using LINGYUN.Abp.Identity.QrCode;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Account;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Identity;
using Volo.Abp.Security.Claims;
using Volo.Abp.Users;

namespace LINGYUN.Abp.Account.Web.Areas.Account.Controllers;

[Controller]
[ControllerName("QrCodeLogin")]
[Area(AccountRemoteServiceConsts.ModuleName)]
[Route($"api/{AccountRemoteServiceConsts.ModuleName}/qrcode")]
[RemoteService(Name = AccountRemoteServiceConsts.RemoteServiceName)]
public class QrCodeLoginController : AbpControllerBase
{
private readonly IdentityUserManager _userManager;
private readonly IQrCodeLoginProvider _qrCodeLoginProvider;

public QrCodeLoginController(
IdentityUserManager userManager,
IQrCodeLoginProvider qrCodeLoginProvider)
{
_userManager = userManager;
_qrCodeLoginProvider = qrCodeLoginProvider;
}

[HttpPost]
[Route("generate")]
[AllowAnonymous]
public async Task<GenerateQrCodeResult> GenerateAsync()
{
var qrCodeInfo = await _qrCodeLoginProvider.GenerateAsync();

return new GenerateQrCodeResult
{
Key = qrCodeInfo.Key,
};
}

[HttpGet]
[Route("{key}/check")]
[AllowAnonymous]
public async Task<QrCodeUserInfoResult> CheckCodeAsync(string key)
{
var qrCodeInfo = await _qrCodeLoginProvider.GetCodeAsync(key);

return new QrCodeUserInfoResult
{
Key = qrCodeInfo.Key,
Status = qrCodeInfo.Status,
Picture = qrCodeInfo.Picture,
UserId = qrCodeInfo.UserId,
UserName = qrCodeInfo.UserName,
};
}

[HttpPost]
[Route("{key}/scan")]
[Authorize]
public async Task<QrCodeUserInfoResult> ScanCodeAsync(string key)
{
var currentUser = await _userManager.GetByIdAsync(CurrentUser.GetId());

var picture = CurrentUser.FindClaim(AbpClaimTypes.Picture)?.Value;
var userName = CurrentUser.FindClaim(AbpClaimTypes.Name)?.Value ?? currentUser.UserName;
var userId = await _userManager.GetUserIdAsync(currentUser);

var qrCodeInfo = await _qrCodeLoginProvider.ScanCodeAsync(key,
new QrCodeScanParams(userId, userName, picture, currentUser.TenantId));

return new QrCodeUserInfoResult
{
Key = qrCodeInfo.Key,
Status = qrCodeInfo.Status,
Picture = qrCodeInfo.Picture,
UserId = qrCodeInfo.UserId,
UserName = qrCodeInfo.UserName
};
}

[HttpPost]
[Route("{key}/confirm")]
[Authorize]
public async Task<QrCodeUserInfoResult> ConfirmCodeAsync(string key)
{
var qrCodeInfo = await _qrCodeLoginProvider.ConfirmCodeAsync(key);

return new QrCodeUserInfoResult
{
Key = qrCodeInfo.Key,
Status = qrCodeInfo.Status,
Picture = qrCodeInfo.Picture,
UserId = qrCodeInfo.UserId,
UserName = qrCodeInfo.UserName
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@

<ItemGroup>
<ProjectReference Include="..\..\identity\LINGYUN.Abp.Identity.Domain\LINGYUN.Abp.Identity.Domain.csproj" />
<ProjectReference Include="..\..\identity\LINGYUN.Abp.Identity.AspNetCore.QrCode\LINGYUN.Abp.Identity.AspNetCore.QrCode.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.Account.Application.Contracts\LINGYUN.Abp.Account.Application.Contracts.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.Account.Emailing\LINGYUN.Abp.Account.Emailing.csproj" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait />
</Weavers>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<AssemblyName>LINGYUN.Abp.Identity.AspNetCore.QrCode</AssemblyName>
<PackageId>LINGYUN.Abp.Identity.AspNetCore.QrCode</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Volo.Abp.Identity.AspNetCore" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.Identity.QrCode\LINGYUN.Abp.Identity.QrCode.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using LINGYUN.Abp.Identity.QrCode;
using Microsoft.AspNetCore.Identity;
using Volo.Abp.Identity.AspNetCore;
using Volo.Abp.Modularity;

namespace LINGYUN.Abp.Identity.AspNetCore.QrCode;

[DependsOn(
typeof(AbpIdentityQrCodeModule),
typeof(AbpIdentityAspNetCoreModule))]
public class AbpIdentityAspNetCoreQrCodeModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<IdentityBuilder>(builder =>
{
builder.AddTokenProvider<QrCodeUserTokenProvider>(QrCodeUserTokenProvider.ProviderName);
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using IdentityUser = Volo.Abp.Identity.IdentityUser;

namespace LINGYUN.Abp.Identity.QrCode;

public class QrCodeUserTokenProvider : DataProtectorTokenProvider<IdentityUser>
{
public static string ProviderName => QrCodeLoginProviderConsts.Name;
public QrCodeUserTokenProvider(
IDataProtectionProvider dataProtectionProvider,
IOptions<DataProtectionTokenProviderOptions> options,
ILogger<DataProtectorTokenProvider<IdentityUser>> logger)
: base(dataProtectionProvider, options, logger)
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">

<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />

<PropertyGroup>
<TargetFrameworks>net9.0</TargetFrameworks>
<AssemblyName>LINGYUN.Abp.Identity.QrCode</AssemblyName>
<PackageId>LINGYUN.Abp.Identity.QrCode</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>

<ItemGroup>
<Content Remove="LINGYUN\Abp\Identity\QrCode\Localization\Resources\*.json" />
<EmbeddedResource Include="LINGYUN\Abp\Identity\QrCode\Localization\Resources\*.json" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Volo.Abp.Identity.Domain" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Volo.Abp.Identity;
using Volo.Abp.Identity.Localization;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;

namespace LINGYUN.Abp.Identity.QrCode;

[DependsOn(typeof(AbpIdentityDomainModule))]
public class AbpIdentityQrCodeModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpIdentityQrCodeModule>();
});

Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Get<IdentityResource>()
.AddVirtualJson("/LINGYUN/Abp/Identity/QrCode/Localization/Resources");
});
}
}
Loading

0 comments on commit dd1c8cc

Please sign in to comment.