添加了授权

This commit is contained in:
CortexCore 2023-09-21 03:49:27 +08:00
parent c59d513cca
commit c65fe87a6c
10 changed files with 317 additions and 20 deletions

View File

@ -0,0 +1,58 @@
[gd_scene load_steps=7 format=3 uid="uid://c44tc60r5df3j"]
[ext_resource type="Script" path="res://BITKit/Scripts/Components/OpenUrl.cs" id="1_pw177"]
[ext_resource type="Script" path="res://BITKit/Scripts/ECS/Core/Entity.cs" id="2_j02yv"]
[ext_resource type="Script" path="res://BITKit/Scripts/Net/HttpListener_GodotBased.cs" id="3_kek8q"]
[ext_resource type="Script" path="res://Artists/Scripts/License/LicenseService.cs" id="4_lycvf"]
[ext_resource type="Script" path="res://Mods/工业数据采集与分析应用分享/Scripts/IDIS_License.cs" id="5_ic0bm"]
[ext_resource type="PackedScene" uid="uid://bu5w3n4me3xj2" path="res://Mods/教育平台/教育平台主菜单.tscn" id="6_6ccua"]
[node name="InitialLicense" type="Node"]
[node name="ColorRect" type="ColorRect" parent="."]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
color = Color(0.0117647, 0.0117647, 0.0117647, 1)
[node name="CenterContainer" type="CenterContainer" parent="ColorRect"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="VBoxContainer" type="VBoxContainer" parent="ColorRect/CenterContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="ColorRect/CenterContainer/VBoxContainer"]
layout_mode = 2
text = "等待激活许可证中"
[node name="Button" type="Button" parent="ColorRect/CenterContainer/VBoxContainer"]
layout_mode = 2
text = "点击开始加载许可证"
script = ExtResource("1_pw177")
url = "http://server.bitfall.icu:5252/oauth"
[node name="授权服务" type="Node" parent="."]
script = ExtResource("2_j02yv")
[node name="HttpListener" type="Node" parent="授权服务"]
script = ExtResource("3_kek8q")
autoStart = true
port = 5348
[node name="License" type="Node" parent="授权服务"]
script = ExtResource("4_lycvf")
_requestAuthorizeUrl = "http://server.bitfall.icu:5252/api/authorize"
[node name="IDIS License" type="Node" parent="授权服务" node_paths=PackedStringArray("licenseNode")]
script = ExtResource("5_ic0bm")
initialScene = ExtResource("6_6ccua")
licenseNode = NodePath("../../ColorRect")
[connection signal="pressed" from="ColorRect/CenterContainer/VBoxContainer/Button" to="ColorRect/CenterContainer/VBoxContainer/Button" method="Execute"]

View File

@ -0,0 +1,126 @@
using Godot;
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Web;
using BITKit;
using BITKit.Auth;
using BITKit.Net.Http;
using Cysharp.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using Environment = System.Environment;
using HttpClient = System.Net.Http.HttpClient;
namespace IDIS.License;
public class LicenseBin
{
public DateTime ExpirationDate=DateTime.Now;
public string Token;
}
public partial class LicenseService : EntityComponent,IAuthService
{
private static readonly HttpClient _httpClient = new();
[Export] private string _requestAuthorizeUrl;
[Export] private string _revokeAuthorizeUrl;
public bool IsAuthorized { get;private set; }
public bool IsAuthorizing { get;private set; }
public event Action<string> OnAuthorize;
public event Action<string> OnAuthorized;
public event Action<string> UnAuthorize;
public event Action<string> OnAuthorizeFailure;
private CancellationTokenSource _cancellationTokenSource;
private CancellationToken _cancellationToken=>_cancellationTokenSource.Token;
private IHttpListenerService _httpListenerService;
private readonly string path = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"iFactory",
"License.bin"
);
public override void BuildService(IServiceCollection serviceCollection)
{
serviceCollection.AddSingleton<IAuthService>(this);
}
public override void _EnterTree()
{
_cancellationTokenSource = new CancellationTokenSource();
}
public override void _ExitTree()
{
_cancellationTokenSource.Cancel();
}
public override void OnAwake()
{
_httpListenerService = Entity.ServiceProvider.GetRequiredService<IHttpListenerService>();
_httpListenerService.OnRequest += OnRequest;
}
public override void OnStart()
{
BIT4Log.Log<LicenseService>("准备文件中,二进制授权文件路径:"+path);
if (IsAuthorized || IsAuthorizing) return;
if (File.Exists(path) is false) return;
var json = File.ReadAllText(path);
var licenseBin = JsonConvert.DeserializeObject<LicenseBin>(json);
if(licenseBin.ExpirationDate<DateTime.Now) return;
AuthorizeAsync(licenseBin.Token).Forget();
}
private HttpContent OnRequest(HttpListenerRequest arg)
{
var token = arg.RawUrl!.Split('/').Last();
AuthorizeAsync(token).Forget();
return new StringContent("success");
}
public async UniTask AuthorizeAsync(string token)
{
var rawToken = token;
OnAuthorize?.Invoke(token);
token = JsonConvert.SerializeObject(token);
var response = await _httpClient.PostAsync(_requestAuthorizeUrl,new StringContent( token,Encoding.UTF8, "application/json"), _cancellationToken);
var message = await response.Content.ReadAsStringAsync(_cancellationToken);
if (response.IsSuccessStatusCode)
{
OnAuthorized?.Invoke(message);
BIT4Log.Log<IAuthService>($"授权成功:{message}");
var licenseBin = new LicenseBin
{
Token = rawToken,
ExpirationDate = DateTime.Now.AddDays(7)
};
PathHelper.EnsureDirectoryCreated(path);
await File.WriteAllTextAsync(path, JsonConvert.SerializeObject(licenseBin), _cancellationToken);
IsAuthorized = true;
}
else
{
OnAuthorizeFailure?.Invoke(message);
BIT4Log.Log<IAuthService>($"当前Token:{rawToken}");
BIT4Log.Log<IAuthService>($"授权失败:{message}");
}
}
public UniTask CancelAuthorizationAsync()
{
if (IsAuthorized is false)
{
throw new InvalidOperationException("未授权");
}
var url = _revokeAuthorizeUrl.Replace("{x}",_requestAuthorizeUrl);
UnAuthorize?.Invoke("取消授权");
IsAuthorized = false;
_httpClient.PostAsync(url, new StringContent(""), _cancellationToken).AsUniTask().Forget();
return UniTask.CompletedTask;
}
}

View File

@ -0,0 +1,16 @@
[gd_scene load_steps=4 format=3 uid="uid://c3mhpoxbs142w"]
[ext_resource type="Script" path="res://BITKit/Scripts/ECS/Core/Entity.cs" id="1_52733"]
[ext_resource type="Script" path="res://BITKit/Scripts/Net/HttpListener_GodotBased.cs" id="2_8gsq5"]
[ext_resource type="Script" path="res://Artists/Scripts/License/LicenseService.cs" id="3_pvdt4"]
[node name="LicenseService" type="Node"]
script = ExtResource("1_52733")
[node name="HttpListener" type="Node" parent="."]
script = ExtResource("2_8gsq5")
autoStart = true
port = 7001
[node name="LicenseService" type="Node" parent="."]
script = ExtResource("3_pvdt4")

File diff suppressed because one or more lines are too long

View File

@ -51,6 +51,7 @@ public partial class Entity : Node,IEntity
public override void _ExitTree()
{
_cancellationTokenSource.Cancel();
_entitiesService.UnRegister(this);
}
/// <summary>
@ -95,6 +96,8 @@ public partial class Entity : Node,IEntity
this._components = entityComponents.ToArray();
SetMeta("Components",Variant.From(_components.Select(x=>x.GetType().Name).ToArray()));
}
public bool TryGetComponent<T>(out T component)
{
if (TypeComponents.TryGetValue(typeof(T), out var iComponent) && iComponent is T _component)
@ -105,14 +108,6 @@ public partial class Entity : Node,IEntity
component = default;
return false;
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
_entitiesService.UnRegister(this);
}
}
public bool RegisterComponent<T>(T component)
{

View File

@ -0,0 +1,63 @@
using Godot;
using System;
using System.Net;
using System.Net.Http;
using BITKit.Net.Http;
using Microsoft.Extensions.DependencyInjection;
namespace BITKit.Net.Http;
public partial class HttpListener_GodotBased : EntityComponent,IHttpListenerService
{
[Export] private bool autoStart;
[Export]
private int port
{
get => _httpListenerServiceImplementation.Port;
set => _httpListenerServiceImplementation.Port = value;
}
private readonly IHttpListenerService _httpListenerServiceImplementation = new HttpListenerService();
public override void BuildService(IServiceCollection serviceCollection)
{
serviceCollection.AddSingleton<IHttpListenerService>(this);
}
public override void _Ready()
{
if (autoStart)
{
Start();
}
}
public override void _ExitTree()
{
if(IsListening)
{
Stop();
}
}
public bool IsListening => _httpListenerServiceImplementation.IsListening;
int IHttpListenerService.Port
{
get => _httpListenerServiceImplementation.Port;
set => _httpListenerServiceImplementation.Port = value;
}
event Func<HttpListenerRequest, HttpContent> IHttpListenerService.OnRequest
{
add => _httpListenerServiceImplementation.OnRequest += value;
remove => _httpListenerServiceImplementation.OnRequest -= value;
}
public void Start()
{
_httpListenerServiceImplementation.Start();
}
public void Stop()
{
_httpListenerServiceImplementation.Stop();
}
}

View File

@ -0,0 +1,25 @@
using Godot;
using System;
using BITKit;
using BITKit.Auth;
using Microsoft.Extensions.DependencyInjection;
namespace IDIS.Entities.License;
public partial class IDIS_License : EntityComponent
{
[Export] private PackedScene initialScene;
[Export] private Control licenseNode;
private IAuthService _authService;
public override void OnAwake()
{
_authService = Entity.ServiceProvider.GetRequiredService<IAuthService>();
_authService.OnAuthorized += OnAuthorized;
}
private async void OnAuthorized(string obj)
{
await BITApp.SwitchToMainThread();
GetParent().AddChild(initialScene.Instantiate());
licenseNode.QueueFree();
}
}

View File

@ -218,7 +218,6 @@ layout_mode = 2
[node name="Button5" type="Button" parent="Layout/UX TabView Service/Horizontal Layout/导航栏/MarginContainer/Layout"]
layout_mode = 2
theme_type_variation = &"SideTab"
toggle_mode = true
button_group = SubResource("ButtonGroup_qfatg")
text = "返回"
icon = ExtResource("9_78wam")

15
ReadMe/License.md Normal file
View File

@ -0,0 +1,15 @@
# 许可证服务
## 流程
启动app
app开启HttpListener监听端口{port}
app打开浏览器访问https://wechat.bitfall.icu/license
用户微信扫码登录
网页跳转http://localhost:{port}/token={code}
登录成功,服务器记录Token
客户端在每次启动时会验证Token的有效期,如果Token过期,则重新登录

View File

@ -12,7 +12,7 @@ config_version=5
config/name="iFactory"
config/description="智慧工厂的映射与交互"
run/main_scene="res://Mods/教育平台/教育平台主菜单.tscn"
run/main_scene="res://Artists/Scenes/InitialLicense.tscn"
config/features=PackedStringArray("4.1", "C#", "Forward Plus")
run/low_processor_mode=true
boot_splash/bg_color=Color(0.00392157, 0, 0.00392157, 1)
@ -21,10 +21,10 @@ config/version="1.03"
[autoload]
EntitiesManager="res://Artists/Services/entities_manager.tscn"
BITApp="res://Artists/Services/BITApp.tscn"
UXMetaService="res://Artists/Services/UXMetaService.tscn"
UXService="res://Artists/Services/UXService.tscn"
EntitiesManager="*res://Artists/Services/entities_manager.tscn"
BITApp="*res://Artists/Services/BITApp.tscn"
UXMetaService="*res://Artists/Services/UXMetaService.tscn"
UXService="*res://Artists/Services/UXService.tscn"
[display]