SqlSugar开发框架逐步深入教程(第六篇)有哪些内容?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1757个文字,预计阅读时间需要8分钟。
在SqlSugar开发框架中,我们设计了系统服务层的基类,其中包含大量涉及相关数据处理操作的代码。若需追踪具体用户的操作,则需要获取当前用户信息。
在基于SqlSugar的开发框架中,我们设计了一些系统服务层的基类,在基类中会有很多涉及到相关的数据处理操作的,如果需要跟踪具体是那个用户进行操作的,那么就需要获得当前用户的身份信息,包括在Web API的控制器中也是一样,需要获得对应的用户身份信息,才能进行相关的身份鉴别和处理操作。本篇随笔介绍基于Principal的用户身份信息的存储和读取操作,以及在适用于Winform程序中的内存缓存的处理方式,从而通过在基类接口中注入用户身份信息接口方式,获得当前用户的详细身份信息。
1、用户身份接口的定义和基类接口注入为了方便获取用户身份的信息,我们定义一个接口 IApiUserSession 如下所示。
/// <summary> /// API接口授权获取的用户身份信息-接口 /// </summary> public interface IApiUserSession { /// <summary> /// 用户登录来源渠道,0为网站,1为微信,2为安卓APP,3为苹果APP /// </summary> string Channel { get; } /// <summary> /// 用户ID /// </summary> int? Id { get; } /// <summary> /// 用户名称 /// </summary> string Name { get; } /// <summary> /// 用户邮箱(可选) /// </summary> string Email { get; } /// <summary> /// 用户手机(可选) /// </summary> string Mobile { get; } /// <summary> /// 用户全名称(可选) /// </summary> string FullName { get; } /// <summary> /// 性别(可选) /// </summary> string Gender { get; } /// <summary> /// 所属公司ID(可选) /// </summary> string Company_ID { get; } /// <summary> /// 所属公司名称(可选) /// </summary> string CompanyName { get; } /// <summary> /// 所属部门ID(可选) /// </summary> string Dept_ID { get; } /// <summary> /// 所属部门名称(可选) /// </summary> string DeptName { get; } /// <summary> /// 把用户信息设置到缓存中去 /// </summary> /// <param name="info">用户登陆信息</param> /// <param name="channel">默认为空,用户登录来源渠道:0为网站,1为微信,2为安卓APP,3为苹果APP </param> void SetInfo(LoginUserInfo info, string channel = null); }
其中的SetInfo是为了在用户身份登录确认后,便于将用户信息存储起来的一个接口方法。其他属性定义用户相关的信息。
由于这个用户身份信息的接口,我们提供给基类进行使用的,默认我们在基类定义一个接口对象,并通过提供默认的NullApiUserSession实现,便于引用对应的身份属性信息。
NullApiUserSession只是提供一个默认的实现,实际在使用的时候,我们会注入一个具体的接口实现来替代它的。
/// <summary>
/// 提供一个空白实现类,具体使用IApiUserSession的时候,会使用其他实现类
/// </summary>
public class NullApiUserSession : IApiUserSession
{
/// <summary>
/// 单件实例
/// </summary>
public static NullApiUserSession Instance { get; } = new NullApiUserSession();
public string Channel => null;
public int? Id => null;
public string Name => null;
..................
/// <summary>
/// 设置信息(保留为空)
/// </summary>
public void SetInfo(LoginUserInfo info, string channel = null)
{
}
}
在之前介绍的SqlSugar框架的时候,我们介绍到数据访问操作的基类定义,如下所示。
/// <summary>
/// 基于SqlSugar的数据库访问操作的基类对象
/// </summary>
/// <typeparam name="TEntity">定义映射的实体类</typeparam>
/// <typeparam name="TKey">主键的类型,如int,string等</typeparam>
/// <typeparam name="TGetListInput">或者分页信息的条件对象</typeparam>
public abstract class MyCrudService<TEntity, TKey, TGetListInput> :
IMyCrudService<TEntity, TKey, TGetListInput>
where TEntity : class, IEntity<TKey>, new()
where TGetListInput : IPagedAndSortedResultRequest
{
/// <summary>
/// 数据库上下文信息
/// </summary>
protected DbContext dbContext;
/// <summary>
/// 当前Api用户信息
/// </summary>
public IApiUserSession CurrentApiUser { get; set; }
public MyCrudService()
{
dbContext = new DbContext();
CurrentApiUser = NullApiUserSession.Instance;//空实现
}
在最底层的操作基类中,我们就已经注入了用户身份信息,这样我们不管操作任何函数处理,都可以通过该用户身份信息接口CurrentApiUser获得对应的用户属性信息了。
在具体的业务服务层中,我们继承该基类,并提供构造函数注入方式,让基类获得对应的 IApiUserSession接口的具体实例。
/// <summary> /// 应用层服务接口实现 /// </summary> public class CustomerService : MyCrudService<CustomerInfo, string, CustomerPagedDto>, ICustomerService { /// <summary> /// 构造函数 /// </summary> /// <param name="currentApiUser">当前用户接口</param> public CustomerService(IApiUserSession currentApiUser) { this.CurrentApiUser = currentApiUser; } ........ }
如果有其他服务接口需要引入,那么我们继续增加其他接口注入即可。
/// <summary> /// 角色信息 应用层服务接口实现 /// </summary> public class RoleService : MyCrudService<RoleInfo,int, RolePagedDto>, IRoleService { private IOuService _ouService; private IUserService _userService; /// <summary> /// 默认构造函数 /// </summary> /// <param name="currentApiUser">当前用户接口</param> /// <param name="ouService">机构服务接口</param> /// <param name="userService">用户服务接口</param> public RoleService(IApiUserSession currentApiUser, IOuService ouService, IUserService userService) { this.CurrentApiUser = currentApiUser; this._ouService = ouService; this._userService = userService; }
由于该接口是通过构造函数注入的,因此在系统运行前,我们需要往IOC容器中注册对应的接口实现类(由于IApiUserSession 提供了多个接口实现,我们这里不自动加入它的对应接口,而通过手工加入)。
在Winform或者控制台程序,启动程序的时候,手工加入对应的接口到IOC容器中即可。
/// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main() { // IServiceCollection负责注册 IServiceCollection services = new ServiceCollection(); //services.AddSingleton<IDictDataService, DictDataService>(); //调用自定义的服务注册 ServiceInjection.ConfigureRepository(services); //添加IApiUserSession实现类 //services.AddSingleton<IApiUserSession, ApiUserCache>(); //缓存实现方式 services.AddSingleton<IApiUserSession, ApiUserPrincipal>(); //CurrentPrincipal实现方式
如果是Web API或者asp.net core项目中加入,也是类似的处理方式。
var builder = WebApplication.CreateBuilder(args); //配置依赖注入访问数据库 ServiceInjection.ConfigureRepository(builder.Services); //添加IApiUserSession实现类 builder.Services.AddSingleton<IApiUserSession, ApiUserPrincipal>();
前面介绍了,IApiUserSession的一个空白实现,是默认的接口实现,我们具体会使用基于Principal或者缓存方式实现记录用户身份的信息实现,如下是它们的类关系。
在上面的代码中,我们注入一个ApiUserPrincipal 的用户身份接口实现。
2、基于Principal的用户身份信息的存储和读取操作ApiUserPrincipal 的用户身份接口实现是可以实现Web及Winform的用户身份信息的存储的。
首先我们先定义一些存储声明信息的键,便于统一处理。
/// <summary> /// 定义一些常用的ClaimType存储键 /// </summary> public class ApiUserClaimTypes { public const string Id = JwtClaimTypes.Id; public const string Name = JwtClaimTypes.Name; public const string NickName = JwtClaimTypes.NickName; public const string Email = JwtClaimTypes.Email; public const string PhoneNumber = JwtClaimTypes.PhoneNumber; public const string Gender = JwtClaimTypes.Gender; public const string FullName = "FullName"; public const string Company_ID = "Company_ID"; public const string CompanyName = "CompanyName"; public const string Dept_ID = "Dept_ID"; public const string DeptName = "DeptName"; public const string Role = ClaimTypes.Role; }
ApiUserPrincipal 用户身份接口实现的定义如下代码所示。
/// <summary>
/// 基于ClaimsPrincipal实现的用户信息接口。
/// </summary>
[Serializable]
public class ApiUserPrincipal : IApiUserSession
{
/// <summary>
/// IHttpContextAccessor对象
/// </summary>
private readonly IHttpContextAccessor _www.iqidi.com
本文共计1757个文字,预计阅读时间需要8分钟。
在SqlSugar开发框架中,我们设计了系统服务层的基类,其中包含大量涉及相关数据处理操作的代码。若需追踪具体用户的操作,则需要获取当前用户信息。
在基于SqlSugar的开发框架中,我们设计了一些系统服务层的基类,在基类中会有很多涉及到相关的数据处理操作的,如果需要跟踪具体是那个用户进行操作的,那么就需要获得当前用户的身份信息,包括在Web API的控制器中也是一样,需要获得对应的用户身份信息,才能进行相关的身份鉴别和处理操作。本篇随笔介绍基于Principal的用户身份信息的存储和读取操作,以及在适用于Winform程序中的内存缓存的处理方式,从而通过在基类接口中注入用户身份信息接口方式,获得当前用户的详细身份信息。
1、用户身份接口的定义和基类接口注入为了方便获取用户身份的信息,我们定义一个接口 IApiUserSession 如下所示。
/// <summary> /// API接口授权获取的用户身份信息-接口 /// </summary> public interface IApiUserSession { /// <summary> /// 用户登录来源渠道,0为网站,1为微信,2为安卓APP,3为苹果APP /// </summary> string Channel { get; } /// <summary> /// 用户ID /// </summary> int? Id { get; } /// <summary> /// 用户名称 /// </summary> string Name { get; } /// <summary> /// 用户邮箱(可选) /// </summary> string Email { get; } /// <summary> /// 用户手机(可选) /// </summary> string Mobile { get; } /// <summary> /// 用户全名称(可选) /// </summary> string FullName { get; } /// <summary> /// 性别(可选) /// </summary> string Gender { get; } /// <summary> /// 所属公司ID(可选) /// </summary> string Company_ID { get; } /// <summary> /// 所属公司名称(可选) /// </summary> string CompanyName { get; } /// <summary> /// 所属部门ID(可选) /// </summary> string Dept_ID { get; } /// <summary> /// 所属部门名称(可选) /// </summary> string DeptName { get; } /// <summary> /// 把用户信息设置到缓存中去 /// </summary> /// <param name="info">用户登陆信息</param> /// <param name="channel">默认为空,用户登录来源渠道:0为网站,1为微信,2为安卓APP,3为苹果APP </param> void SetInfo(LoginUserInfo info, string channel = null); }
其中的SetInfo是为了在用户身份登录确认后,便于将用户信息存储起来的一个接口方法。其他属性定义用户相关的信息。
由于这个用户身份信息的接口,我们提供给基类进行使用的,默认我们在基类定义一个接口对象,并通过提供默认的NullApiUserSession实现,便于引用对应的身份属性信息。
NullApiUserSession只是提供一个默认的实现,实际在使用的时候,我们会注入一个具体的接口实现来替代它的。
/// <summary>
/// 提供一个空白实现类,具体使用IApiUserSession的时候,会使用其他实现类
/// </summary>
public class NullApiUserSession : IApiUserSession
{
/// <summary>
/// 单件实例
/// </summary>
public static NullApiUserSession Instance { get; } = new NullApiUserSession();
public string Channel => null;
public int? Id => null;
public string Name => null;
..................
/// <summary>
/// 设置信息(保留为空)
/// </summary>
public void SetInfo(LoginUserInfo info, string channel = null)
{
}
}
在之前介绍的SqlSugar框架的时候,我们介绍到数据访问操作的基类定义,如下所示。
/// <summary>
/// 基于SqlSugar的数据库访问操作的基类对象
/// </summary>
/// <typeparam name="TEntity">定义映射的实体类</typeparam>
/// <typeparam name="TKey">主键的类型,如int,string等</typeparam>
/// <typeparam name="TGetListInput">或者分页信息的条件对象</typeparam>
public abstract class MyCrudService<TEntity, TKey, TGetListInput> :
IMyCrudService<TEntity, TKey, TGetListInput>
where TEntity : class, IEntity<TKey>, new()
where TGetListInput : IPagedAndSortedResultRequest
{
/// <summary>
/// 数据库上下文信息
/// </summary>
protected DbContext dbContext;
/// <summary>
/// 当前Api用户信息
/// </summary>
public IApiUserSession CurrentApiUser { get; set; }
public MyCrudService()
{
dbContext = new DbContext();
CurrentApiUser = NullApiUserSession.Instance;//空实现
}
在最底层的操作基类中,我们就已经注入了用户身份信息,这样我们不管操作任何函数处理,都可以通过该用户身份信息接口CurrentApiUser获得对应的用户属性信息了。
在具体的业务服务层中,我们继承该基类,并提供构造函数注入方式,让基类获得对应的 IApiUserSession接口的具体实例。
/// <summary> /// 应用层服务接口实现 /// </summary> public class CustomerService : MyCrudService<CustomerInfo, string, CustomerPagedDto>, ICustomerService { /// <summary> /// 构造函数 /// </summary> /// <param name="currentApiUser">当前用户接口</param> public CustomerService(IApiUserSession currentApiUser) { this.CurrentApiUser = currentApiUser; } ........ }
如果有其他服务接口需要引入,那么我们继续增加其他接口注入即可。
/// <summary> /// 角色信息 应用层服务接口实现 /// </summary> public class RoleService : MyCrudService<RoleInfo,int, RolePagedDto>, IRoleService { private IOuService _ouService; private IUserService _userService; /// <summary> /// 默认构造函数 /// </summary> /// <param name="currentApiUser">当前用户接口</param> /// <param name="ouService">机构服务接口</param> /// <param name="userService">用户服务接口</param> public RoleService(IApiUserSession currentApiUser, IOuService ouService, IUserService userService) { this.CurrentApiUser = currentApiUser; this._ouService = ouService; this._userService = userService; }
由于该接口是通过构造函数注入的,因此在系统运行前,我们需要往IOC容器中注册对应的接口实现类(由于IApiUserSession 提供了多个接口实现,我们这里不自动加入它的对应接口,而通过手工加入)。
在Winform或者控制台程序,启动程序的时候,手工加入对应的接口到IOC容器中即可。
/// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main() { // IServiceCollection负责注册 IServiceCollection services = new ServiceCollection(); //services.AddSingleton<IDictDataService, DictDataService>(); //调用自定义的服务注册 ServiceInjection.ConfigureRepository(services); //添加IApiUserSession实现类 //services.AddSingleton<IApiUserSession, ApiUserCache>(); //缓存实现方式 services.AddSingleton<IApiUserSession, ApiUserPrincipal>(); //CurrentPrincipal实现方式
如果是Web API或者asp.net core项目中加入,也是类似的处理方式。
var builder = WebApplication.CreateBuilder(args); //配置依赖注入访问数据库 ServiceInjection.ConfigureRepository(builder.Services); //添加IApiUserSession实现类 builder.Services.AddSingleton<IApiUserSession, ApiUserPrincipal>();
前面介绍了,IApiUserSession的一个空白实现,是默认的接口实现,我们具体会使用基于Principal或者缓存方式实现记录用户身份的信息实现,如下是它们的类关系。
在上面的代码中,我们注入一个ApiUserPrincipal 的用户身份接口实现。
2、基于Principal的用户身份信息的存储和读取操作ApiUserPrincipal 的用户身份接口实现是可以实现Web及Winform的用户身份信息的存储的。
首先我们先定义一些存储声明信息的键,便于统一处理。
/// <summary> /// 定义一些常用的ClaimType存储键 /// </summary> public class ApiUserClaimTypes { public const string Id = JwtClaimTypes.Id; public const string Name = JwtClaimTypes.Name; public const string NickName = JwtClaimTypes.NickName; public const string Email = JwtClaimTypes.Email; public const string PhoneNumber = JwtClaimTypes.PhoneNumber; public const string Gender = JwtClaimTypes.Gender; public const string FullName = "FullName"; public const string Company_ID = "Company_ID"; public const string CompanyName = "CompanyName"; public const string Dept_ID = "Dept_ID"; public const string DeptName = "DeptName"; public const string Role = ClaimTypes.Role; }
ApiUserPrincipal 用户身份接口实现的定义如下代码所示。
/// <summary>
/// 基于ClaimsPrincipal实现的用户信息接口。
/// </summary>
[Serializable]
public class ApiUserPrincipal : IApiUserSession
{
/// <summary>
/// IHttpContextAccessor对象
/// </summary>
private readonly IHttpContextAccessor _www.iqidi.com

