Falcon.SugarApi/Falcon.SugarApi/ClaimTicket/Readme.md
2024-05-07 11:43:05 +08:00

283 lines
8.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 客户凭据 Falcon.SugarApi.ClaimTicket.ClaimTicket
### 1、添加ClaimTicket支持。
是否使用ClaimTicket由插件自行决定。
如果插件需要使用ClaimTicket按如下方式在插件服务配置中添加。
~~~C#
public class ServicePlugin:IServicePlugin
{
IServiceCollection IServicePlugin.AddServices(IServiceCollection services,IConfiguration configuration) {
//注入使用ClaimTicket的控制器
services.AddPluginsController(this.GetType().Assembly);
//添加ClaimTicket服务支持
services.AddClaimTicket();
return services;
}
}
~~~
### 2、控制器注入
要完成用户的登录认证和绑定工作需要注入ITicketBuilder接口这个接口在上面的services.AddClaimTicket()中已经完成注入。
下面是在HomeController控制器中注入ITicketBuilder的示例。
~~~C#
public ITicketBuilder TicketBuilder { get; set; }
public HomeController(IServiceProvider service) : base(service) {
this.TicketBuilder = service.GetRequiredService<ITicketBuilder>();
}
~~~
### 3、用户登录。
插件需要自行完成用户认证工作,示例代码如下。
~~~c#
[HttpGet]
public string Login(string username) {
//验证用户有效性,自行调用数据库进行验证。
//如果通过验证,生成用户票据
var user = new UserTicket(
//添加用户名
new Claim("name",username),
//添加其他必要的声明
new Claim("role","admin")
);
var ticket = this.TicketBuilder.GetTicket(user);
return ticket ?? "";
}
~~~
客户端在收到返回的票据后自行保管票据。
### 4、验证用户
实例代码如下:
~~~c#
[HttpGet]
public string ViewUser(string ticket) {
//通过票据获取用户
var cs = this.TicketBuilder.GetUser(ticket);
if(cs == null) {
return "TicketBuilder.GetUser 返回空";
}
StringBuilder sb = new();
//轮训票据生成获取登录信息
foreach(var i in cs.Claims) {
sb.AppendLine($"type:{i.Type},Val:{i.Value}");
}
return sb.ToString();
}
~~~
### 5、绑定用户
示例代码如下:
~~~c#
[HttpGet]
public string Viewbind(string _authUserTicket,[FromHeader] UserTicket user) {
StringBuilder sb = new();
foreach(var i in user.Claims) {
sb.AppendLine($"type:{i.Type},Val:{i.Value}");
}
return sb.ToString();
}
~~~
一般客户端通过HTTP头参数_authUserTicket提交用户凭据这个例子中为了方便通过get参数提交票据控制器可以自动将其绑定在UserTicket对象中。
因为action还通过httpbody获取了一个_authUserTicket参数所以UserTicket需要加[FromHeader]特性。
## 完成以上工作基本就可以正常使用了,但是有时候我们还有一些特殊需求,可以通过下面的方式自行扩展。
### 6、自定义ClaimTicket配置
通过ClaimTicketOptions对象完成配置。完成配置的途径有两个。
> 1、在插件配置中优先注入自己的ClaimTicketOptions对象。
> ~~~c#
> public class ServicePlugin:IServicePlugin
> {
> IServiceCollection IServicePlugin.AddServices(IServiceCollection services,IConfiguration configuration) {
> //注入使用ClaimTicket的控制器
> services.AddPluginsController(this.GetType().Assembly);
>
> //优先添加自己的服务配置
> services.AddSingleton(new ClaimTicketOptions());
>
> //添加ClaimTicket服务支持
> services.AddClaimTicket();
> return services;
> }
> }
> ~~~
> 2、在services.AddClaimTicket中重写ClaimTicketOptions。
> ~~~c#
> public class ServicePlugin:IServicePlugin
> {
> IServiceCollection IServicePlugin.AddServices(IServiceCollection services,IConfiguration configuration) {
> //注入使用ClaimTicket的控制器
> services.AddPluginsController(this.GetType().Assembly);
>
> //优先添加自己的服务配置
> //services.AddSingleton(new ClaimTicketOptions());
>
> //添加ClaimTicket服务支持
> services.AddClaimTicket(optionsBuilder => {
> //客户端通过_headCalimTick属性提交凭据
> optionsBuilder.HttpHeaderKey = "_headCalimTick";
> });
> return services;
> }
> }
> ~~~
### 7、扩展ITicketBuilder
插件可以自行扩展票据的生成方式方法有两个一个是继承TicketBuilder对象并重写方法另一个就是自己实现ITicketBuilder接口。
~~~c#
/// <summary>
/// 自定义票据生成方式
/// </summary>
public class MyTicketBuilder:TicketBuilder, ITicketBuilder
{
/// <summary>
/// 使用票据参数构造生成器
/// </summary>
/// <param name="options">生成参数</param>
public MyTicketBuilder(ClaimTicketOptions options) : base(options) { }
/// <inheritdoc/>
public override string? GetTicket(UserTicket userTicket) {
//实现自己的票据生成方法
//或使用基类提供的方法
return base.GetTicket(userTicket);
}
/// <inheritdoc/>
public override UserTicket? GetUser(string ticket) {
//根据票据获取用户声明返回用户信息
//或使用基类提供的方法
return base.GetUser(ticket);
}
}
~~~
然后在调用AddClaimTicket之前注入自己的ITicketBuilder
~~~c#
public class ServicePlugin:IServicePlugin
{
IServiceCollection IServicePlugin.AddServices(IServiceCollection services,IConfiguration configuration) {
//注入使用ClaimTicket的控制器
services.AddPluginsController(this.GetType().Assembly);
//优先添加自己的服务配置
//services.AddSingleton(new ClaimTicketOptions());
//注入扩展MyTicketBuilder
services.TryAddSingleton<ITicketBuilder,MyTicketBuilder>();
//添加ClaimTicket服务支持
services.AddClaimTicket(optionsBuilder => {
//客户端通过_headCalimTick属性提交凭据
optionsBuilder.HttpHeaderKey = "_headCalimTick";
});
return services;
}
}
~~~
### 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();
}
~~~