using Microsoft.Extensions.Options; using System.DirectoryServices.Protocols; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.Net; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; public static class GlobalClass { public static IServiceProvider ServiceProvider; public static bool isURL(string url) { return Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute); } public static string GetIP(this HttpContext context) { var ip = context.Request.Headers["X-Forwarded-For"].FirstOrDefault(); if (string.IsNullOrEmpty(ip)) { ip = context.Connection.RemoteIpAddress.ToString(); } return ip; } public static string CreateRandomCode(int Number) { string allChar = "0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z"; string[] allCharArray = allChar.Split(','); string randomCode = ""; Random rand = new Random(Guid.NewGuid().GetHashCode()); for (int i = 0; i <= Number - 1; i++) { int t = rand.Next(allCharArray.Length); randomCode += allCharArray[t]; } return randomCode; } public static string CreateUniRandomCode(int Number) { string allChar = "2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,J,K,M,N,P,Q,R,S,U,V,W,X,Y,Z"; string[] allCharArray = allChar.Split(','); string randomCode = ""; Random rand = new Random(Guid.NewGuid().GetHashCode()); for (int i = 0; i <= Number - 1; i++) { int t = rand.Next(allCharArray.Length); randomCode += allCharArray[t]; } return randomCode; } public static string ToMD5(this string str) { using (var cryptoMD5 = System.Security.Cryptography.MD5.Create()) { //將字串編碼成 UTF8 位元組陣列 var bytes = Encoding.UTF8.GetBytes(str); //取得雜湊值位元組陣列 var hash = cryptoMD5.ComputeHash(bytes); //取得 MD5 var md5 = BitConverter.ToString(hash) .Replace("-", String.Empty) .ToLower(); return md5; } } public static string Sha256(this string input) { System.Security.Cryptography.SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider(); Byte[] ByteString = Encoding.ASCII.GetBytes(input); ByteString = sha256.ComputeHash(ByteString); string returnString = ""; foreach (Byte bt in ByteString) { returnString += bt.ToString("x2"); } return returnString.ToLower(); } /// /// Creates a SHA256 hash of the specified input. /// /// The input. /// A hash. public static byte[] Sha256(this byte[] input) { if (input == null) { return null; } using (var sha = SHA256.Create()) { return sha.ComputeHash(input); } } public static bool isEmail(string email) { //Email檢查格式 System.Text.RegularExpressions.Regex EmailExpression = new Regex(@"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$", RegexOptions.Compiled | RegexOptions.Singleline); try { if (string.IsNullOrEmpty(email)) { return false; } else { return EmailExpression.IsMatch(email); } } catch (Exception ex) { //log.Error(ex.Message); return false; } } public static string appsettings(string key) { var builder = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json"); var config = builder.Build(); return config[key]; } public static Image embedImage(Image watermark, Image targetImg, int x, int y) { Image outImg; using (Graphics g = Graphics.FromImage(targetImg)) { g.DrawImage(watermark, new Rectangle(x, y, watermark.Width, watermark.Height)); outImg = (Image)targetImg.Clone(); } return outImg; } public static Image resizeImage(Image image, int width, int height) { var destinationRect = new Rectangle(0, 0, width, height); var destinationImage = new Bitmap(width, height); destinationImage.SetResolution(image.HorizontalResolution, image.VerticalResolution); using (var graphics = Graphics.FromImage(destinationImage)) { graphics.CompositingMode = CompositingMode.SourceCopy; graphics.CompositingQuality = CompositingQuality.HighQuality; using (var wrapMode = new ImageAttributes()) { wrapMode.SetWrapMode(WrapMode.TileFlipXY); graphics.DrawImage(image, destinationRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode); } } return (Image)destinationImage; } } public class LdapSettings { public string Server { get; set; } = string.Empty; public string Domain { get; set; } = string.Empty; public string BaseDn { get; set; } = string.Empty; } public class PasswordManagementService(IOptions ldapSettings) { private readonly string _ldapServer = ldapSettings.Value.Server; private readonly string _domain = ldapSettings.Value.Domain; private readonly string _baseDn = ldapSettings.Value.BaseDn; // 修改密碼 (透過 System.DirectoryServices.Protocols) public bool ChangePasswordSdsP(string username, string oldPassword, string newPassword) { try { using var connection = new LdapConnection(new LdapDirectoryIdentifier(_ldapServer, 636)); // 修改密碼必須使用 LDAPS 636 port。 connection.Credential = new NetworkCredential(username, oldPassword, _domain); connection.SessionOptions.SecureSocketLayer = true; // 修改密碼必須使用 LDAPS。 connection.SessionOptions.ProtocolVersion = 3; // 使用 LDAPv3 協議。 connection.SessionOptions.VerifyServerCertificate = (con, cert) => true; // 忽略證書驗證 (僅在測試環境使用,生產環境應該正確配置 SSL/TLS 證書)。 connection.AuthType = AuthType.Negotiate; // 如果使用 Negotiate 會先嘗試 Kerberos,失敗再改試 NTLM。 connection.Bind(); // 嘗試綁定,成功表示驗證通過 // 以 sAMAccountName 查詢使用者的 DN SearchRequest searchRequest = new( _baseDn, // 根目錄 $"(sAMAccountName={username})", // 根據 sAMAccountName 查詢 System.DirectoryServices.Protocols.SearchScope.Subtree, "distinguishedName" // 只獲取 DN 屬性 ); SearchResponse searchResponse = (SearchResponse)connection.SendRequest(searchRequest); if (searchResponse.Entries.Count == 0) { Console.WriteLine("User not found."); return false; } string userDn = searchResponse.Entries[0].DistinguishedName; // 使用 LDAP 修改密碼屬性 (unicodePwd) 時, // 只有高權限帳號 (如 Domain Admins) 可以對 unicodePwd 屬性執行修改 (DirectoryAttributeOperation.Replace)。 // 若要讓一般使用者更改自己的密碼,必須透過 LDAPS (安全通道),且同時送出 delete 與 add 操作來替換密碼。 var deleteOldPassword = new DirectoryAttributeModification { Operation = DirectoryAttributeOperation.Delete, Name = "unicodePwd" }; deleteOldPassword.Add(Encoding.Unicode.GetBytes($"\"{oldPassword}\"")); var addNewPassword = new DirectoryAttributeModification { Operation = DirectoryAttributeOperation.Add, Name = "unicodePwd" }; addNewPassword.Add(Encoding.Unicode.GetBytes($"\"{newPassword}\"")); // 組合 ModifyRequest,執行 Delete + Add 操作 var request = new ModifyRequest( userDn, deleteOldPassword, addNewPassword ); connection.SendRequest(request); return true; } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); return false; } } }