mirror of https://github.com/abpframework/abp.git
52 changed files with 323 additions and 75 deletions
@ -0,0 +1,68 @@ |
|||
# How to Use the Weixin Authentication for MVC / Razor Page Applications |
|||
|
|||
This guide demonstrates how to integrate Weixin to an ABP application that enables users to sign in using OAuth 2.0 with credentials. |
|||
|
|||
## Create a sandbox account |
|||
|
|||
If you don't have a production account, you can create a sendbox account for testing: https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index |
|||
|
|||
In this article we will use the sandbox account. |
|||
|
|||
> You should configure the callback domain name on the Weixin open platform |
|||
|
|||
## AddWeixin |
|||
|
|||
You need to install `AspNet.Security.OAuth.Weixin` package to your **.Web** project. |
|||
|
|||
In your **.Web** project, locate your **ApplicationWebModule** and modify `ConfigureAuthentication` method with the following: |
|||
|
|||
```csharp |
|||
private void ConfigureAuthentication(ServiceConfigurationContext context) |
|||
{ |
|||
var configuration = context.Services.GetConfiguration(); |
|||
context.Services.ForwardIdentityAuthenticationForBearer(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme); |
|||
context.Services.AddAuthentication() |
|||
.AddWeixin(options => |
|||
{ |
|||
options.ClientId = configuration["Weixin:ClientId"]; |
|||
options.ClientSecret = configuration["Weixin:ClientSecret"]; |
|||
}); |
|||
} |
|||
``` |
|||
|
|||
Updating `appsettings.json` to add `Weixin` section: |
|||
|
|||
````json |
|||
"Weixin": { |
|||
"ClientId": "<your-app-id>", |
|||
"ClientSecret": "<your-app-secret>" |
|||
} |
|||
```` |
|||
|
|||
## Web page authorization |
|||
|
|||
Now you can run the application to login with Weixin. |
|||
|
|||
 |
|||
|
|||
It will redirect to weixin platform to scan the QR code. |
|||
|
|||
> The sandbox account lacks the necessary scope, so it may not work properly. |
|||
|
|||
## Official account authorization |
|||
|
|||
Updating `AddWeixin`: |
|||
|
|||
```csharp |
|||
context.Services.AddAuthentication() |
|||
.AddWeixin(options => |
|||
{ |
|||
options.ClientId = configuration["Weixin:ClientId"]; |
|||
options.ClientSecret = configuration["Weixin:ClientSecret"]; |
|||
options.AuthorizationEndpoint = "https://open.weixin.qq.com/connect/oauth2/authorize"; |
|||
}); |
|||
``` |
|||
|
|||
Now you can use WeChat app to open the web application URL to login with weixin. |
|||
|
|||
 |
|||
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 25 KiB |
@ -0,0 +1,66 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Microsoft.Extensions.Localization; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.Localization; |
|||
|
|||
public class AbpEnumLocalizer : IAbpEnumLocalizer, ITransientDependency |
|||
{ |
|||
protected readonly IStringLocalizerFactory StringLocalizerFactory; |
|||
|
|||
public AbpEnumLocalizer(IStringLocalizerFactory stringLocalizerFactory) |
|||
{ |
|||
StringLocalizerFactory = stringLocalizerFactory; |
|||
} |
|||
|
|||
public virtual string GetString(Type enumType, object enumValue) |
|||
{ |
|||
return GetStringInternal(enumType, enumValue, StringLocalizerFactory.CreateDefaultOrNull()); |
|||
} |
|||
|
|||
public virtual string GetString(Type enumType, object enumValue, params IStringLocalizer[] specifyLocalizers) |
|||
{ |
|||
return GetStringInternal(enumType, enumValue, specifyLocalizers); |
|||
} |
|||
|
|||
protected virtual string GetStringInternal(Type enumType, object enumValue, params IStringLocalizer[] specifyLocalizers) |
|||
{ |
|||
var memberName = enumType.GetEnumName(enumValue); |
|||
var localizedString = GetStringOrNull( |
|||
specifyLocalizers, |
|||
new[] |
|||
{ |
|||
$"Enum:{enumType.Name}.{enumValue}", |
|||
$"Enum:{enumType.Name}.{memberName}", |
|||
$"{enumType.Name}.{enumValue}", |
|||
$"{enumType.Name}.{memberName}", |
|||
memberName |
|||
} |
|||
); |
|||
|
|||
return localizedString ?? memberName; |
|||
} |
|||
|
|||
protected virtual string GetStringOrNull(IStringLocalizer[] localizers, IEnumerable<string> keys) |
|||
{ |
|||
foreach (var key in keys) |
|||
{ |
|||
foreach (var l in localizers) |
|||
{ |
|||
if (l == null) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
var localizedString = l[key]; |
|||
if (!localizedString.ResourceNotFound) |
|||
{ |
|||
return localizedString.Value; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
using System; |
|||
using Microsoft.Extensions.Localization; |
|||
|
|||
namespace Volo.Abp.Localization; |
|||
|
|||
public static class AbpEnumLocalizerExtensions |
|||
{ |
|||
public static string GetString<TEnum>(this IAbpEnumLocalizer abpEnumLocalizer, object enumValue) |
|||
where TEnum : Enum |
|||
{ |
|||
return abpEnumLocalizer.GetString(typeof(TEnum), enumValue); |
|||
} |
|||
|
|||
public static string GetString<TEnum>(this IAbpEnumLocalizer abpEnumLocalizer, object enumValue, IStringLocalizer[] specifyLocalizers) |
|||
where TEnum : Enum |
|||
{ |
|||
return abpEnumLocalizer.GetString(typeof(TEnum), enumValue, specifyLocalizers); |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using System; |
|||
using Microsoft.Extensions.Localization; |
|||
|
|||
namespace Volo.Abp.Localization; |
|||
|
|||
public interface IAbpEnumLocalizer |
|||
{ |
|||
string GetString(Type enumType, object enumValue); |
|||
|
|||
string GetString(Type enumType, object enumValue, IStringLocalizer[] specifyLocalizers); |
|||
} |
|||
@ -0,0 +1,47 @@ |
|||
using Microsoft.Extensions.Localization; |
|||
using Shouldly; |
|||
using Volo.Abp.Localization.TestResources.Base.Validation; |
|||
using Volo.Abp.Testing; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.Localization; |
|||
|
|||
public class AbpEnumLocalizer_Tests : AbpIntegratedTest<AbpLocalizationTestModule> |
|||
{ |
|||
private readonly IAbpEnumLocalizer _enumLocalizer; |
|||
|
|||
public AbpEnumLocalizer_Tests() |
|||
{ |
|||
_enumLocalizer = GetRequiredService<IAbpEnumLocalizer>(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void GetString_Test() |
|||
{ |
|||
using (CultureHelper.Use("en")) |
|||
{ |
|||
_enumLocalizer.GetString<BookType>(BookType.Undefined).ShouldBe("Undefined"); |
|||
_enumLocalizer.GetString<BookType>(BookType.Adventure).ShouldBe("Adventure"); |
|||
_enumLocalizer.GetString<BookType>(0).ShouldBe("Undefined with value 0"); |
|||
_enumLocalizer.GetString<BookType>(1).ShouldBe("Adventure with value 1"); |
|||
_enumLocalizer.GetString<BookType>(BookType.Biography).ShouldBe("Biography"); |
|||
|
|||
var specifyLocalizer = new[] |
|||
{ |
|||
GetRequiredService<IStringLocalizerFactory>().Create<LocalizationTestValidationResource>() |
|||
}; |
|||
_enumLocalizer.GetString<BookType>(BookType.Undefined, specifyLocalizer).ShouldBe("Undefined from ValidationResource"); |
|||
_enumLocalizer.GetString<BookType>(BookType.Adventure, specifyLocalizer).ShouldBe("Adventure from ValidationResource"); |
|||
_enumLocalizer.GetString<BookType>(0, specifyLocalizer).ShouldBe("Undefined with value 0 from ValidationResource"); |
|||
_enumLocalizer.GetString<BookType>(1, specifyLocalizer).ShouldBe("Adventure with value 1 from ValidationResource"); |
|||
_enumLocalizer.GetString<BookType>(BookType.Biography, specifyLocalizer).ShouldBe("Biography from ValidationResource"); |
|||
} |
|||
} |
|||
} |
|||
|
|||
enum BookType |
|||
{ |
|||
Undefined, |
|||
Adventure, |
|||
Biography, |
|||
} |
|||
Loading…
Reference in new issue