Browse Source

SignalR Updateing

leiy 1 year ago
parent
commit
79a5015171

+ 28 - 4
OASystem/OASystem.Api/Controllers/AuthController.cs

@@ -14,8 +14,9 @@ using OASystem.Domain.Dtos.QiYeWeChat;
 using OASystem.Domain.Entities.System;
 using TinyPinyin;
 using System.Globalization;
-using OASystem.API.OAMethodLib.Hubs;
 using Microsoft.AspNetCore.SignalR;
+using OASystem.API.OAMethodLib.Hub.Hubs;
+using OASystem.API.OAMethodLib.Hub.HubClients;
 
 namespace OASystem.API.Controllers
 {
@@ -33,10 +34,10 @@ namespace OASystem.API.Controllers
         private readonly MessageRepository _messageRep;
         
         private readonly IQiYeWeChatApiService _qiYeWeChatApiServic;
-        private readonly IHubContext<ServerHub> _hubContext;
+      
 
         public AuthController(IConfiguration config, LoginRepository loginRep, IMapper mapper,MessageRepository message,
-            SystemMenuPermissionRepository systemMenuPermissionRepository, IQiYeWeChatApiService qiYeWeChatApiService, IHubContext<ServerHub> hubContext, MessageRepository messageRep)
+            SystemMenuPermissionRepository systemMenuPermissionRepository, IQiYeWeChatApiService qiYeWeChatApiService, MessageRepository messageRep)
         {
             _config = config;
             _loginRep = loginRep;
@@ -45,7 +46,7 @@ namespace OASystem.API.Controllers
             _SystemMenuPermissionRepository = systemMenuPermissionRepository;
             _qiYeWeChatApiServic = qiYeWeChatApiService;
             _messageRep = messageRep;
-            _hubContext = hubContext;
+            
         }
 
         /// <summary>
@@ -116,6 +117,13 @@ namespace OASystem.API.Controllers
 
             }
 
+
+            #region 添加登录用户上线信息
+
+
+
+            #endregion
+
             #region 测试添加系统消息
 
             //await _message.AddMsg(new MessageDto()
@@ -726,5 +734,21 @@ namespace OASystem.API.Controllers
             }
             
         }
+
+
+        /// <summary>
+        /// 测试 
+        /// 发送消息
+        /// </summary>
+        /// <param name="date"></param>
+        /// <param name="hubContext"></param>
+        /// <returns></returns>
+        [HttpPost("SendMessage")]
+        public async Task SendMessage(string date, [FromServices] IHubContext<ChatHub, IChatClient> hubContext)
+        {
+
+            await hubContext.Clients.All.SendAll(date);
+
+        }
     }
 }

+ 59 - 0
OASystem/OASystem.Api/OAMethodLib/Auth/JWTBearer.cs

@@ -0,0 +1,59 @@
+using System.IdentityModel.Tokens.Jwt;
+using System.Security.Claims;
+
+namespace OASystem.API.OAMethodLib.Auth
+{
+    /// <summary>
+    /// jwt
+    /// </summary>
+    public static class JWTBearer
+    {
+        public static readonly SymmetricSecurityKey SecurityKey = new SymmetricSecurityKey(Guid.NewGuid().ToByteArray());
+        public static readonly JwtSecurityTokenHandler JwtTokenHandler = new JwtSecurityTokenHandler();
+        public static string GenerateToken(HttpContext httpContext)
+        {
+            // 请求时传入的用户参数为NameIdentifier claim的值
+            var claims = new[] { 
+                new Claim(ClaimTypes.NameIdentifier, httpContext.Request.Query["user"]) 
+            
+            };
+            // 签名凭据
+            var credentials = new SigningCredentials(SecurityKey, SecurityAlgorithms.HmacSha256);
+            // 生成JWT Token
+            var token = new JwtSecurityToken("FMGJ-OA", "OA-Users", claims, expires: DateTime.UtcNow.AddSeconds(60), signingCredentials: credentials);
+            return JwtTokenHandler.WriteToken(token);
+        }
+        public static void AddMyJWTBearerAuth(this IServiceCollection services)
+        {
+            // 添加自定义授权
+            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
+                .AddJwtBearer(options =>
+                {
+                    options.TokenValidationParameters =
+                    new TokenValidationParameters
+                    {
+                        LifetimeValidator = (before, expires, token, parameters) => expires > DateTime.UtcNow,
+                        ValidateAudience = false,
+                        ValidateIssuer = false,
+                        ValidateActor = false,
+                        ValidateLifetime = true,
+                        IssuerSigningKey = JWTBearer.SecurityKey
+                    };
+                    options.Events = new JwtBearerEvents
+                    {
+                        OnMessageReceived = context =>
+                        {
+                            // 当我们收到消息时,去获取请求中的access_token字段
+                            var accessToken = context.Request.Query["access_token"];
+                            // 如果没有就去头上找,找到了就放入我们context.token中
+                            if (!string.IsNullOrEmpty(accessToken))
+                            {
+                                context.Token = accessToken;
+                            }
+                            return Task.CompletedTask;
+                        }
+                    };
+                });
+        }
+    }
+}

+ 1 - 1
OASystem/OASystem.Api/OAMethodLib/GeneralMethod.cs

@@ -93,7 +93,7 @@ namespace OASystem.API.OAMethodLib
         /// <param name="Number"></param>
         /// <param name="exp"></param>
         /// <returns></returns>
-        public static async Task< string> GetToken(IConfiguration _config, string Number, int uId, string uName, DateTime exp)
+        public static async Task<string> GetToken(IConfiguration _config, string Number, int uId, string uName, DateTime exp)
         {
             string userId = Guid.NewGuid().ToString().Replace("-", "");
             var claims = new[] {

+ 0 - 122
OASystem/OASystem.Api/OAMethodLib/Hubs/ServerHub.cs

@@ -1,122 +0,0 @@
-using Microsoft.AspNetCore.Cors;
-using Microsoft.AspNetCore.SignalR;
-using OASystem.Domain;
-using QuartzUI.Extension.AspNetCore.Enum;
-using SqlSugar;
-using System;
-using System.ComponentModel.DataAnnotations;
-using System.IdentityModel.Tokens.Jwt;
-using static OASystem.API.OAMethodLib.JWTHelper;
-
-namespace OASystem.API.OAMethodLib.Hubs
-{
-    /// <summary>
-    /// 站内通信 Hub
-    /// </summary>
-    public class ServerHub : Hub
-    {
-
-        /// <summary>
-        /// 已连接的用户信息
-        /// </summary>
-        public static List<UserModel> OnlineUser { get; set; } = new List<UserModel>();
-
-        private readonly ILogger<ServerHub> _logger;
-        private readonly IHttpContextAccessor _accessor;
-
-        public ServerHub( ILogger<ServerHub> logger, IHttpContextAccessor accessor)
-        {
-            _logger = logger;
-            _accessor = accessor;
-        }
-
-        /// <summary>
-        /// 当连接成功时执行
-        /// </summary>
-        /// <returns></returns>
-        public override Task OnConnectedAsync()
-        {
-            string connId = Context.ConnectionId;
-
-            _logger.LogWarning("SignalR已连接");
-            //验证Token
-            var token = _accessor.HttpContext.Request.Query["access_token"];
-            var user = JwtHelper.SerializeJwt(token);
-            _logger.LogWarning("SignalR已连接,用户名:" + user.UserName);
-            //连接用户 这里可以存在Redis
-            var model = new UserModel
-            {
-                UserId = user.Uid,
-                ConnectionId = connId,
-                Token = token,
-                UserName = user.UserName
-            };
-            OnlineUser.Add(model);
-            //给当前的连接分组 可以进行同一组接收消息 也可以用Token获取机构权限
-            //await Groups.AddToGroupAsync(Context.ConnectionId, "测试组");
-
-            //给当前连接返回消息 .Clients可以发多个连接ID
-            Clients.Client(connId).SendAsync("ConnectResponse",
-                new Result()
-                {
-                    Code = 200,
-                    Data = model,
-                    Msg = user.UserName + "连接成功"
-                });
-
-            return base.OnConnectedAsync();
-        }
-
-        /// <summary>
-        /// 当连接断开时的处理
-        /// </summary>
-        public override Task OnDisconnectedAsync(Exception exception)
-        {
-            string connId = Context.ConnectionId;
-            var model = OnlineUser.Find(u => u.ConnectionId == connId);
-            int count = OnlineUser.RemoveAll(u => u.ConnectionId == connId);
-            if (model != null)
-            {
-                //给当前分组发送消息 在一个分组就能接收到消息
-                //Clients.Group(model.GroupName).SendAsync("GetUsersResponse", result);
-
-                //给当前连接返回消息 .Clients可以发多个连接ID
-                Clients.Client(connId).SendAsync("DisconnectResponse",
-                new Result()
-                {
-                    Code  = 400,
-                    Data = "true",
-                    Msg = "断开连接"
-                });
-            }
-            return base.OnDisconnectedAsync(exception);
-        }
-
-        public async Task Send(string name, string message)
-        {
-            // Call the broadcastMessage method to update clients.
-            await Clients.All.SendAsync("broadcastMessage", name, message);
-        }
-
-        /// <summary>
-        /// 接受用户的数进行推送
-        /// </summary>
-        /// <returns></returns>
-        public async Task SendMessage(string user, string msg)
-        {
-            Result  result = new Result();
-            result.Data = new UserModel
-            {
-                ConnectionId = Context.ConnectionId,
-                Token = "",
-                UserName = user
-            };
-            result.Code = 200;
-            result.Msg = msg;
-
-            //推送给所有连接ID的第一条数据
-            await Clients.Clients(OnlineUser.Select(q => q.ConnectionId).ToList()).SendAsync("SendMessage", result);
-        }
-    }
-}
-

+ 0 - 13
OASystem/OASystem.Api/OAMethodLib/Hubs/UserModel.cs

@@ -1,13 +0,0 @@
-namespace OASystem.API.OAMethodLib.Hubs
-{
-    public class UserModel
-    {
-        public long UserId { get; set; }
-
-        public string ConnectionId { get; set; }
-
-        public string Token { get; set; }
-
-        public string UserName { get; set; }
-    }
-}

+ 0 - 1
OASystem/OASystem.Api/OAMethodLib/Quartz/Business/TaskAssignment.cs

@@ -1,5 +1,4 @@
 using Microsoft.AspNetCore.SignalR;
-using OASystem.API.OAMethodLib.Hubs;
 using OASystem.Domain.Entities.Groups;
 using OASystem.Domain.Entities.PersonnelModule;
 using OASystem.Infrastructure.Repositories.PersonnelModule;

+ 0 - 1
OASystem/OASystem.Api/OAMethodLib/Quartz/Business/TaskNewsFeedJob.cs

@@ -1,5 +1,4 @@
 using Microsoft.AspNetCore.SignalR;
-using OASystem.API.OAMethodLib.Hubs;
 using OASystem.Domain.Entities.PersonnelModule;
 using OASystem.Infrastructure.Repositories.PersonnelModule;
 using ILogger = Microsoft.Extensions.Logging.ILogger;

+ 5 - 11
OASystem/OASystem.Api/OAMethodLib/Quartz/Jobs/TaskNewsFeedJob.cs

@@ -1,5 +1,5 @@
 using Microsoft.AspNetCore.SignalR;
-using OASystem.API.OAMethodLib.Hubs;
+using OASystem.API.OAMethodLib.Hub.Hubs;
 using OASystem.API.OAMethodLib.Quartz.Business;
 using OASystem.Infrastructure.Repositories.PersonnelModule;
 using Quartz;
@@ -14,13 +14,11 @@ namespace OASystem.API.OAMethodLib.Quartz.Jobs
     {
         private readonly ILogger<TaskNewsFeedJob> _logger;
         private readonly TaskAllocationRepository _taskAllocationRep = AutofacIocManager.Instance.GetService<TaskAllocationRepository>();
-        private readonly IHubContext<ServerHub> _hubContext;
 
-        public TaskNewsFeedJob(ILogger<TaskNewsFeedJob> logger, TaskAllocationRepository taskAllocationRep, IHubContext<ServerHub> hubContext)
+        public TaskNewsFeedJob(ILogger<TaskNewsFeedJob> logger, TaskAllocationRepository taskAllocationRep)
         {
             _logger = logger;
             _taskAllocationRep = taskAllocationRep;
-            _hubContext = hubContext;
         }
 
         /// <summary>
@@ -144,8 +142,7 @@ namespace OASystem.API.OAMethodLib.Quartz.Jobs
             #endregion
 
             string msg = string.Empty;
-            if (ServerHub.OnlineUser.Count  > 0)
-            {
+            
                 //查询需要提示的消息 Singlr
                 string sql = string.Format(@"Select smra.Id,su.CnName As Issuer,sm.ReleaseTime,sm.Title,
 										 sm.Content,smra.ReadableUId,smra.IsRead,smra.CreateTime
@@ -159,11 +156,8 @@ namespace OASystem.API.OAMethodLib.Quartz.Jobs
 
                 //_hubContext.Clients.All.SendAsync("ReceiveMessage", "系统通知", $"最新消息{DateTime.Now}");
                 //推送给所有连接ID的第一条数据
-            }
-
-            _logger.LogInformation("调用任务消息推送 " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "【在线人数】:" + JsonConvert.SerializeObject(ServerHub.OnlineUser) +"【推送消息】:"+ msg);
-
-            await _hubContext.Clients.Clients(ServerHub.OnlineUser.Select(q => q.ConnectionId).ToList()).SendAsync("SendMessageResponse", $"最新消息{DateTime.Now}");
+           
+            //await _hubContext.Clients.Clients(ServerHub.OnlineUser.Select(q => q.ConnectionId).ToList()).SendAsync("SendMessageResponse", $"最新消息{DateTime.Now}");
             //return Task.CompletedTask;
         }
     }

+ 7 - 0
OASystem/OASystem.Api/OAMethodLib/SignalR/HubClients/IChatClient.cs

@@ -0,0 +1,7 @@
+namespace OASystem.API.OAMethodLib.Hub.HubClients
+{
+    public interface IChatClient
+    {
+        Task SendAll(object message);
+    }
+}

+ 10 - 0
OASystem/OASystem.Api/OAMethodLib/SignalR/HubService/CommonService.cs

@@ -0,0 +1,10 @@
+namespace OASystem.API.OAMethodLib.SignalR.HubService
+{
+    public class CommonService
+    {
+        internal object SendAll(string data)
+        {
+            return $"Hello {new Random().Next(0, 100)} {data} ";
+        }
+    }
+}

+ 51 - 0
OASystem/OASystem.Api/OAMethodLib/SignalR/Hubs/ChatHub.cs

@@ -0,0 +1,51 @@
+using Microsoft.AspNetCore.SignalR;
+using OASystem.API.OAMethodLib.Hub.HubClients;
+using OASystem.API.OAMethodLib.SignalR.HubService;
+
+namespace OASystem.API.OAMethodLib.Hub.Hubs
+{
+    [Authorize]
+    public class ChatHub : Hub<IChatClient>
+    {
+        ILogger<ChatHub> _logger;
+        public ChatHub(ILogger<ChatHub> logger, CommonService common)
+        {
+            _logger = logger;
+            _common = common;
+        }
+        readonly CommonService _common;
+        /// <summary>
+        /// 客户端连接服务端
+        /// </summary>
+        /// <returns></returns>
+        public override Task OnConnectedAsync()
+        {
+            var id = Context.ConnectionId;
+            _logger.LogInformation($"Client ConnectionId=> [[{id}]] Already Connection Server!");
+            return base.OnConnectedAsync();
+        }
+        /// <summary>
+        /// 客户端断开连接
+        /// </summary>
+        /// <param name="exception"></param>
+        /// <returns></returns>
+        public override Task OnDisconnectedAsync(Exception exception)
+        {
+            var id = Context.ConnectionId;
+            _logger.LogInformation($"Client ConnectionId=> [[{id}]] Already Close Connection Server!");
+            return base.OnDisconnectedAsync(exception);
+        }
+        /**
+         * 测试 
+         * */
+        /// <summary>
+        /// 给所有客户端发送消息
+        /// </summary>
+        /// <returns></returns>
+        public async Task SendMessage(string data)
+        {
+            Console.WriteLine("Have one Data!");
+            await Clients.All.SendAll(_common.SendAll(data));
+        }
+    }
+}

+ 4 - 0
OASystem/OASystem.Api/OASystem.API.csproj

@@ -55,6 +55,10 @@
     </Reference>
   </ItemGroup>
 
+  <ItemGroup>
+    <Folder Include="OAMethodLib\新文件夹\" />
+  </ItemGroup>
+
   <ProjectExtensions><VisualStudio><UserProperties properties_4launchsettings_1json__JsonSchema="" /></VisualStudio></ProjectExtensions>
 
 </Project>

+ 51 - 26
OASystem/OASystem.Api/Program.cs

@@ -18,8 +18,12 @@ using OASystem.API.OAMethodLib.QiYeWeChatAPI;
 using OASystem.API.OAMethodLib.Quartz.Jobs;
 using Microsoft.AspNetCore.Cors.Infrastructure;
 using Microsoft.AspNetCore.SignalR;
-using OASystem.API.OAMethodLib.Hubs;
 using SqlSugar.DistributedSystem.Snowflake;
+using Microsoft.AspNetCore.Http.Connections;
+using OASystem.API.OAMethodLib.Hub.Hubs;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using OASystem.API.OAMethodLib.SignalR.HubService;
+using OASystem.API.OAMethodLib.Auth;
 
 var builder = WebApplication.CreateBuilder(args);
 var basePath = AppContext.BaseDirectory;
@@ -49,14 +53,23 @@ builder.Services.AddControllers()
         //options.JsonSerializerOptions.Converters.Add(new JsonConverterDecimal(0.0000M));
     });
 
+// 添加授权服务
+builder.Services.AddMyJWTBearerAuth();
+
 #region Cors
 builder.Services.AddCors(policy =>
 {
+    //policy.AddPolicy("Cors", opt => opt
+    //.AllowAnyOrigin()
+    //.AllowAnyHeader()
+    //.AllowAnyMethod()
+    //.WithExposedHeaders("X-Pagination"));
+
     policy.AddPolicy("Cors", opt => opt
-    .AllowAnyOrigin()
-    .AllowAnyHeader()
-    .AllowAnyMethod()
-    .WithExposedHeaders("X-Pagination"));
+          .SetIsOriginAllowed(origin => true)//这个必须加
+          .AllowAnyHeader()
+          .WithMethods("GET", "POST", "HEAD", "PUT", "DELETE", "OPTIONS")
+          .AllowCredentials());//这个一定不能少);
 
 });
 #endregion
@@ -199,22 +212,22 @@ if (AppSettingsHelper.Get("UseSwagger").ToBool())
 #region 添加校验
 
 //builder.Services.AddTransient<OASystemAuthentication>();
-builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
-    .AddJwtBearer(options =>
-        {
-            options.TokenValidationParameters = new TokenValidationParameters
-            {
-                ValidateIssuer = true,
-                ValidateAudience = true,
-                ValidateLifetime = true,
-                ValidateIssuerSigningKey = true,
-                ValidAudience = "OASystem.com",
-                ValidIssuer = "OASystem.com",
-                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["JwtSecurityKey"])),
-                ClockSkew = TimeSpan.FromSeconds(30), //过期时间容错值,解决服务器端时间不同步问题(秒)
-                RequireExpirationTime = true,
-            };
-        });
+//builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
+//    .AddJwtBearer(options =>
+//        {
+//            options.TokenValidationParameters = new TokenValidationParameters
+//            {
+//                ValidateIssuer = true,
+//                ValidateAudience = true,
+//                ValidateLifetime = true,
+//                ValidateIssuerSigningKey = true,
+//                ValidAudience = "OASystem.com",
+//                ValidIssuer = "OASystem.com",
+//                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["JwtSecurityKey"])),
+//                ClockSkew = TimeSpan.FromSeconds(30), //过期时间容错值,解决服务器端时间不同步问题(秒)
+//                RequireExpirationTime = true,
+//            };
+//        });
 #endregion
 
 #region 初始化日志
@@ -284,7 +297,12 @@ builder.Services.AddSingleton<IJobFactory, IOCJobFactory>();
 
 
 #region SignalR
-builder.Services.AddSignalR();
+builder.Services.AddSignalR()
+                .AddJsonProtocol(options =>
+                {
+                    options.PayloadSerializerOptions.PropertyNamingPolicy = null;
+                });
+builder.Services.TryAddSingleton(typeof(CommonService));
 #endregion
 
 var app = builder.Build();
@@ -298,9 +316,13 @@ if (!app.Environment.IsDevelopment())
 app.UseStaticFiles();
 
 app.UseRouting();
+app.UseCors("Cors");  //Cors
+
 app.UseAuthentication(); // 认证
 app.UseAuthorization();  // 授权
-app.UseCors("Cors");  //Cors
+
+// 授权路径
+app.MapGet("generatetoken", c => c.Response.WriteAsync(JWTBearer.GenerateToken(c)));
 
 #region 启用swaggerUI
 if (AppSettingsHelper.Get("UseSwagger").ToBool())
@@ -339,11 +361,14 @@ app.Lifetime.ApplicationStopped.Register(() =>
 
 
 #region SignalR
-app.UseEndpoints(endpoints =>
+
+app.MapHub<ChatHub>("/ChatHub", options =>
 {
-    endpoints.MapControllers();
-    endpoints.MapHub<ServerHub>("/api/chatHub");
+    options.Transports =
+        HttpTransportType.WebSockets |
+        HttpTransportType.LongPolling;
 });
+
 #endregion
 
 app.MapControllerRoute(