添加了授权
This commit is contained in:
parent
c59d513cca
commit
c65fe87a6c
|
@ -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"]
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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")
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
# 许可证服务
|
||||
## 流程
|
||||
启动app
|
||||
|
||||
app开启HttpListener监听端口{port}
|
||||
|
||||
app打开浏览器,访问https://wechat.bitfall.icu/license
|
||||
|
||||
用户微信扫码登录
|
||||
|
||||
网页跳转http://localhost:{port}/token={code}
|
||||
|
||||
登录成功,服务器记录Token
|
||||
|
||||
客户端在每次启动时会验证Token的有效期,如果Token过期,则重新登录
|
|
@ -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]
|
||||
|
||||
|
|
Loading…
Reference in New Issue