abp vnext IdentityServer4 使用IExtensionGrantValidator接口进行的授权登入扩展,按照以下代码可实现,欢迎交流指正。
微信返回数据字段类- Code2Session 类
public class Code2Session
{
/// <summary>
/// 用户唯一标识
/// </summary>
public string openid { get; set; }
/// <summary>
/// 会话密钥
/// </summary>
public string session_key { get; set; }
/// <summary>
/// 用户在开放平台的唯一标识符,若当前小程序已绑定到微信开放平台帐号下会返回
/// </summary>
public string unionid { get; set; }
/// <summary>
/// 错误码
/// </summary>
public int errcode { get; set; }
/// <summary>
/// 错误信息
/// </summary>
public string errmsg { get; set; }
}
在HttpApi.Host新建类
using IdentityServer4.Validation;
using Microsoft.AspNetCore.Identity;
using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
using Volo.Abp.Identity;
using Volo.Abp.Json;
using System.Net.Http;
namespace Demo
{
public class ExtensionGrantTypes
{
//扩展授权名称
public const string WeChatGrantType = "wechat_code";
}
public class WeChatGrantValidator : IExtensionGrantValidator
{
public string GrantType => ExtensionGrantTypes.WeChatGrantType;
private readonly UserManager<Volo.Abp.Identity.IdentityUser> _userManager;
private readonly IJsonSerializer _jsonSerializer;
public WeChatGrantValidator(
UserManager<Volo.Abp.Identity.IdentityUser> userLoginManager,
IJsonSerializer jsonSerializer)
{
_userManager = userLoginManager;
_jsonSerializer = jsonSerializer;
}
public async Task ValidateAsync(ExtensionGrantValidationContext context)
{
string code = context.Request.Raw.Get("Code");
if (string.IsNullOrEmpty(code))
{
context.Result = new GrantValidationResult(IdentityServer4.Models.TokenRequestErrors.InvalidGrant);
}
//微信开发平台验证
string _appid = "自己的appid";
string _secret = "自己的secret";
string url = string.Format(
"https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code",
_appid,
_secret,
code);
HttpClient client = new HttpClient();
HttpResponseMessage response = client.GetAsync(url).Result;
if (response.IsSuccessStatusCode)
{
string resContent = response.Content.ReadAsStringAsync().Result;
var code2session = _jsonSerializer.Deserialize<Code2Session>(resContent);
switch (code2session.errcode)
{
case 0:
string providerKey = code2session.openid;
context.Result = await ServerValidate("WeChat", providerKey);
break;
default:context.Result = new GrantValidationResult(
IdentityServer4.Models.TokenRequestErrors.InvalidGrant,
"wechat:"+code2session.errmsg);
break;
}
}
else
context.Result = new GrantValidationResult(IdentityServer4.Models.TokenRequestErrors.InvalidGrant);
}
readonly DateTime DateTime1970 = new DateTime(1970, 1, 1).ToLocalTime();
/// <summary>
/// 服务器验证并输出用户信息,以便自动生成token
/// </summary>
/// <param name="loginProvider"></param>
/// <param name="providerKey"></param>
/// <returns></returns>
private async Task<GrantValidationResult> ServerValidate(string loginProvider,string providerKey)
{
var user = await _userManager.FindByLoginAsync(loginProvider, providerKey);
if (user == null)
return new GrantValidationResult(IdentityServer4.Models.TokenRequestErrors.InvalidGrant);
var principal = new ClaimsPrincipal();
List<ClaimsIdentity> claimsIdentity = new List<ClaimsIdentity>();
ClaimsIdentity identity = new ClaimsIdentity();
identity.AddClaim(new Claim("sub", user.Id.ToString()));
identity.AddClaim(new Claim("tenantid", user.TenantId.ToString()));
identity.AddClaim(new Claim("idp", "local"));
identity.AddClaim(new Claim("amr", loginProvider));
long authTime = (long)(DateTime.Now.ToLocalTime() - DateTime1970).TotalSeconds;
identity.AddClaim(new Claim("auth_time", authTime.ToString()));
claimsIdentity.Add(identity);
principal.AddIdentities(claimsIdentity);
return new GrantValidationResult(principal);
}
}
}
在HttpApiHostModule.cs 文件中添加注册
public override void PreConfigureServices(ServiceConfigurationContext context)
{
context.Services.PreConfigure<IIdentityServerBuilder>(
builder =>
{
builder.AddExtensionGrantValidator<WeChatGrantValidator>();
});
}
在Domain项目中的identityServer 文件夹中的种子数据添加grantTypes(CreateClientAsync()下)
grantTypes: new[] { "password", "client_credentials", "authorization_code", "wechat_code" },
请求地址和参数
host:/connect/token
methon:POST
media type:aplication/x-www-form-urlencoded
body:
grant_type=wechat_code
code=微信小程序提供的code
client_id=自己项目的client_id
scope=自己项目 openid offline_access
钉钉可参考本文进行IdentityServer4扩展授权登录,欢迎交流指正,谢谢阅读。