Falcon.SugarApi.ClaimTicket基本完成
This commit is contained in:
parent
206916e209
commit
3c08f01c19
|
@ -1,4 +1,5 @@
|
|||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Falcon.SugarApi.ClaimTicket
|
||||
|
@ -8,23 +9,31 @@ namespace Falcon.SugarApi.ClaimTicket
|
|||
/// </summary>
|
||||
public class ClaimTicketModelBinding:IModelBinder
|
||||
{
|
||||
/// <summary>
|
||||
/// 票据创建器
|
||||
/// </summary>
|
||||
public ITicketBuilder Builter { get; set; }
|
||||
/// <summary>
|
||||
/// 配置
|
||||
/// </summary>
|
||||
public ClaimTicketOptions Options { get; set; }
|
||||
/// <summary>
|
||||
/// 票据创建器
|
||||
/// </summary>
|
||||
public ITicketBuilder TicketBuilder { get; }
|
||||
/// <summary>
|
||||
/// 日志记录
|
||||
/// </summary>
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 通过票据创建器创建模型绑定
|
||||
/// </summary>
|
||||
/// <param name="builter"></param>
|
||||
/// <param name="options"></param>
|
||||
public ClaimTicketModelBinding(ITicketBuilder builter,ClaimTicketOptions options) {
|
||||
Builter = builter;
|
||||
/// <param name="options">配置</param>
|
||||
/// <param name="ticketBuilder">票据创建器</param>
|
||||
/// <param name="logger"></param>
|
||||
public ClaimTicketModelBinding(
|
||||
ClaimTicketOptions options,
|
||||
ITicketBuilder ticketBuilder,ILogger<ClaimTicketModelBinding> logger) {
|
||||
this.Options = options;
|
||||
TicketBuilder = ticketBuilder;
|
||||
this.Logger = logger;
|
||||
}
|
||||
|
||||
Task IModelBinder.BindModelAsync(ModelBindingContext bindingContext) {
|
||||
|
@ -35,7 +44,14 @@ namespace Falcon.SugarApi.ClaimTicket
|
|||
if(token.IsNullOrEmpty()) {
|
||||
token = bindingContext.HttpContext.Request.Headers[this.Options.HttpHeaderKey].ToString();
|
||||
}
|
||||
var model = this.Builter.GetUser(token);
|
||||
UserTicket? model;
|
||||
try {
|
||||
model = this.TicketBuilder.GetUser(token);
|
||||
}
|
||||
catch(System.Exception ex) {
|
||||
this.Logger.LogError($"通过token生成用户时发生错误\n{ex}");
|
||||
return FailBind(bindingContext);
|
||||
}
|
||||
if(model == null) {
|
||||
return FailBind(bindingContext);
|
||||
}
|
||||
|
|
|
@ -15,13 +15,5 @@ namespace Falcon.SugarApi.ClaimTicket
|
|||
/// http头票据key
|
||||
/// </summary>
|
||||
public string HttpHeaderKey { get; set; } = "_authUserTicket";
|
||||
/// <summary>
|
||||
/// 安全加密组件
|
||||
/// </summary>
|
||||
public IEncryption Encryption { get; set; }
|
||||
/// <summary>
|
||||
/// 序列化组件
|
||||
/// </summary>
|
||||
public ISerialize JsonSerialize { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,6 +83,8 @@ public string Viewbind(string _authUserTicket,[FromHeader] UserTicket user) {
|
|||
一般客户端通过HTTP头参数_authUserTicket提交用户凭据,这个例子中为了方便通过get参数提交票据,控制器可以自动将其绑定在UserTicket对象中。
|
||||
因为action还通过httpbody获取了一个_authUserTicket参数,所以UserTicket需要加[FromHeader]特性。
|
||||
|
||||
## 完成以上工作基本就可以正常使用了,但是有时候我们还有一些特殊需求,可以通过下面的方式自行扩展。
|
||||
|
||||
### 6、自定义ClaimTicket配置
|
||||
通过ClaimTicketOptions对象完成配置。完成配置的途径有两个。
|
||||
> 1、在插件配置中优先注入自己的ClaimTicketOptions对象。
|
||||
|
@ -102,7 +104,7 @@ public string Viewbind(string _authUserTicket,[FromHeader] UserTicket user) {
|
|||
> }
|
||||
> }
|
||||
> ~~~
|
||||
> 2、在插件配置中优先注入自己的ClaimTicketOptions对象。
|
||||
> 2、在services.AddClaimTicket中重写ClaimTicketOptions。
|
||||
> ~~~c#
|
||||
> public class ServicePlugin:IServicePlugin
|
||||
> {
|
||||
|
@ -178,3 +180,103 @@ public class ServicePlugin:IServicePlugin
|
|||
}
|
||||
|
||||
~~~
|
||||
### 8、扩展UserTicket
|
||||
从UserTicket继承实现自己的用户类,比如以下代码实现了自己的MyUserTicket类,并添加了一个Ver属性。
|
||||
~~~c#
|
||||
public class MyUserTicket:UserTicket
|
||||
{
|
||||
public MyUserTicket() {}
|
||||
|
||||
public int Ver { get; set; }
|
||||
|
||||
public MyUserTicket(UserTicket? user) {
|
||||
this.Claims = user?.Claims;
|
||||
}
|
||||
}
|
||||
~~~
|
||||
然后还需要实现自己的ITicketBuilder实现,因为UserTicket不知道如何处理Ver。
|
||||
~~~c#
|
||||
/// <summary>
|
||||
/// 自定义票据生成方式
|
||||
/// </summary>
|
||||
public class MyTicketBuilder:TicketBuilder, ITicketBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// 使用票据参数构造生成器
|
||||
/// </summary>
|
||||
/// <param name="options">生成参数</param>
|
||||
public MyTicketBuilder(ClaimTicketOptions options,IEncryption encryption,IJsonSerialize serialize)
|
||||
: base(options,encryption,serialize) { }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string? GetTicket(UserTicket userTicket) {
|
||||
//实现自己的票据生成方法
|
||||
if(userTicket is MyUserTicket mut) {
|
||||
var obj = mut.Claims.Select(a => new ClaimKeyValue { Key = a.Type,Value = a.Value });
|
||||
var ll = obj.ToList();
|
||||
ll.Add(new ClaimKeyValue { Key = "Ver",Value = mut.Ver.ToString() });
|
||||
var str = this.Serialize.Serialize(ll);
|
||||
var code = this.Encryption.Encrypt(this.Options.EncryptionKey,str);
|
||||
return code;
|
||||
}
|
||||
//或使用基类提供的方法
|
||||
return base.GetTicket(userTicket);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override UserTicket? GetUser(string ticket) {
|
||||
//根据票据获取用户声明返回用户信息
|
||||
var str = this.Encryption.Decrypt(this.Options.EncryptionKey,ticket);
|
||||
if(str.IsNullOrEmpty()) {
|
||||
return new MyUserTicket();
|
||||
}
|
||||
var list = this.Serialize.Deserialize<List<ClaimKeyValue>>(str);
|
||||
if(list == null) {
|
||||
return new MyUserTicket();
|
||||
}
|
||||
var ut = new UserTicket(list.Select(a => new Claim(a.Key,a.Value)));
|
||||
var result = new MyUserTicket(ut);
|
||||
var verf = list.Find(a => a.Key == "Ver");
|
||||
if(verf != null) {
|
||||
result.Ver = int.Parse(verf.Value);
|
||||
}
|
||||
//或使用基类提供的方法
|
||||
return result as UserTicket;
|
||||
}
|
||||
}
|
||||
~~~
|
||||
然后使用上面的方式把ITicketBuilder注入服务。
|
||||
接着就是在登录时候使用自己的票据类
|
||||
~~~c#
|
||||
public string Login(string username) {
|
||||
//验证用户密码有效性,自行调用数据库进行验证。
|
||||
|
||||
//如果通过验证,生成用户票据
|
||||
var user = new UserTicket(
|
||||
//添加用户名
|
||||
new Claim("name",username),
|
||||
//添加其他必要的声明
|
||||
new Claim("role","admin")
|
||||
);
|
||||
var muser = new MyUserTicket(user);
|
||||
//设置自己的特有属性
|
||||
muser.Ver = 5;
|
||||
var ticket = this.TicketBuilder.GetTicket(muser);
|
||||
return ticket ?? "";
|
||||
}
|
||||
|
||||
~~~
|
||||
使用的时候可以直接注入:
|
||||
~~~c#
|
||||
public string Viewbind(string _authUserTicket,[FromHeader] MyUserTicket? user) {
|
||||
if(user == null) {
|
||||
return "绑定失败!";
|
||||
}
|
||||
StringBuilder sb = new();
|
||||
foreach(var i in user.Claims) {
|
||||
sb.AppendLine($"type:{i.Type},Val:{i.Value}");
|
||||
}
|
||||
sb.AppendLine($"user.Ver={user.Ver}");
|
||||
return sb.ToString();
|
||||
}
|
||||
~~~
|
||||
|
|
|
@ -3,10 +3,6 @@ using Falcon.SugarApi.JsonSerialize;
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Falcon.SugarApi.ClaimTicket
|
||||
{
|
||||
|
@ -22,18 +18,15 @@ namespace Falcon.SugarApi.ClaimTicket
|
|||
/// <param name="OptionBuilder">配置创建</param>
|
||||
/// <returns>服务集合</returns>
|
||||
public static IServiceCollection AddClaimTicket(this IServiceCollection services,Action<ClaimTicketOptions>? OptionBuilder = null) {
|
||||
services.TryAddSingleton<ClaimTicketOptions>(p => {
|
||||
var en = p.GetRequiredService<IEncryption>();
|
||||
var ser = p.GetRequiredService<IJsonSerialize>();
|
||||
var option = new ClaimTicketOptions {
|
||||
Encryption = en,JsonSerialize = ser,
|
||||
};
|
||||
OptionBuilder?.Invoke(option);
|
||||
return option;
|
||||
});
|
||||
services.TryAddSingleton<IEncryption,AESProvider>();
|
||||
services.TryAddSingleton<IJsonSerialize,JsonSerialize.JsonSerialize>();
|
||||
services.TryAddSingleton<ITicketBuilder,TicketBuilder>();
|
||||
|
||||
services.TryAddSingleton<ClaimTicketOptions>(p => {
|
||||
var option = new ClaimTicketOptions();
|
||||
OptionBuilder?.Invoke(option);
|
||||
return option;
|
||||
});
|
||||
services.AddControllers(op => {
|
||||
op.ModelBinderProviders.Insert(0,new ClaimTicketModelBindingProvider());
|
||||
});
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Falcon.SugarApi.Encryption;
|
||||
using Falcon.SugarApi.JsonSerialize;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
|
@ -13,24 +14,26 @@ namespace Falcon.SugarApi.ClaimTicket
|
|||
/// <summary>
|
||||
/// 构造票据生成器
|
||||
/// </summary>
|
||||
/// <param name="options">加密配置</param>
|
||||
public TicketBuilder(ClaimTicketOptions options) {
|
||||
this.Encryption = options.Encryption;
|
||||
this.Serialize = options.JsonSerialize;
|
||||
/// <param name="options">配置</param>
|
||||
/// <param name="encryption">安全加密组件</param>
|
||||
/// <param name="serialize">序列化组件</param>
|
||||
public TicketBuilder(ClaimTicketOptions options,IEncryption encryption,IJsonSerialize serialize) {
|
||||
this.Options = options;
|
||||
Encryption = encryption;
|
||||
Serialize = serialize;
|
||||
}
|
||||
/// <summary>
|
||||
/// 加密模块
|
||||
/// </summary>
|
||||
public IEncryption Encryption { get; }
|
||||
/// <summary>
|
||||
/// 序列化模块
|
||||
/// </summary>
|
||||
public ISerialize Serialize { get; }
|
||||
/// <summary>
|
||||
/// 票据生成配置
|
||||
/// </summary>
|
||||
public ClaimTicketOptions Options { get; }
|
||||
/// <summary>
|
||||
/// 安全加密组件
|
||||
/// </summary>
|
||||
public IEncryption Encryption { get; }
|
||||
/// <summary>
|
||||
/// json序列化组件
|
||||
/// </summary>
|
||||
public ISerialize Serialize { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual UserTicket? GetUser(string ticket) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user