ad_login/Models/GlobalClass.cs

228 lines
8.5 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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();
}
/// <summary>
/// Creates a SHA256 hash of the specified input.
/// </summary>
/// <param name="input">The input.</param>
/// <returns>A hash.</returns>
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> 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;
}
}
}