domian-build

This commit is contained in:
tongfei
2023-10-18 10:37:41 +08:00
parent 9b739e2e37
commit 05ee79a04f
18 changed files with 2894 additions and 5 deletions

View File

@@ -0,0 +1,387 @@
using AutoMapper;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Json;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WMS.Web.Core.Dto.Login;
using WMS.Web.Core.Dto.Login.Temp;
using WMS.Web.Core.Help;
using WMS.Web.Core.Internal.Results;
using WMS.Web.Core.Internal.Security;
using WMS.Web.Domain.IService.Public;
using WMS.Web.Domain.Options;
using WMS.Web.Domain.Values.Single;
namespace WMS.Web.Domain.Services.Public
{
public class LoginService : ILoginService
{
private IMapper _mapper;
private SoaOptions _soaOptions;
private ILogger<LoginService> _logger;
private HttpClientHelp _httpClientHelp;
private readonly ISingleDataService _singleDataService;
private readonly RedisClientService _redisClientService;
public LoginService(
IMapper mapper,
IOptions<SoaOptions> soaOptions,
ILogger<LoginService> logger,
HttpClientHelp httpClientHelp,
ISingleDataService singleDataService,
RedisClientService redisClientService)
{
this._redisClientService = redisClientService;
this._singleDataService = singleDataService;
this._soaOptions = soaOptions?.Value;
this._mapper = mapper;
this._logger = logger;
this._httpClientHelp = httpClientHelp;
}
/// <summary>
/// 创建token
/// </summary>
/// <param name="data"></param>
/// <param name="tempDto"></param>
/// <param name="NewToken"></param>
/// <returns></returns>
private async Task<AccessTokenDto> CreateToken(UserInfoDto data, LoginTempDto tempDto, string NewToken)
{
return await Task.Run(() =>
{
DateTime expires_time = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)).AddSeconds(tempDto.expires_in);
AccessTokenDto accessToken = new AccessTokenDto()
{
Token = NewToken,
PhpToken = tempDto.access_token,
RefreshToken = tempDto.refresh_token,
Expired = expires_time
};
return accessToken;
});
}
/// <summary>
/// 得到单点用户信息
/// </summary>
/// <param name="code"></param>
/// <returns></returns>
public async Task<Result<LoginInDto>> GetUserInfoAsync(string code)
{
JsonObject reqData = new JsonObject();
reqData.Add("app_id", _soaOptions.AppId);
reqData.Add("app_secret", _soaOptions.AppSecret);
reqData.Add("code", code);
//这个是登录的时候给前端验证的token,以及传给php单点那边的一个session值用于单点退出时通知ops退出
string NewToken = Guid.NewGuid().ToString("N");
try
{
string result = _httpClientHelp.PostHttp(_soaOptions.Url + "/uc/authorize/access_token", reqData, true, NewToken);
var jObject = JsonObject.Parse(result);
LoginInDto r = new LoginInDto();
r.UserInfo = new UserInfoDto();
r.TokenInfo = new AccessTokenDto();
var login_result = jObject["errno"] == 0 ? "成功" : "失败";
_logger.LogInformation($"登录信息:单点->{login_result}");
if (jObject["errno"] == 0)
{
string datajson = jObject["data"].ToString();
var _loginDto = JsonConvert.DeserializeObject<LoginTempDto>(datajson);
#region
string enptStr = _loginDto.encryptedData;
List<string> enptlist = enptStr.Trim().Split(',').ToList();
string str = RSA.DecryptSection(_soaOptions.PrivateKey, enptlist);
var entity = JsonConvert.DeserializeObject<LoginJsonTokenTempDto>(str);
#endregion
//映射登录信息
r.UserInfo = _mapper.Map<UserInfoDto>(entity);
_logger.LogInformation($"登录信息用户ID->{entity.uc_id}");
//HTTP请求获取登录信息人员客户供应商公司
var loginRequest = new LoginSingleRequest()
{
UserId = entity.uc_id,
SupplierId = entity.supplier_id ?? 0,
CustomerId = entity.customer_id ?? 0
};
var loginResponse_result = await _singleDataService.GetSingleDataNoCache<Result<LoginSingleResponse>, LoginSingleRequest, SingleLoginAction>
(loginRequest, SingleLoginAction.All, type: SingleControllerType.Login);
//绑定返回对象的登录信息
var staffName = "Null";
var token = await CreateToken(r.UserInfo, _loginDto, NewToken);
r.TokenInfo = token;
if (loginResponse_result.Success && loginResponse_result.Data != null)
{
var loginResponse = loginResponse_result.Data;
if (loginResponse.Supplier != null)
r.UserInfo.SupplierName = loginResponse.Supplier.Name;
if (loginResponse.Customer != null)
r.UserInfo.CustomerName = loginResponse.Customer.Name;
if (loginResponse.Staff != null)
{
r.UserInfo.StaffId = loginResponse.Staff.Id;
staffName = loginResponse.Staff.Name;
}
if (loginResponse.Company != null)
r.UserInfo.CompanyName = loginResponse.Company.Name;
}
r.UserInfo.UcId = entity.uc_id;
r.UserInfo.SeesionId = _loginDto?.uc_sessid;
r.UserInfo.CompanyId = entity.company_id.Value;
r.UserInfo.Identity = entity.identity;
r.UserInfo.OrgId = entity.org_id;
r.UserInfo.CustomerId = entity.customer_id;
r.UserInfo.SupplierId = entity.supplier_id;
r.SignedIn = true;
_logger.LogInformation($"登录信息:用户人员信息->{staffName}{r.UserInfo.StaffId}),公司名称->{r.UserInfo.CompanyName}");
//登录后缓存登录的用户信息和token信息
var loginInfo = new LoginInDto();
loginInfo.UserInfo = r.UserInfo;
loginInfo.TokenInfo = token;
var ops_login_time = token.Expired.AddDays(1) - DateTime.Now;//用于正式
_redisClientService.SetStringKey<LoginInDto>($"ops_login_{token.Token}", loginInfo, ops_login_time);
//登录成功移出对应的用户token黑名单应为新的token产生,移除登录的信息
string blacktoken = _redisClientService.GetStringKey($"ops_black_token_{r.UserInfo.UcId}");
if (!string.IsNullOrEmpty(blacktoken))
{
this.RemoveLoginInfo(blacktoken);
_redisClientService.RemoveStringKey($"ops_black_token_{r.UserInfo.UcId}");
}
if (r == null || r.UserInfo == null || r.TokenInfo == null)
return Result<LoginInDto>.ReFailure("授权失败,请重新登录", 401);
return Result<LoginInDto>.ReSuccess(r);
}
else
{
var errno_text = "登陆失败:" + jObject["errmsg"];
r.SignedIn = false;
string datajson_sessid = jObject["data"]["uc_sessid"];
//调用单点的退出接口
result = _httpClientHelp.GetHttp(_soaOptions.Url + "/uc/authorize/signin_out", true, cookieValue: datajson_sessid);
jObject = JsonObject.Parse(result);
if (jObject["errno"] == 0)
{
_logger.LogInformation("用户信息登录:" + errno_text);
return Result<LoginInDto>.ReFailure("拒绝用户证书试图访问此web站点请与站点管理员联系以建立用户证书权限", 403);
}
else
{
return Result<LoginInDto>.ReFailure(jObject["errmsg"], jObject["errno"]);
}
}
}
catch (Exception ex)
{
return Result<LoginInDto>.ReFailure("授权失败,请重新登录", 401);
}
}
/// <summary>
/// 登录退出
/// </summary>
/// <returns></returns>
public async Task<Result> LoginOutAsync(LoginOutDto dto)
{
_logger.LogInformation("dto_SessionId:" + dto.SessionId);
//2.请求PHP单点登出接口
JsonObject reqData = new JsonObject();
reqData.Add("app_id", _soaOptions.AppId);
reqData.Add("app_secret", _soaOptions.AppSecret);
reqData.Add("access_token", dto.AccessToken);
string result = _httpClientHelp.PostHttp(_soaOptions.Url + "/uc/authorize/signin_out", reqData, true, dto.SessionId);
_logger.LogInformation("退出登录返回:" + result);
var jObject = JsonObject.Parse(result);
if (jObject["errno"] == 0)
{
//设置本地token的缓存为黑名单的token做存储
await CacheOutToken(dto);
return Result.ReSuccess();
}
else
{
return Result.ReFailure(jObject["errmsg"], jObject["errno"]);
}
}
/// <summary>
/// 刷新token
/// </summary>
/// <returns></returns>
public async Task<Result<LoginInDto>> RefreshToken(string Token, string RefreshToken)
{
_logger.LogInformation("RefreshToken:" + RefreshToken);
//1.根据旧token 找到登录对象
var loginInfo = _redisClientService.GetStringKey<LoginInDto>($"ops_login_{Token}");
//2.请求PHP单点登出接口
JsonObject reqData = new JsonObject();
reqData.Add("app_id", _soaOptions.AppId);
reqData.Add("app_secret", _soaOptions.AppSecret);
reqData.Add("refresh_token", RefreshToken);
string result = _httpClientHelp.PostHttp(_soaOptions.Url + "/uc/authorize/refresh_token", reqData, true, Token);
var jObject = JsonObject.Parse(result);
LoginInDto r = new LoginInDto();
r.UserInfo = new UserInfoDto();
r.TokenInfo = new AccessTokenDto();
if (jObject["errno"] == 0)
{
string datajson = jObject["data"].ToString();
var _loginDto = JsonConvert.DeserializeObject<LoginTempDto>(datajson);
r.UserInfo = loginInfo.UserInfo;
r.SignedIn = true;
var token = await CreateToken(loginInfo.UserInfo, _loginDto, Token);
r.TokenInfo = token;
loginInfo.TokenInfo = token;
var ops_login_time = token.Expired.AddDays(1) - DateTime.Now;//用于正式
_redisClientService.SetStringKey<LoginInDto>($"ops_login_{token.Token}", loginInfo, ops_login_time);
return Result<LoginInDto>.ReSuccess(r);
}
else
{
//失败了1就把登录的token清除 2 ucid添加到黑名单
var time = new TimeSpan(r.TokenInfo.Expired.Day, r.TokenInfo.Expired.Hour, r.TokenInfo.Expired.Minute, r.TokenInfo.Expired.Second, r.TokenInfo.Expired.Millisecond);
_redisClientService.SetStringKey($"ops_black_token_{r.UserInfo.UcId}", r.TokenInfo.Token, time);
this.RemoveLoginInfo(r.TokenInfo.Token);
r.SignedIn = false;
return Result<LoginInDto>.ReFailure(jObject["errmsg"], jObject["errno"]);
}
}
/// <summary>
/// 单点退出通知token失效
/// </summary>
/// <param name="ucid"></param>
/// <param name="token"></param>
/// <param name="expires_in"></param>
/// <returns></returns>
public async Task LoginOutSingleAsync(int ucid, string token, int expires_in)
{
await Task.Run(() =>
{
var cache_token = _redisClientService.GetStringKey($"ops_black_token_{ucid}");
if (string.IsNullOrEmpty(cache_token))
{
DateTime expires_time = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)).AddSeconds(expires_in);
var time = new TimeSpan(expires_time.Day, expires_time.Hour, expires_time.Minute, expires_time.Second, expires_time.Millisecond);
_redisClientService.SetStringKey($"ops_black_token_{ucid}", token, time);
this.RemoveLoginInfo(token);
}
});
}
/// <summary>
/// 单点退出通知token失效
/// </summary>
/// <param name="SeesionId">这个是单点传过来的SeesionId</param>
/// <returns></returns>
public async Task LoginOutSingleAsync(string SeesionId)
{
var logininfo = _redisClientService.GetStringKey<LoginInDto>($"ops_login_{SeesionId}");
await Task.Run(() =>
{
if (logininfo != null)
{
var cache_token = _redisClientService.GetStringKey($"ops_black_token_{logininfo.UserInfo.UcId}");
if (string.IsNullOrEmpty(cache_token))
{
DateTime expires_time = logininfo.TokenInfo.Expired;
var time = new TimeSpan(expires_time.Day, expires_time.Hour, expires_time.Minute, expires_time.Second, expires_time.Millisecond);
_redisClientService.SetStringKey($"ops_black_token_{logininfo.UserInfo.UcId}", logininfo.TokenInfo.Token, time);
this.RemoveLoginInfo(logininfo.TokenInfo.Token);
}
}
});
}
/// <summary>
/// 缓存退出的token
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
private async Task CacheOutToken(LoginOutDto dto)
{
await Task.Run(() =>
{
if (!string.IsNullOrEmpty(dto.AccessToken))
{
var time = new TimeSpan(dto.ExpiresIn.Day, dto.ExpiresIn.Hour, dto.ExpiresIn.Minute, dto.ExpiresIn.Second, dto.ExpiresIn.Millisecond);
_redisClientService.SetStringKey($"ops_black_token_{dto.UcId}", dto.AccessToken, time);
this.RemoveLoginInfo(dto.Token);
}
});
}
/// <summary>
/// 获取登录后的信息
/// </summary>
/// <param name="authorization"></param>
/// <returns></returns>
public LoginInDto GetLoginInfo(string authorization)
{
string token = string.Empty;
if (authorization.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
{
token = authorization.Substring("Bearer ".Length).Trim();
}
var logininfo = _redisClientService.GetStringKey<LoginInDto>($"ops_login_{token}");
return logininfo;
}
/// <summary>
/// 移除登录后的用户信息
/// </summary>
/// <param name="token"></param>
private void RemoveLoginInfo(string token)
{
if (!string.IsNullOrEmpty(token))
{
var info = _redisClientService.GetStringKey<LoginInDto>($"ops_login_{token}");
if (info != null)
{
_redisClientService.RemoveStringKey($"ops_login_{token}");
}
}
}
/// <summary>
/// 单点-在线接口
/// </summary>
/// <param name="sessionId"></param>
/// <returns></returns>
public async Task<Result> Online(string sessionId)
{
var request = new { PHPSESSID = sessionId };
string result = _httpClientHelp.PostHttpNoData(_soaOptions.Url + "/uc/user/online.html?app_id=" + _soaOptions.AppId, sessionId);
return Result.ReSuccess();
}
/// <summary>
/// 单点-下线接口
/// </summary>
/// <param name="sessionId"></param>
/// <returns></returns>
public async Task<Result> Offline(string sessionId)
{
var request = new { PHPSESSID = sessionId };
string result = _httpClientHelp.PostHttpNoData(_soaOptions.Url + "/uc/user/offline.html?app_id=" + _soaOptions.AppId, sessionId);
return Result.ReSuccess();
}
}
}