CrazyIter_Bin 5 months ago
parent
commit
f8d1281723

+ 2 - 1
IES.ExamServer/App.xaml.cs

@@ -1,5 +1,6 @@
 using IES.ExamServer.DI;
 using IES.ExamServer.DI.SignalRHost;
+using IES.ExamServer.Helper;
 using Microsoft.AspNetCore.Builder;
 using Microsoft.AspNetCore.Hosting;
 using Microsoft.AspNetCore.StaticFiles;
@@ -111,7 +112,7 @@ namespace IES.ExamServer
                     string content = await message.Content.ReadAsStringAsync();
                     data = JsonSerializer.Deserialize<JsonNode>(content);
                     data!["centerUrl"]=CenterUrl;
-                    cache.Set("Server:Center:Data", data);
+                    cache.Set(Constant._KeyServerCenter, data);
                     SystemInfo? system= JsonSerializer.Deserialize<SystemInfo>(data);
                     system!.id= $"{DateTimeOffset.Now.ToUnixTimeMilliseconds()}";
                     liteDBFactory.GetLiteDatabase().GetCollection<SystemInfo>("System").Insert(system);

BIN
IES.ExamServer/Configs/logo.png


+ 100 - 30
IES.ExamServer/Controllers/HomeController.cs

@@ -12,30 +12,37 @@ using System.Text.Json.Nodes;
  
 using System.DrawingCore;
 using System.DrawingCore.Imaging;
+using System.DirectoryServices.ActiveDirectory;
+using ZXing.QrCode.Internal;
+using System.Text.Json;
+using ZXing.Aztec.Internal;
+using System.IdentityModel.Tokens.Jwt;
+using IES.ExamServer.Models;
+using System.Net.Http.Json;
 
 namespace IES.ExamServer.Controllers
 {
     [Route("core")]
     [ApiController]
-    public class HomeController:ControllerBase
+    public class HomeController : ControllerBase
     {
         private readonly IConfiguration _configuration;
         private readonly IHttpClientFactory _httpClientFactory;
         private readonly IMemoryCache _memoryCache;
-        public HomeController(IConfiguration configuration,IHttpClientFactory httpClientFactory, IMemoryCache memoryCache) 
+        public HomeController(IConfiguration configuration, IHttpClientFactory httpClientFactory, IMemoryCache memoryCache)
         {
             _configuration=configuration;
             _httpClientFactory=httpClientFactory;
             _memoryCache=memoryCache;
         }
         [HttpGet("/init")]
-        public async Task<IActionResult> Init() 
+        public async Task<IActionResult> Init()
         {
-            int code =0;
+            int code = 0;
             string msg = string.Empty;
             try {
 
-                _memoryCache.TryGetValue("Server:Center:Data", out JsonNode? data);
+                _memoryCache.TryGetValue(Constant._KeyServerCenter, out JsonNode? data);
                 if (data!=null)
                 {
                     return Ok(new { code = 200, msg = "云端服务连接成功!", data = data });
@@ -44,44 +51,107 @@ namespace IES.ExamServer.Controllers
                     code=500;
                     msg="云端服务未连接!";
                 }
-               
-               
-            } catch (Exception ex) 
+
+
+            } catch (Exception ex)
             {
                 code=500;
                 msg="云端服务未连接!";
             }
-            return Ok(new { code,msg} );
+            return Ok(new { code, msg });
         }
-        [HttpGet("/mobile-login")]
-        public async Task<IActionResult> MobileLogin() 
+
+
+        /**
         {
-            return Ok();
+            "type":"sms",//qrcode二维码扫码登录:randomCode必传;  sms 短信验证登录:randomCode必传,mobile必传
+            "randomCode",
+            "mobile":"1528377****"
         }
-        [HttpGet("/qrcode-login")]
-        public async Task<IActionResult> QRcodeLogin()
+        **/
+        /// <summary>
+        /// 登录验证
+        /// </summary>
+        /// <param name="randomCode"></param>
+        /// <returns></returns>
+        [HttpPost("/login-check")]
+        public async Task<IActionResult> LoginCheck(JsonNode json)
         {
+            string randomCode = $"{json["randomCode"]}";
+            System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;
+            string? CenterUrl = _configuration.GetValue<string>("ExamServer:CenterUrl");
+            var response = await _httpClientFactory.CreateClient().GetAsync($"{CenterUrl}/hita/check-login?code={randomCode}");
+            if (response.IsSuccessStatusCode)
+            {
+                string content = await response.Content.ReadAsStringAsync();
+                if (!string.IsNullOrWhiteSpace(content)) 
+                {
+                    var json = JsonSerializer.Deserialize<JsonNode>(content);
+                    if (json != null) 
+                    {
+                      
+                        TmdidImplicit? token = JsonSerializer.Deserialize<TmdidImplicit>(json["implicit_token"]);
+                        string x_auth_token = $"{json["x_auth_token"]}";
+                        List<School>? schools = JsonSerializer.Deserialize<List<School>>(json["schools"]);
+                        var jwt = new JwtSecurityToken(token?.id_token);
+                        var id = jwt.Payload.Sub;
+                        jwt.Payload.TryGetValue("name", out object? name);
+                        jwt.Payload.TryGetValue("picture", out object? picture);
+                    }
+                }
+            }
             return Ok();
         }
-        [HttpGet("/qrcode-gen")]
-        public async Task<IActionResult> QRcodeGen()
+        /// <summary>
+        /// 登录模式初始化
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet("/login-init")]
+        public async Task<IActionResult> LoginInit(JsonNode json)
         {
-            // 生成二维码图片
-            Random random = new Random();
-            int  code = random.Next(1000, 9999);
-            string? CenterUrl = _configuration.GetValue<string>("ExamServer:CenterUrl");
-            string content = $"{CenterUrl}/joinSchool?schoolName=&schoolCode=login:{code}&m=%E6%89%AB%E7%A0%81%E7%99%BB%E5%BD%95&o=1";
-            Bitmap qrCodeImage =QRCodeHelper. GetBitmap(content, 200, 200);
+            var type = json["type"];
             string qrcode = string.Empty;
-            using (MemoryStream stream = new MemoryStream())
+            string randomCode = "";
+            switch (true) 
             {
-                qrCodeImage.Save(stream, ImageFormat.Png);
-                byte[] data = stream.ToArray();
-                qrcode= Convert.ToBase64String(data);
+                case bool when $"{type}".Equals("qrcode"):
+                    { 
+                        // 生成二维码图片
+                        Random random = new Random();
+                        randomCode = $"{random.Next(1000, 9999)}";
+                        string? CenterUrl = _configuration.GetValue<string>("ExamServer:CenterUrl");
+                        string content = $"{CenterUrl}/joinSchool?schoolCode=login:{randomCode}&m=%E7%99%BB%E5%BD%95&o=1";
+                        Bitmap qrCodeImage = QRCodeHelper.GetBitmap(content, 200, 200);
+                        using (MemoryStream stream = new MemoryStream())
+                        {
+                            qrCodeImage.Save(stream, ImageFormat.Png);
+                            byte[] data = stream.ToArray();
+                            qrcode=$"data:image/png;base64,{Convert.ToBase64String(data)}";
+                        }
+                        return Ok(new { code = 200, randomCode = randomCode, qrcode, type });
+                    }
+                case bool when $"{type}".Equals("smspin"):
+                    {
+                        int send = 0;
+                        if (  !string.IsNullOrWhiteSpace($"{json["area"]}") &&  !string.IsNullOrWhiteSpace($"{json["to"]}"))
+                        {
+                            string? CenterUrl = _configuration.GetValue<string>("ExamServer:CenterUrl");
+                            string url = $"{CenterUrl}/core/sendsms/pin";
+                            HttpResponseMessage message= await _httpClientFactory.CreateClient().PostAsJsonAsync(url, new { });
+                            if (message.IsSuccessStatusCode) 
+                            {
+                                string content =await message.Content.ReadAsStringAsync();
+                                JsonNode? jsonNode = JsonSerializer.Deserialize<JsonNode>(content);
+                                if (jsonNode!=null && int.TryParse($"{jsonNode["send"]}", out int s)) 
+                                {
+                                    send = s;
+                                }
+                            }
+                        }
+                        return Ok(new { code = 200, send, type });
+                    }
             }
-            return Ok(new {code=200, randomCode = code,qrcode});
+            return Ok(new { code = 400});
         }
-        [HttpGet("/hello")]
-        public string Get() => "Hello World";
     }
-}
+}

+ 13 - 0
IES.ExamServer/Helper/Constant.cs

@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace IES.ExamServer.Helper
+{
+    public static class Constant
+    {
+        public static string _KeyServerCenter = "Server:Center:Data";
+    }
+}

File diff suppressed because it is too large
+ 38 - 13
IES.ExamServer/Helper/QRCodeHelper.cs


+ 4 - 0
IES.ExamServer/IES.ExamServer.csproj

@@ -26,6 +26,7 @@
     <PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.1" />
     <PackageReference Include="Microsoft.Web.WebView2" Version="1.0.2903.40" />
     <PackageReference Include="System.Drawing.Common" Version="8.0.6" />
+    <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.1.2" />
     <PackageReference Include="ZXing.Net" Version="0.16.9" />
     <PackageReference Include="ZXing.Net.Bindings.ZKWeb.System.Drawing" Version="0.16.7" />
   </ItemGroup>
@@ -42,5 +43,8 @@
     <None Update="appsettings.json">
       <CopyToOutputDirectory>Always</CopyToOutputDirectory>
     </None>
+    <None Update="Configs\logo.png">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </None>
   </ItemGroup>
 </Project>

+ 33 - 0
IES.ExamServer/Models/Teacher.cs

@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace IES.ExamServer.Models
+{
+    public class Teacher
+    {
+        public string? id {  get; set; }
+        public string? name { get; set; }
+        public string? picture {  get; set; }
+        public string? x_auth_token {  get; set; }
+        public string? access_token { get; set; }
+        public List<School> schools { get; set; }= new List<School>();
+    }
+
+    public class School
+    {
+        public string? id { get; set; }
+        public string? name { get; set; }
+        public string? picture { get; set; }
+    }
+    [Serializable]
+    public class TmdidImplicit
+    {
+        public string? id_token { get; set; }
+        public string? access_token { get; set; }
+        public string? expires_in { get; set; }
+        public string? token_type { get; set; }
+    }
+}

+ 62 - 0
TEAMModelOS.SDK/DI/CoreAPI/CoreAPIHttpService.cs

@@ -682,6 +682,68 @@ lang 语系"zh-cn" ,zh-tw", "en-us"
             public string eventName { get; set; }
             public string data { get; set; }
         }
+
+        public async Task<(HttpStatusCode code, string content)> Auth2Login(string pin_code,string account, string location, IConfiguration _configuration, DI.DingDing _dingDing)
+        {
+            try
+            {
+                var url = _configuration.GetValue<string>("HaBookAuth:CoreAPI");
+                //url = "https://api2-rc.teammodel.cn";
+                url = $"{url}/oauth2/login";
+                var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
+                var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
+                if (location.Contains("China"))
+                {
+                    location = "China";
+                }
+                else if (location.Contains("Global"))
+                {
+                    location = "Global";
+                }
+                var client = _httpClient;
+                var token = await CoreTokenExtensions.CreateAccessToken(clientID, clientSecret, location);
+                if (client.DefaultRequestHeaders.Contains("Authorization"))
+                {
+                    client.DefaultRequestHeaders.Remove("Authorization");
+
+                }
+                client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token.AccessToken}");
+                var data = new Dictionary<string, string> 
+                {
+                    { "pin_code", pin_code },
+                    { "account", account },
+                    { "grant_type", "create" },
+                    { "client_id", clientID },
+                    { "nonce", "habook" },
+                    { "name", "User" },
+                };
+
+                HttpResponseMessage responseMessage = await client.PostAsJsonAsync(url, data);
+                if (responseMessage.Content != null)
+                {
+                    string content = await responseMessage.Content.ReadAsStringAsync();
+                    if (!string.IsNullOrWhiteSpace(content))
+                    {
+                        return (responseMessage.StatusCode, content);
+                    }
+                    else
+                    {
+                        return (responseMessage.StatusCode, null);
+                    }
+                }
+                else
+                {
+                    return (responseMessage.StatusCode, null);
+                }
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"{location}短信登录验证异常:\n{ex.Message}\n{ex.StackTrace}", DI.GroupNames.醍摩豆服務運維群組);
+                return (HttpStatusCode.InternalServerError, null);
+            }
+
+        }
+
         /// <summary>
         ///  发送短信验证码
         /// </summary>

+ 16 - 8
TEAMModelOS/Controllers/Client/HiTAControlller.cs

@@ -306,24 +306,32 @@ namespace TEAMModelOS.Controllers.Client
             {
                 timezone=tz;
             }
-            var data = await _azureRedis.GetRedisClient(8).StringGetAsync($"HiTA:Login:{join.code}");
-            if (data.HasValue)
+            string tmdid=string.Empty;
+            if (!string.IsNullOrWhiteSpace(join.code)) 
+            {
+                var data = await _azureRedis.GetRedisClient(8).StringGetAsync($"HiTA:Login:{join.code}");
+                if (data.HasValue)
+                {
+                    tmdid= data.ToString();
+                }
+            }
+
+            if (!string.IsNullOrWhiteSpace(tmdid))
             {
-                var id = data.ToString();
                 var location = _option.Location;
                 var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
                 TmdidImplicit implicit_token = await _coreAPIHttpService.Implicit(new Dictionary<string, string>()
                         {
                         { "grant_type", "implicit" },
                         { "client_id",clientID },
-                        { "account",id },
+                        { "account",tmdid },
                         { "nonce",Guid.NewGuid().ToString()}
                         }, location, _configuration);
                 IEnumerable<dynamic> schools= new List<dynamic>();
-                var response =  await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemStreamAsync(id, new PartitionKey("Base"));
+                var response =  await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemStreamAsync(tmdid, new PartitionKey("Base"));
                 if (response.StatusCode==System.Net.HttpStatusCode.OK) { 
                     Teacher teacher= JsonDocument.Parse(response.Content).RootElement.ToObject<Teacher>();
-                    schools= teacher.schools.Where(x=>x.status.Equals("join")).Select(x => new { id = x.schoolId, name = x.name });
+                    schools= teacher.schools.Where(x=>x.status.Equals("join")).Select(x => new { id = x.schoolId, name = x.name, picture=x.picture });
                 }
                 object name = null, picture = null;
                 var jwt = new JwtSecurityToken(implicit_token.id_token);
@@ -336,9 +344,9 @@ namespace TEAMModelOS.Controllers.Client
                 if (teacherInfo!=null) {
                     x_auth_token= teacherInfo.auth_token;
                 }
-                return Ok(new { implicit_token ,schools, x_auth_token });
+                return Ok(new { code = 200, implicit_token ,schools, x_auth_token });
             }
-            return Ok();
+            return Ok(new { code =400});
         }
         /// <summary>
         /// 扫码加入学校 //已被school-join 替代

File diff suppressed because it is too large
+ 93 - 2
TEAMModelOS/Controllers/System/CoreController.cs