using EVCB_OCPP.Domain; using EVCB_OCPP.WSServer; using EVCB_OCPP.WSServer.Helper; using NLog; using OCPPPackage.Profiles; using SuperWebSocket; using SuperWebSocket.SubProtocol; using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Net; using System.Net.Security; using System.Security.Cryptography.X509Certificates; using System.Text; namespace OCPPServer.Protocol { public class OCPPWSServer : WebSocketServer { static private ILogger logger = NLog.LogManager.GetCurrentClassLogger(); /// /// 可允許連線Clinet數 /// public int connectNum { get; set; } /// /// 是否限制連線Clinet數 /// public bool beConnectLimit { get; set; } /// /// Initializes a new instance of the class. /// /// The sub protocols. public OCPPWSServer(IEnumerable> subProtocols) : base(subProtocols) { } /// /// Initializes a new instance of the class. /// /// The sub protocol. public OCPPWSServer(ISubProtocol subProtocol) : base(subProtocol) { } /// /// Initializes a new instance of the class. /// public OCPPWSServer() : base(new List>()) { } protected override bool ValidateClientCertificate(ClientData session, object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { // Console.WriteLine(string.Format("{0} :{1}", session.ChargeBoxId + " ValidateClientCertificate", sslPolicyErrors)); return true; // return base.ValidateClientCertificate(session, sender, certificate, chain, sslPolicyErrors); } protected override bool ValidateHandshake(ClientData session, string origin) { int securityProfile = GlobalConfig.SecurityProfileLevel; string authorizationKey = GlobalConfig.SecurityPassword; bool authorizated = false; session.ISOCPP20 = session.SecWebSocketProtocol.ToLower().Contains("ocpp2.0"); if (string.IsNullOrEmpty(session.Path)) { logger.Warn("==========================================="); logger.Warn("session.Path EMPTY"); logger.Warn("==========================================="); } string[] words = session.Path.Split('/'); session.ChargeBoxId = words.Last(); if (ConfigurationManager.AppSettings["MaintainMode"] == "1") { session.ChargeBoxId = session.ChargeBoxId + "_2"; } logger.Info(string.Format("ValidateHandshake: {0}", session.Path)); if (session.ISOCPP20) { // 1.6 server only support change server function securityProfile = 0; } switch (securityProfile) { case 0: { authorizated = true; } break; case 1: { if(session.UriScheme == "ws") { string client_authorization = string.Empty; if (session.Items.ContainsKey("Authorization") || session.Items.ContainsKey("authorization")) { client_authorization = session.Items.ContainsKey("Authorization") ? session.Items["Authorization"].ToString().Replace("Basic ", "") : session.Items["authorization"].ToString().Replace("Basic ", ""); } if (ValidateSecurity(session.ChargeBoxId, authorizationKey, client_authorization)) { authorizated = true; } else { logger.Warn(string.Format(" {0} ValidateSecurity Fail client_authorization:[{1}]:", session.ChargeBoxId, client_authorization)); } } } break; case 2: { if (session.UriScheme == "wss") { string client_authorization = string.Empty; if (session.Items.ContainsKey("Authorization") || session.Items.ContainsKey("authorization")) { client_authorization = session.Items.ContainsKey("Authorization") ? session.Items["Authorization"].ToString().Replace("Basic ", "") : session.Items["authorization"].ToString().Replace("Basic ", ""); } if (ValidateSecurity(session.ChargeBoxId, authorizationKey, client_authorization)) { authorizated = true; } else { logger.Warn(string.Format(" {0} ValidateSecurity Fail client_authorization:[{1}]:", session.ChargeBoxId, client_authorization)); } } } break; case 3: { authorizated = false; } break; default: break; } if(!authorizated) { StringBuilder responseBuilder = new StringBuilder(); responseBuilder.AppendFormatWithCrCf(@"HTTP/{0} {1} {2}", "1.1", (int)HttpStatusCode.Unauthorized, @"Unauthorized"); responseBuilder.AppendWithCrCf(); string sb = responseBuilder.ToString(); byte[] data = Encoding.UTF8.GetBytes(sb); ((IWebSocketSession)session).SendRawData(data, 0, data.Length); logger.Info(sb); return false; } return true; } private bool ValidateSecurity(string chargeBoxId, string authorizationKey, string client_authorization) { bool result = false; if (string.IsNullOrEmpty(client_authorization)) return result; string server_authorization = EncodeHelper.EncodeBase64(string.Format("{0}:{1}", chargeBoxId, authorizationKey)); if (client_authorization == server_authorization) { result = true; } return result; } } }