Merge branch 'abp' of https://gitee.com/ccnetcore/Yi into abp

This commit is contained in:
陈淳
2023-12-21 08:57:17 +08:00
60 changed files with 25424 additions and 372 deletions

View File

@@ -41,6 +41,8 @@ namespace Yi.Framework.Rbac.Application.Services
private IDistributedCache<CaptchaPhoneCacheItem, CaptchaPhoneCacheKey> _phoneCache;
private readonly ICaptcha _captcha;
private readonly IGuidGenerator _guidGenerator;
private readonly RbacOptions _rbacOptions;
private readonly IAliyunManger _aliyunManger;
public AccountService(IUserRepository userRepository,
ICurrentUser currentUser,
AccountManager accountManager,
@@ -50,7 +52,11 @@ namespace Yi.Framework.Rbac.Application.Services
IOptions<JwtOptions> jwtOptions,
IDistributedCache<CaptchaPhoneCacheItem, CaptchaPhoneCacheKey> phoneCache,
ICaptcha captcha,
IGuidGenerator guidGenerator)
IGuidGenerator guidGenerator,
IOptions<RbacOptions> options,
IAliyunManger aliyunManger,
ISqlSugarRepository<RoleEntity> roleRepository,
UserManager userManager)
{
_userRepository = userRepository;
_currentUser = currentUser;
@@ -62,6 +68,10 @@ namespace Yi.Framework.Rbac.Application.Services
_phoneCache = phoneCache;
_captcha = captcha;
_guidGenerator = guidGenerator;
_rbacOptions = options.Value;
_aliyunManger = aliyunManger;
_roleRepository = roleRepository;
_userManager = userManager;
}
@@ -79,27 +89,17 @@ namespace Yi.Framework.Rbac.Application.Services
/// </summary>
private void ValidationImageCaptcha(LoginInputVo input)
{
//登录不想要验证码 ,可不效验
if (!_captcha.Validate(input.Uuid, input.Code))
if (_rbacOptions.EnableCaptcha)
{
throw new UserFriendlyException("验证码错误");
//登录不想要验证码 ,可不效验
if (!_captcha.Validate(input.Uuid, input.Code))
{
throw new UserFriendlyException("验证码错误");
}
}
}
/// <summary>
/// 效验电话验证码,需要与电话号码绑定
/// </summary>
private void ValidationPhoneCaptcha(RegisterDto input)
{
//var value = _memoryCache.Get<string>($"Yi:Phone:{input.Phone}");
//if (value is not null && value.Equals($"{input.Code}"))
//{
// //成功,需要清空
// _memoryCache.Remove($"Yi:Phone:{input.Phone}");
// return;
//}
//throw new UserFriendlyException("验证码错误");
}
/// <summary>
/// 登录
@@ -114,7 +114,7 @@ namespace Yi.Framework.Rbac.Application.Services
}
//效验验证码
// ValidationImageCaptcha(input);
ValidationImageCaptcha(input);
UserEntity user = new();
//登录成功
@@ -123,6 +123,12 @@ namespace Yi.Framework.Rbac.Application.Services
//获取用户信息
var userInfo = await _userRepository.GetUserAllInfoAsync(user.Id);
//判断用户状态
if (userInfo.User.State == false)
{
throw new UserFriendlyException(UserConst.State_Is_State);
}
if (userInfo.RoleCodes.Count == 0)
{
throw new UserFriendlyException(UserConst.No_Role);
@@ -216,19 +222,9 @@ namespace Yi.Framework.Rbac.Application.Services
//生成一个4位数的验证码
//发送短信同时生成uuid
////key 电话号码 value:验证码+uuid
//var code = _securityCode.GetRandomEnDigitalText(4);
var code = Guid.NewGuid().ToString().Substring(0, 4);
var uuid = Guid.NewGuid();
//未开启短信验证默认8888
//if (_smsAliyunManagerOptions.Value.EnableFeature)
//{
// await _smsAliyunManager.Send(input.Phone, code);
//}
//else
//{
var code = "8888";
//}
//_memoryCache.Set($"Yi:Phone:{input.Phone}", $"{code}", new TimeSpan(0, 10, 0));
await _aliyunManger.SendSmsAsync(input.Phone, code);
await _phoneCache.SetAsync(new CaptchaPhoneCacheKey(input.Phone), new CaptchaPhoneCacheItem(code), new DistributedCacheEntryOptions { SlidingExpiration = TimeSpan.FromMinutes(10) });
return new
@@ -237,6 +233,22 @@ namespace Yi.Framework.Rbac.Application.Services
};
}
/// <summary>
/// 效验电话验证码,需要与电话号码绑定
/// </summary>
private async Task ValidationPhoneCaptchaAsync(RegisterDto input)
{
var item = await _phoneCache.GetAsync(new CaptchaPhoneCacheKey(input.Phone.ToString()));
if (item is not null && item.Code.Equals($"{input.Code}"))
{
//成功,需要清空
await _phoneCache.RemoveAsync(new CaptchaPhoneCacheKey(input.Phone.ToString()));
return;
}
throw new UserFriendlyException("验证码错误");
}
/// <summary>
/// 注册,需要验证码通过
/// </summary>
@@ -246,6 +258,11 @@ namespace Yi.Framework.Rbac.Application.Services
[UnitOfWork]
public async Task<object> PostRegisterAsync(RegisterDto input)
{
if (_rbacOptions.EnableRegister == false)
{
throw new UserFriendlyException("该系统暂未开放注册功能");
}
if (input.UserName == UserConst.Admin)
{
throw new UserFriendlyException("用户名无效注册!");
@@ -260,15 +277,13 @@ namespace Yi.Framework.Rbac.Application.Services
throw new UserFriendlyException("密码需大于等于6位");
}
//效验验证码,根据电话号码获取 value比对验证码已经uuid
ValidationPhoneCaptcha(input);
await ValidationPhoneCaptchaAsync(input);
//输入的用户名与电话号码都不能在数据库中存在
UserEntity user = new();
var isExist = await _userRepository.IsAnyAsync(x =>
x.UserName == input.UserName
|| x.Phone == input.Phone);
var isExist = await _userRepository.IsAnyAsync(x =>x.UserName == input.UserName|| x.Phone == input.Phone);
if (isExist)
{
throw new UserFriendlyException("用户已存在,注册失败");
@@ -278,8 +293,7 @@ namespace Yi.Framework.Rbac.Application.Services
var entity = await _userRepository.InsertReturnEntityAsync(newUser);
//赋上一个初始角色
var roleRepository = _roleRepository;
var role = await roleRepository.GetFirstAsync(x => x.RoleCode == UserConst.GuestRoleCode);
var role = await _roleRepository.GetFirstAsync(x => x.RoleCode == UserConst.GuestRoleCode);
if (role is not null)
{
await _userManager.GiveUserSetRoleAsync(new List<Guid> { entity.Id }, new List<Guid> { role.Id });

View File

@@ -11,7 +11,7 @@
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
<PackageReference Include="Lazy.Captcha.Core" Version="2.0.7" />
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="2.88.6" />
<PackageReference Include="Volo.Abp.BackgroundWorkers.Quartz" Version="8.0.0-rc.3" />
<PackageReference Include="Volo.Abp.BackgroundWorkers.Quartz" Version="8.0.0" />
</ItemGroup>
<ItemGroup>

View File

@@ -16,6 +16,7 @@ namespace Yi.Framework.Rbac.Domain.Shared.Consts
public const string Login_User_No_Exist = "登录失败!用户名不存在!";
public const string Login_Passworld_Error = "密码为空,添加失败!";
public const string User_Exist = "用户已经存在,添加失败!";
public const string State_Is_State = "该用户已被禁用,请联系管理员进行恢复";
public const string No_Permission = "登录禁用!该用户分配无任何权限,无意义登录!";
public const string No_Role = "登录禁用!该用户分配无任何角色,无意义登录!";

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Yi.Framework.Rbac.Domain.Shared.Options
{
public class AliyunOptions
{
public string AccessKeyId { get; set; }
public string AccessKeySecret { get; set; }
public AliyunSms Sms { get; set; }
}
public class AliyunSms
{
public string SignName { get; set; }
public string TemplateCode { get; set; }
}
}

View File

@@ -12,5 +12,15 @@ namespace Yi.Framework.Rbac.Domain.Shared.Options
/// 超级管理员默认密码
/// </summary>
public string AdminPassword { get; set; } = "123456";
/// <summary>
/// 是否开启登录验证码
/// </summary>
public bool EnableCaptcha { get; set; } = false;
/// <summary>
/// 是否开启用户注册功能
/// </summary>
public bool EnableRegister { get; set; } = false;
}
}

View File

@@ -7,7 +7,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Domain.Shared" Version="8.0.0-rc.3" />
<PackageReference Include="Volo.Abp.Ddd.Domain.Shared" Version="8.0.0" />
</ItemGroup>
<ItemGroup>

View File

@@ -0,0 +1,69 @@
using AlibabaCloud.SDK.Dysmsapi20170525;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Volo.Abp.Domain.Services;
using Yi.Framework.Rbac.Domain.Shared.Options;
namespace Yi.Framework.Rbac.Domain.Managers
{
public class AliyunManger : DomainService, IAliyunManger
{
private ILogger<AliyunManger> _logger;
private AliyunOptions Options { get; set; }
public AliyunManger(ILogger<AliyunManger> logger, IOptions<AliyunOptions> options)
{
Options = options.Value;
_logger = logger;
}
private Client CreateClient()
{
AlibabaCloud.OpenApiClient.Models.Config config = new AlibabaCloud.OpenApiClient.Models.Config
{
// 必填,您的 AccessKey ID
AccessKeyId = Options.AccessKeyId,
// 必填,您的 AccessKey Secret
AccessKeySecret = Options.AccessKeySecret,
};
// 访问的域名
config.Endpoint = "dysmsapi.aliyuncs.com";
return new Client(config);
}
/// <summary>
/// 发送短信
/// </summary>
/// <param name="phoneNumbers"></param>
/// <param name="code"></param>
/// <returns></returns>
public async Task SendSmsAsync(string phoneNumbers, string code)
{
try
{
var _aliyunClient = CreateClient();
AlibabaCloud.SDK.Dysmsapi20170525.Models.SendSmsRequest sendSmsRequest = new AlibabaCloud.SDK.Dysmsapi20170525.Models.SendSmsRequest
{
PhoneNumbers = phoneNumbers,
SignName = Options.Sms.SignName,
TemplateCode = Options.Sms.TemplateCode,
TemplateParam = System.Text.Json.JsonSerializer.Serialize(new { code })
};
var response = await _aliyunClient.SendSmsAsync(sendSmsRequest);
}
catch (Exception _error)
{
_logger.LogError(_error, "阿里云短信发送错误:" + _error.Message);
}
}
}
public interface IAliyunManger
{
Task SendSmsAsync(string phoneNumbers, string code);
}
}

View File

@@ -10,13 +10,13 @@ namespace Yi.Framework.Rbac.Domain.SignalRHubs
{
[HubRoute("/hub/main")]
[Authorize]
public class OnlineUserHub : AbpHub
public class OnlineUserHub : AbpHub
{
public static readonly List<OnlineUserModel> clientUsers = new();
private HttpContext? _httpContext;
private ILogger<OnlineUserHub> _logger=> LoggerFactory.CreateLogger<OnlineUserHub>();
private ILogger<OnlineUserHub> _logger => LoggerFactory.CreateLogger<OnlineUserHub>();
public OnlineUserHub(IHttpContextAccessor httpContextAccessor)
{
_httpContext = httpContextAccessor?.HttpContext;
@@ -68,10 +68,15 @@ namespace Yi.Framework.Rbac.Domain.SignalRHubs
//判断用户是否存在,否则添加集合
if (user != null)
{
clientUsers.Remove(user);
Clients.All.SendAsync("onlineNum", clientUsers.Count);
//Clients.All.SendAsync(HubsConstant.OnlineUser, clientUsers);
_logger.LogInformation($"用户{user?.UserName}离开了,当前已连接{clientUsers.Count}个");
var clientUser = clientUsers.FirstOrDefault(x => x.ConnnectionId == user.ConnnectionId);
if (clientUser is not null)
{
clientUsers.Remove(clientUser);
Clients.All.SendAsync("onlineNum", clientUsers.Count);
//Clients.All.SendAsync(HubsConstant.OnlineUser, clientUsers);
_logger.LogInformation($"用户{user?.UserName}离开了,当前已连接{clientUsers.Count}个");
}
}
return base.OnDisconnectedAsync(exception);
}

View File

@@ -1,19 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.props" />
<ItemGroup>
<PackageReference Include="AlibabaCloud.SDK.Dysmsapi20170525" Version="2.0.24" />
<PackageReference Include="IPTools.China" Version="1.6.0" />
<PackageReference Include="TencentCloudSDK" Version="3.0.917" />
<PackageReference Include="UAParser" Version="3.1.47" />
<PackageReference Include="Volo.Abp.AspNetCore.SignalR" Version="8.0.0-rc.3" />
<PackageReference Include="Volo.Abp.AspNetCore.SignalR" Version="8.0.0" />
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="8.0.0-rc.3" />
<PackageReference Include="Volo.Abp.Caching" Version="8.0.0-rc.3" />
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="8.0.0" />
<PackageReference Include="Volo.Abp.Caching" Version="8.0.0" />
</ItemGroup>

View File

@@ -7,6 +7,7 @@ using Yi.Framework.Mapster;
using Yi.Framework.Rbac.Domain.Authorization;
using Yi.Framework.Rbac.Domain.Operlog;
using Yi.Framework.Rbac.Domain.Shared;
using Yi.Framework.Rbac.Domain.Shared.Options;
namespace Yi.Framework.Rbac.Domain
{
@@ -22,11 +23,15 @@ namespace Yi.Framework.Rbac.Domain
public override void ConfigureServices(ServiceConfigurationContext context)
{
var service = context.Services;
var configuration = context.Services.GetConfiguration();
service.AddControllers(options =>
{
options.Filters.Add<PermissionGlobalAttribute>();
options.Filters.Add<OperLogGlobalAttribute>();
});
//配置阿里云短信
Configure<AliyunOptions>(configuration.GetSection(nameof(AliyunOptions)));
}
}
}