小程序端onlogin增加redis锁。

This commit is contained in:
大灰灰
2022-09-15 01:57:09 +08:00
parent 673628ed10
commit 0e87700656
2 changed files with 94 additions and 68 deletions

View File

@@ -10,6 +10,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using CoreCms.Net.Model.Entities; using CoreCms.Net.Model.Entities;
namespace CoreCms.Net.Model.FromBody namespace CoreCms.Net.Model.FromBody
@@ -20,8 +21,9 @@ namespace CoreCms.Net.Model.FromBody
public class FMWxPost public class FMWxPost
{ {
/// <summary> /// <summary>
/// 页面编码 /// 用户前端编码
/// </summary> /// </summary>
[Required(ErrorMessage = "请提交合法数据")]
public string code { get; set; } public string code { get; set; }
} }

View File

@@ -20,6 +20,7 @@ using System.Threading.Tasks;
using CoreCms.Net.Auth.HttpContextUser; using CoreCms.Net.Auth.HttpContextUser;
using CoreCms.Net.Auth.Policys; using CoreCms.Net.Auth.Policys;
using CoreCms.Net.Caching.AccressToken; using CoreCms.Net.Caching.AccressToken;
using CoreCms.Net.Caching.AutoMate.RedisCache;
using CoreCms.Net.Configuration; using CoreCms.Net.Configuration;
using CoreCms.Net.IServices; using CoreCms.Net.IServices;
using CoreCms.Net.Loging; using CoreCms.Net.Loging;
@@ -35,6 +36,7 @@ using CoreCms.Net.WeChat.Service.HttpClients;
using CoreCms.Net.WeChat.Service.Models; using CoreCms.Net.WeChat.Service.Models;
using CoreCms.Net.WeChat.Service.Options; using CoreCms.Net.WeChat.Service.Options;
using CoreCms.Net.WeChat.Service.Utilities; using CoreCms.Net.WeChat.Service.Utilities;
using DotLiquid.Util;
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
@@ -87,11 +89,7 @@ namespace CoreCms.Net.Web.WebApi.Controllers
private readonly ICoreCmsOrderServices _orderServices; private readonly ICoreCmsOrderServices _orderServices;
private readonly IWeChatApiHttpClientFactory _weChatApiHttpClientFactory; private readonly IWeChatApiHttpClientFactory _weChatApiHttpClientFactory;
private readonly WeChatOptions _weChatOptions; private readonly WeChatOptions _weChatOptions;
private readonly IRedisOperationRepository _redisOperationRepository;
private readonly AsyncLock _mutex = new AsyncLock();
/// <summary> /// <summary>
/// 构造函数 /// 构造函数
@@ -122,7 +120,7 @@ namespace CoreCms.Net.Web.WebApi.Controllers
, ICoreCmsSettingServices settingServices , ICoreCmsSettingServices settingServices
, ICoreCmsServicesServices servicesServices , ICoreCmsServicesServices servicesServices
, IOptions<WeChatOptions> weChatOptions , IOptions<WeChatOptions> weChatOptions
, ICoreCmsUserServicesOrderServices userServicesOrderServices, ICoreCmsUserServicesTicketServices userServicesTicketServices, ICoreCmsStoreServices storeServices, ICoreCmsCouponServices couponServices, ICoreCmsOrderServices orderServices, IWeChatApiHttpClientFactory weChatApiHttpClientFactory) , ICoreCmsUserServicesOrderServices userServicesOrderServices, ICoreCmsUserServicesTicketServices userServicesTicketServices, ICoreCmsStoreServices storeServices, ICoreCmsCouponServices couponServices, ICoreCmsOrderServices orderServices, IWeChatApiHttpClientFactory weChatApiHttpClientFactory, IRedisOperationRepository redisOperationRepository)
{ {
_user = user; _user = user;
_userWeChatInfoServices = userWeChatInfoServices; _userWeChatInfoServices = userWeChatInfoServices;
@@ -154,6 +152,7 @@ namespace CoreCms.Net.Web.WebApi.Controllers
_couponServices = couponServices; _couponServices = couponServices;
_orderServices = orderServices; _orderServices = orderServices;
_weChatApiHttpClientFactory = weChatApiHttpClientFactory; _weChatApiHttpClientFactory = weChatApiHttpClientFactory;
_redisOperationRepository = redisOperationRepository;
_weChatOptions = weChatOptions.Value; _weChatOptions = weChatOptions.Value;
} }
@@ -170,84 +169,109 @@ namespace CoreCms.Net.Web.WebApi.Controllers
{ {
var jm = new WebApiCallBack(); var jm = new WebApiCallBack();
var client = _weChatApiHttpClientFactory.CreateWxOpenClient(); var lockKey = "LOCK_OnLogin:user_" + entity.code;
var accessToken = WeChatCacheAccessTokenHelper.GetWxOpenAccessToken(); var lockHolder = Guid.NewGuid().ToString("N"); //锁持有者
var request = new SnsJsCode2SessionRequest(); var redisUserLock = await _redisOperationRepository.LockTakeAsync(lockKey, lockHolder, TimeSpan.FromSeconds(10));
request.JsCode = entity.code; if (redisUserLock)
request.AccessToken = accessToken;
var response = await client.ExecuteSnsJsCode2SessionAsync(request, HttpContext.RequestAborted);
if (response.ErrorCode == (int)WeChatReturnCode.ReturnCode.)
{ {
using (await _mutex.LockAsync()) try
{ {
var userInfo = await _userWeChatInfoServices.QueryByClauseAsync(p => p.openid == response.OpenId); var client = _weChatApiHttpClientFactory.CreateWxOpenClient();
if (userInfo == null) var accessToken = WeChatCacheAccessTokenHelper.GetWxOpenAccessToken();
var request = new SnsJsCode2SessionRequest
{ {
userInfo = new CoreCmsUserWeChatInfo(); JsCode = entity.code,
userInfo.openid = response.OpenId; AccessToken = accessToken
userInfo.type = (int)GlobalEnumVars.UserAccountTypes.; };
userInfo.sessionKey = response.SessionKey;
userInfo.gender = 1;
userInfo.createTime = DateTime.Now;
userInfo.unionId = response.UnionId;
await _userWeChatInfoServices.InsertAsync(userInfo);
}
else
{
if (userInfo.sessionKey != response.SessionKey)
{
await _userWeChatInfoServices.UpdateAsync(
p => new CoreCmsUserWeChatInfo() { sessionKey = response.SessionKey, updateTime = DateTime.Now },
p => p.openid == userInfo.openid);
}
}
if (userInfo is { userId: > 0 }) var response = await client.ExecuteSnsJsCode2SessionAsync(request, HttpContext.RequestAborted);
if (response.ErrorCode == (int)WeChatReturnCode.ReturnCode.)
{ {
var user = await _userServices.QueryByClauseAsync(p => p.id == userInfo.userId); var userInfo = await _userWeChatInfoServices.QueryByClauseAsync(p => p.openid == response.OpenId);
if (user != null) if (userInfo == null)
{ {
var claims = new List<Claim> { userInfo = new CoreCmsUserWeChatInfo
{
openid = response.OpenId,
type = (int)GlobalEnumVars.UserAccountTypes.,
sessionKey = response.SessionKey,
gender = 1,
createTime = DateTime.Now,
unionId = response.UnionId
};
await _userWeChatInfoServices.InsertAsync(userInfo);
}
else
{
if (userInfo.sessionKey != response.SessionKey)
{
await _userWeChatInfoServices.UpdateAsync(
p => new CoreCmsUserWeChatInfo() { sessionKey = response.SessionKey, updateTime = DateTime.Now },
p => p.openid == userInfo.openid);
}
}
if (userInfo is { userId: > 0 })
{
var user = await _userServices.QueryByClauseAsync(p => p.id == userInfo.userId);
if (user != null)
{
var claims = new List<Claim> {
new Claim(ClaimTypes.Name, user.nickName), new Claim(ClaimTypes.Name, user.nickName),
new Claim(JwtRegisteredClaimNames.Jti, user.id.ToString()), new Claim(JwtRegisteredClaimNames.Jti, user.id.ToString()),
new Claim(ClaimTypes.Expiration, DateTime.Now.AddSeconds(_permissionRequirement.Expiration.TotalSeconds).ToString(CultureInfo.InvariantCulture)) }; new Claim(ClaimTypes.Expiration, DateTime.Now.AddSeconds(_permissionRequirement.Expiration.TotalSeconds).ToString(CultureInfo.InvariantCulture)) };
//用户标识 //用户标识
var identity = new ClaimsIdentity(JwtBearerDefaults.AuthenticationScheme); var identity = new ClaimsIdentity(JwtBearerDefaults.AuthenticationScheme);
identity.AddClaims(claims); identity.AddClaims(claims);
jm.status = true; jm.status = true;
jm.data = new jm.data = new
{ {
auth = JwtToken.BuildJwtToken(claims.ToArray(), _permissionRequirement), auth = JwtToken.BuildJwtToken(claims.ToArray(), _permissionRequirement),
user user
}; };
jm.otherData = response.OpenId; jm.otherData = response.OpenId;
//录入登录日志 //录入登录日志
var log = new CoreCmsUserLog(); var log = new CoreCmsUserLog
log.userId = user.id; {
log.state = (int)GlobalEnumVars.UserLogTypes.; userId = user.id,
log.ip = _httpContextAccessor.HttpContext?.Connection.RemoteIpAddress != null ? _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString() : "127.0.0.1"; state = (int)GlobalEnumVars.UserLogTypes.,
log.createTime = DateTime.Now; ip = _httpContextAccessor.HttpContext?.Connection.RemoteIpAddress != null ? _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString() : "127.0.0.1",
log.parameters = GlobalEnumVars.UserLogTypes..ToString(); createTime = DateTime.Now,
await _userLogServices.InsertAsync(log); parameters = GlobalEnumVars.UserLogTypes..ToString()
};
await _userLogServices.InsertAsync(log);
return jm; return jm;
}
} }
//注意生产环境下SessionKey属于敏感信息不能进行传输
//return new JsonResult(new { success = true, msg = "OK", sessionAuthId = sessionBag.Key, sessionKey = sessionBag.SessionKey, data = jsonResult, sessionBag = sessionBag });
jm.status = true;
jm.data = response.OpenId;
jm.otherData = response.OpenId;
//jm.methodDescription = JsonConvert.SerializeObject(sessionBag);
jm.msg = "OK";
}
else
{
jm.msg = response.ErrorMessage;
} }
} }
//注意生产环境下SessionKey属于敏感信息不能进行传输 catch (Exception e)
//return new JsonResult(new { success = true, msg = "OK", sessionAuthId = sessionBag.Key, sessionKey = sessionBag.SessionKey, data = jsonResult, sessionBag = sessionBag }); {
jm.status = true; jm.msg = "数据处理异常";
jm.data = response.OpenId; jm.otherData = e;
jm.otherData = response.OpenId; }
//jm.methodDescription = JsonConvert.SerializeObject(sessionBag); finally
jm.msg = "OK"; {
await _redisOperationRepository.LockReleaseAsync(lockKey, lockHolder);
}
} }
else else
{ {
jm.msg = response.ErrorMessage; jm.msg = "当前请求太频繁_请稍后再试";
} }
return jm; return jm;