权限认证

This commit is contained in:
橙子
2022-04-06 22:22:45 +08:00
parent 5fcf5bd583
commit a6a2025972
13 changed files with 202 additions and 108 deletions

View File

@@ -2,6 +2,7 @@
using Yi.Framework.Common.Models; using Yi.Framework.Common.Models;
using Yi.Framework.Model.Query; using Yi.Framework.Model.Query;
using Yi.Framework.Repository; using Yi.Framework.Repository;
using Yi.Framework.WebCore.AttributeExtend;
namespace Yi.Framework.ApiMicroservice.Controllers namespace Yi.Framework.ApiMicroservice.Controllers
{ {
@@ -10,38 +11,45 @@ namespace Yi.Framework.ApiMicroservice.Controllers
public class BaseCrudController<T> : ControllerBase where T : class,new() public class BaseCrudController<T> : ControllerBase where T : class,new()
{ {
private readonly ILogger<T> _logger; private readonly ILogger<T> _logger;
public IRepository<T> _iRepository; public IRepository<T> _iRepository;
public BaseCrudController(ILogger<T> logger, IRepository<T> iRepository) public BaseCrudController(ILogger<T> logger, IRepository<T> iRepository)
{ {
_logger = logger; _logger = logger;
_iRepository = iRepository; _iRepository = iRepository;
} }
[Permission($"{nameof(T)}:Get:One")]
[HttpGet] [HttpGet]
public async Task<Result> Get() public async Task<Result> Get(object id)
{
return Result.Success().SetData(await _iRepository.GetByIdAsync(id));
}
[Permission($"{nameof(T)}:Get:List")]
[HttpGet]
public async Task<Result> GetList()
{ {
return Result.Success().SetData(await _iRepository.GetListAsync()); return Result.Success().SetData(await _iRepository.GetListAsync());
} }
[Permission($"{nameof(T)}:Get:Page")]
[HttpPost] [HttpPost]
public async Task<Result> Page(QueryCondition queryCondition) public async Task<Result> Page(QueryCondition queryCondition)
{ {
return Result.Success().SetData(_iRepository.CommonPage(queryCondition)); return Result.Success().SetData(await _iRepository.CommonPage(queryCondition));
} }
[Permission($"{nameof(T)}:Add")]
[HttpPost] [HttpPost]
public async Task<Result> Add(T entity) public async Task<Result> Add(T entity)
{ {
return Result.Success().SetData(await _iRepository.InsertReturnEntityAsync(entity)); return Result.Success().SetData(await _iRepository.InsertReturnEntityAsync(entity));
} }
[Permission($"{nameof(T)}:Update")]
[HttpPut] [HttpPut]
public async Task<Result> Update(T entity) public async Task<Result> Update(T entity)
{ {
return Result.Success().SetStatus(await _iRepository.UpdateAsync(entity)); return Result.Success().SetStatus(await _iRepository.UpdateAsync(entity));
} }
[Permission($"{nameof(T)}:Delete:List")]
[HttpDelete] [HttpDelete]
public async Task<Result> Delete(object[] ids) public async Task<Result> DeleteList(object[] ids)
{ {
return Result.Success().SetStatus(await _iRepository.DeleteByIdsAsync(ids)); return Result.Success().SetStatus(await _iRepository.DeleteByIdsAsync(ids));
} }

View File

@@ -10,6 +10,7 @@ using Yi.Framework.Interface;
using Yi.Framework.Model.Models; using Yi.Framework.Model.Models;
using Yi.Framework.Repository; using Yi.Framework.Repository;
using Yi.Framework.WebCore; using Yi.Framework.WebCore;
using Yi.Framework.WebCore.AttributeExtend;
using Yi.Framework.WebCore.AuthorizationPolicy; using Yi.Framework.WebCore.AuthorizationPolicy;
namespace Yi.Framework.ApiMicroservice.Controllers namespace Yi.Framework.ApiMicroservice.Controllers
@@ -20,12 +21,13 @@ namespace Yi.Framework.ApiMicroservice.Controllers
{ {
public UserController(ILogger<UserEntity> logger, IUserService iUserService) : base(logger, iUserService) public UserController(ILogger<UserEntity> logger, IUserService iUserService) : base(logger, iUserService)
{ {
} }
[HttpGet] [HttpGet]
public async Task<IActionResult> Test() [Permission("user:query:list")]
public async Task<Result> PermissionTest()
{ {
return Ok(await _iRepository.GetListAsync()); return Result.Success().SetData( await _iRepository.GetListAsync());
} }
} }
} }

View File

@@ -7,6 +7,7 @@ using Autofac;
using Yi.Framework.Common.Models; using Yi.Framework.Common.Models;
using Yi.Framework.Language; using Yi.Framework.Language;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Yi.Framework.WebCore.AttributeExtend;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddCommandLine(args); builder.Configuration.AddCommandLine(args);
@@ -48,6 +49,10 @@ builder.Host.ConfigureLogging(loggingBuilder =>
#endregion #endregion
builder.Services.AddIocService(builder.Configuration); builder.Services.AddIocService(builder.Configuration);
#region #region
//Sqlsugar<61><72><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><D7A2>
#endregion
builder.Services.AddSqlsugarServer();
#region
//Quartz<74><7A><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> //Quartz<74><7A><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#endregion #endregion
builder.Services.AddQuartzService(); builder.Services.AddQuartzService();
@@ -55,9 +60,13 @@ builder.Services.AddQuartzService();
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>+<2B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>+<2B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#endregion #endregion
builder.Services.AddControllers(optios => { builder.Services.AddControllers(optios => {
//optios.Filters.Add(typeof(CustomExceptionFilterAttribute)); //optios.Filters.Add<PermissionAttribute>();
}).AddJsonFileService(); }).AddJsonFileService();
#region #region
//Ȩ<>޹<EFBFBD><DEB9><EFBFBD><EFBFBD><EFBFBD>
#endregion
builder.Services.AddSingleton<PermissionAttribute>();
#region
//Swagger<65><72><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> //Swagger<65><72><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#endregion #endregion
builder.Services.AddSwaggerService<Program>(); builder.Services.AddSwaggerService<Program>();
@@ -92,8 +101,7 @@ builder.Services.AddSMSService();
#region #region
//CAP<41><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> //CAP<41><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#endregion #endregion
builder.Services.AddCAPService<Program>(); builder.Services.AddCAPService();
#region #region
//<2F><><EFBFBD>ʻ<EFBFBD><CABB><EFBFBD><EFBFBD><EFBFBD> //<2F><><EFBFBD>ʻ<EFBFBD><CABB><EFBFBD><EFBFBD><EFBFBD>
#endregion #endregion
@@ -119,17 +127,15 @@ ServiceLocator.Instance = app.Services;
#region #region
//<2F><><EFBFBD><EFBFBD>ץȡ<D7A5><C8A1><EFBFBD><EFBFBD>ע<EFBFBD><D7A2> //<2F><><EFBFBD><EFBFBD>ץȡ<D7A5><C8A1><EFBFBD><EFBFBD>ע<EFBFBD><D7A2>
#endregion #endregion
//app.UseErrorHandlingService(); app.UseErrorHandlingService();
#region #region
//<2F><>̬<EFBFBD>ļ<EFBFBD>ע<EFBFBD><D7A2> //<2F><>̬<EFBFBD>ļ<EFBFBD>ע<EFBFBD><D7A2>
#endregion #endregion
//app.UseStaticFiles(); app.UseStaticFiles();
#region #region
//<2F><><EFBFBD><EFBFBD><EFBFBD>Թ<EFBFBD><D4B9>ʻ<EFBFBD>ע<EFBFBD><D7A2> //<2F><><EFBFBD><EFBFBD><EFBFBD>Թ<EFBFBD><D4B9>ʻ<EFBFBD>ע<EFBFBD><D7A2>
#endregion #endregion
app.UseLocalizerService(); app.UseLocalizerService();
#region #region
//HttpsRedirectionע<6E><D7A2> //HttpsRedirectionע<6E><D7A2>
#endregion #endregion
@@ -161,7 +167,7 @@ app.UseConsulService();
#region #region
//redis<69><73><EFBFBD><EFBFBD>ע<EFBFBD><D7A2> //redis<69><73><EFBFBD><EFBFBD>ע<EFBFBD><D7A2>
#endregion #endregion
app.UseRedisSeedInitService(app.Services.GetService<CacheClientDB>()); app.UseRedisSeedInitService();
#region #region
//Endpointsע<73><D7A2> //Endpointsע<73><D7A2>
#endregion #endregion

View File

@@ -6,8 +6,14 @@ using System.Threading.Tasks;
namespace Yi.Framework.Common.Models namespace Yi.Framework.Common.Models
{ {
public class PageModel
{
public class PageModel<T>
{
public int Total { get; set; }
public T Data { get; set; }
}
public class PageModel : PageModel<object>
{
} }
} }

View File

@@ -5,68 +5,11 @@ namespace Yi.Framework.Repository
{ {
public class DataContext<T> : SimpleClient<T> where T : class, new() public class DataContext<T> : SimpleClient<T> where T : class, new()
{ {
public DataContext(ISqlSugarClient context = null!) : base(context) public DataContext(ISqlSugarClient context) : base(context)
{ {
if (context == null) Db =base.Context;
{
base.Context = Db;
}
} }
/// <summary>
/// SqlSugarScope操作数据库是线程安的可以单例 public ISqlSugarClient Db;
/// </summary>
public static SqlSugarScope Db = new SqlSugarScope(new ConnectionConfig()
{
DbType = SqlSugar.DbType.MySql,
//ConnectionString = Appsettings.app("ConnectionStrings", "mysqlConnection"),
ConnectionString= "server=119.91.207.67;port=3306;database=yi-sqlsugar-dev;user id=root;password=Qz52013142020.",
IsAutoCloseConnection = true
},
db =>
{
db.Aop.DataExecuting = (oldValue, entityInfo) =>
{
//var httpcontext = ServiceLocator.Instance.GetService<IHttpContextAccessor>().HttpContext;
switch (entityInfo.OperationType)
{
case DataFilterType.InsertByObject:
if (entityInfo.PropertyName == "CreateUser")
{
//entityInfo.SetValue(new Guid(httpcontext.Request.Headers["Id"].ToString()));
}
if (entityInfo.PropertyName == "TenantId")
{
//现在不能直接给了要根据判断一下租户等级如果租户等级是1不给需要自己去赋值如果租户等级是0就执行下面的。
//entityInfo.SetValue(new Guid(httpcontext.Request.Headers["TenantId"].ToString()));
//查询的时候,也需要判断一下,如果是租户等级,不要租户条件,如果是超级租户,就返回所有
}
break;
case DataFilterType.UpdateByObject:
if (entityInfo.PropertyName == "ModifyTime")
{
entityInfo.SetValue(DateTime.Now);
}
if (entityInfo.PropertyName == "ModifyUser")
{
//entityInfo.SetValue(new Guid(httpcontext.Request.Headers["Id"].ToString()));
}
break;
}
//inset生效
};
//如果用单例配置要统一写在这儿
db.Aop.OnLogExecuting = (s, p) =>
{
Console.WriteLine("_______________________________________________");
Console.WriteLine(s);
};
});
} }
} }

View File

@@ -5,6 +5,7 @@ using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Yi.Framework.Common.Models;
using Yi.Framework.Model.Query; using Yi.Framework.Model.Query;
namespace Yi.Framework.Repository namespace Yi.Framework.Repository
@@ -13,6 +14,6 @@ namespace Yi.Framework.Repository
{ {
public Task<T> InsertReturnEntityAsync(T entity); public Task<T> InsertReturnEntityAsync(T entity);
public Task<List<S>> StoreAsync<S>(string storeName, object para); public Task<List<S>> StoreAsync<S>(string storeName, object para);
public object CommonPage(QueryCondition queryCondition); public Task<PageModel<List<T>>> CommonPage(QueryCondition pars);
} }
} }

View File

@@ -1,6 +1,7 @@
using SqlSugar; using SqlSugar;
using System.Data; using System.Data;
using System.Linq.Expressions; using System.Linq.Expressions;
using Yi.Framework.Common.Models;
using Yi.Framework.Model.Query; using Yi.Framework.Model.Query;
/***这里面写的代码不会给覆盖,如果要重新生成请删除 Repository.cs ***/ /***这里面写的代码不会给覆盖,如果要重新生成请删除 Repository.cs ***/
@@ -17,12 +18,8 @@ namespace Yi.Framework.Repository
/// 构造函数 /// 构造函数
/// </summary> /// </summary>
/// <param name="context"></param> /// <param name="context"></param>
public Repository(ISqlSugarClient context = null) : base(context)//注意这里要有默认值等于null public Repository(ISqlSugarClient context) : base(context)//注意这里要有默认值等于null
{ {
if (context == null)
{
base.Context = Db;
}
} }
@@ -52,9 +49,9 @@ namespace Yi.Framework.Repository
/// 仓储扩展方法:单表查询通用分页 /// 仓储扩展方法:单表查询通用分页
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public object CommonPage(QueryCondition pars) public async Task<PageModel<List<T>>> CommonPage(QueryCondition pars)
{ {
int tolCount = 0; RefAsync<int> tolCount = 0;
var sugarParamters = pars.Parameters.Select(it => (IConditionalModel)new ConditionalModel() var sugarParamters = pars.Parameters.Select(it => (IConditionalModel)new ConditionalModel()
{ {
ConditionalType = it.ConditionalType, ConditionalType = it.ConditionalType,
@@ -66,14 +63,15 @@ namespace Yi.Framework.Repository
{ {
foreach (var item in pars.OrderBys) foreach (var item in pars.OrderBys)
{ {
query.OrderBy(item.ToSqlFilter());//格式 id asc或者 id desc query.OrderBy(item.ToSqlFilter());
} }
} }
var result = query.Where(sugarParamters).ToPageList(pars.Index, pars.Size, ref tolCount); var result =await query.Where(sugarParamters).ToPageListAsync(pars.Index, pars.Size, tolCount);
return new
return new PageModel<List<T>>
{ {
count = tolCount, Total = tolCount.Value,
data = result Data = result
}; };
} }
} }

View File

@@ -1,11 +1,14 @@
using Yi.Framework.Interface; using SqlSugar;
using Yi.Framework.Interface;
using Yi.Framework.Model.Models; using Yi.Framework.Model.Models;
using Yi.Framework.Repository; using Yi.Framework.Repository;
namespace Yi.Framework.Service namespace Yi.Framework.Service
{ {
public partial class UserService public partial class UserService
{ {
public UserService(ISqlSugarClient context) : base(context)
{
}
} }
} }

View File

@@ -0,0 +1,51 @@
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Yi.Framework.WebCore.AttributeExtend
{
[AttributeUsage(AttributeTargets.Method)]
public class PermissionAttribute : ActionFilterAttribute
{
private string permission { get; set; }
public PermissionAttribute(string permission)
{
this.permission = permission;
}
/// <summary>
/// 动作鉴权
/// </summary>
/// <param name="context"></param>
/// <exception cref="Exception"></exception>
public override void OnActionExecuting(ActionExecutingContext context)
{
base.OnActionExecuting(context);
if (string.IsNullOrEmpty(permission))
{
throw new Exception("权限不能为空!");
}
//可以从Redis得到用户菜单列表或者直接从jwt中获取
var result = false;
//判断权限是否存在Redis中
if (permission.Length>0)
{
result = true;
}
if (!result)
{
throw new Exception("拦截未授权请求!");
}
}
}
}

View File

@@ -12,7 +12,7 @@ namespace Yi.Framework.WebCore.MiddlewareExtend
{ {
public static class CAPExtend public static class CAPExtend
{ {
public static IServiceCollection AddCAPService<T>(this IServiceCollection services) public static IServiceCollection AddCAPService(this IServiceCollection services)
{ {
if (Appsettings.appBool("CAP_Enabled")) if (Appsettings.appBool("CAP_Enabled"))
{ {
@@ -31,9 +31,9 @@ namespace Yi.Framework.WebCore.MiddlewareExtend
x.FailedRetryInterval = 60;//second x.FailedRetryInterval = 60;//second
x.FailedThresholdCallback = failed => x.FailedThresholdCallback = failed =>
{ {
var logger = failed.ServiceProvider.GetService<ILogger<T>>(); //var logger = failed.ServiceProvider.GetService<ILogger<T>>();
logger.LogError($@"MessageType {failed.MessageType} 失败了, 重试了 {x.FailedRetryCount} 次, //logger.LogError($@"MessageType {failed.MessageType} 失败了, 重试了 {x.FailedRetryCount} 次,
消息名称: {failed.Message.GetName()}");//do anything //消息名称: {failed.Message.GetName()}");//do anything
}; };
if (Appsettings.appBool("CAPDashboard_Enabled")) if (Appsettings.appBool("CAPDashboard_Enabled"))
{ {

View File

@@ -1,11 +1,13 @@
using log4net; using log4net;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Yi.Framework.Common.Models;
using Yi.Framework.Core; using Yi.Framework.Core;
namespace Yi.Framework.WebCore.MiddlewareExtend namespace Yi.Framework.WebCore.MiddlewareExtend
@@ -13,12 +15,12 @@ namespace Yi.Framework.WebCore.MiddlewareExtend
public static class RedisInitExtend public static class RedisInitExtend
{ {
private static readonly ILog log = LogManager.GetLogger(typeof(RedisInitExtend)); private static readonly ILog log = LogManager.GetLogger(typeof(RedisInitExtend));
public static void UseRedisSeedInitService(this IApplicationBuilder app, CacheClientDB _cacheClientDB) public static void UseRedisSeedInitService(this IApplicationBuilder app )
{ {
if (Appsettings.appBool("RedisSeed_Enabled")) if (Appsettings.appBool("RedisSeed_Enabled"))
{ {
if (app == null) throw new ArgumentNullException(nameof(app)); var _cacheClientDB = ServiceLocator.Instance.GetService<CacheClientDB>();
try try
{ {

View File

@@ -0,0 +1,72 @@
using Microsoft.Extensions.DependencyInjection;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Yi.Framework.WebCore.MiddlewareExtend
{
public static class SqlsugarExtension
{
public static void AddSqlsugarServer(this IServiceCollection services)
{
SqlSugarScope sqlSugar = new SqlSugarScope(new ConnectionConfig()
{
DbType = SqlSugar.DbType.MySql,
ConnectionString = Appsettings.app("DbConn", "WriteUrl"),
IsAutoCloseConnection = true
},
db =>
{
db.Aop.DataExecuting = (oldValue, entityInfo) =>
{
//var httpcontext = ServiceLocator.Instance.GetService<IHttpContextAccessor>().HttpContext;
switch (entityInfo.OperationType)
{
case DataFilterType.InsertByObject:
if (entityInfo.PropertyName == "CreateUser")
{
//entityInfo.SetValue(new Guid(httpcontext.Request.Headers["Id"].ToString()));
}
if (entityInfo.PropertyName == "TenantId")
{
//现在不能直接给了要根据判断一下租户等级如果租户等级是1不给需要自己去赋值如果租户等级是0就执行下面的。
//entityInfo.SetValue(new Guid(httpcontext.Request.Headers["TenantId"].ToString()));
//查询的时候,也需要判断一下,如果是租户等级,不要租户条件,如果是超级租户,就返回所有
}
break;
case DataFilterType.UpdateByObject:
if (entityInfo.PropertyName == "ModifyTime")
{
entityInfo.SetValue(DateTime.Now);
}
if (entityInfo.PropertyName == "ModifyUser")
{
//entityInfo.SetValue(new Guid(httpcontext.Request.Headers["Id"].ToString()));
}
break;
}
//inset生效
};
//如果用单例配置要统一写在这儿
db.Aop.OnLogExecuting = (s, p) =>
{
Console.WriteLine("_______________________________________________");
Console.WriteLine(s);
};
});
services.AddSingleton<ISqlSugarClient>(sqlSugar);//这边是SqlSugarScope用AddSingleton
}
}
}

View File

@@ -4,6 +4,12 @@
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Compile Remove="Init\**" />
<EmbeddedResource Remove="Init\**" />
<None Remove="Init\**" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Autofac" Version="6.3.0" /> <PackageReference Include="Autofac" Version="6.3.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="7.2.0" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="7.2.0" />
@@ -32,8 +38,4 @@
<ProjectReference Include="..\Yi.Framework.Model\Yi.Framework.Model.csproj" /> <ProjectReference Include="..\Yi.Framework.Model\Yi.Framework.Model.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Init\" />
</ItemGroup>
</Project> </Project>