ad_login/Controllers/AdApiController.cs

309 lines
13 KiB
C#
Raw 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 Dapper;
using Dapper.Contrib.Extensions;
using MailKit.Security;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Data.SqlClient;
using Microsoft.Extensions.Options;
using MimeKit;
using Newtonsoft.Json;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
using System.DirectoryServices.Protocols;
using System.Net;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using static ad_login.Controllers.ApiController;
using static DbTableClass;
namespace ad_login.Controllers
{
[EnableCors("any")]
[Route("adApi")]
public class AdApiController : ControllerBase
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IWebHostEnvironment _hostingEnvironment;
private readonly PasswordManagementService _passwordManagement;
private readonly string _ldapServer;
private readonly string _domain;
private readonly string _baseDn;
DbConn dbConn = new DbConn();
SqlConnection conn = new SqlConnection(GlobalClass.appsettings("ConnectionStrings:SQLConnectionString"));
public AdApiController(IHttpContextAccessor httpContextAccessor, IWebHostEnvironment webHostEnvironment, PasswordManagementService passwordManagement, IOptions<LdapSettings> ldapSettings)
{
this._httpContextAccessor = httpContextAccessor;
this._hostingEnvironment = webHostEnvironment;
this._passwordManagement = passwordManagement;
this._ldapServer = ldapSettings.Value.Server;
this._domain = ldapSettings.Value.Domain;
this._baseDn = ldapSettings.Value.BaseDn;
}
[EnableCors("any")]
[Route("resetPassword")]
[SupportedOSPlatform("windows")]
public ActionResult ResetPassword(IFormCollection obj)
{
Result ret = new Result();
string new_password = obj["new_password"].ToString();
string token = obj["token"].ToString();
if (new_password == "")
{
ret.message = "new_password is null";
ret.err_code = "1003";
ret.ret = "no";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
mailToken objMailToken = conn.QueryFirstOrDefault<mailToken>("select * from mailToken where mailToken_value=@mailToken_value and mailToken_useed='N' and mailToken_endDate>=getdate()", new { mailToken_value = token });
if (objMailToken == null)
{
ret.ret = "no";
ret.err_code = "1001";
ret.message = "token無效或過期或是已經變更密碼過了請重新申請忘記密碼步驟";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
try {
DirectoryEntry entry = new DirectoryEntry($"LDAP://{_ldapServer}/{_baseDn}", GlobalClass.appsettings("LdapSettings:User"), GlobalClass.appsettings("LdapSettings:Password")); // 使用 LDAP 伺服器和基礎 DN 建立 DirectoryEntry 物件。
DirectorySearcher mySearcher = new DirectorySearcher(entry);
mySearcher.Filter = ("(&(objectClass=user)(sAMAccountName=" + objMailToken.mailToken_account + "))");
SearchResult searchResult = mySearcher.FindOne();
DirectoryEntry userEntry = searchResult.GetDirectoryEntry();
userEntry.Invoke("SetPassword", new object[] { new_password });
ret.ret = "yes";
objMailToken.mailToken_useed = "Y";
conn.Update<mailToken>(objMailToken);
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
} catch (Exception ex) {
ret.ret = "no";
ret.err_code = "1002";
ret.message = "修改密碼失敗,請聯絡系統管理員 原因為" + ex.Message;
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
[EnableCors("any")]
[Route("forgetPassword")]
[SupportedOSPlatform("windows")]
public async Task<ActionResult> ForgetPasswordAsync(IFormCollection obj)
{
Result ret = new Result();
string userEmail = obj["userEmail"].ToString();
string userAccount = obj["userAccount"].ToString();
if (userAccount == "")
{
ret.message = "userAccount is null";
ret.err_code = "1003";
ret.ret = "no";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
if (userEmail == "")
{
ret.message = "userEmail is null";
ret.err_code = "1004";
ret.ret = "no";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, _domain, _baseDn, GlobalClass.appsettings("LdapSettings:User"), GlobalClass.appsettings("LdapSettings:Password")))
{
UserPrincipal user = UserPrincipal.FindByIdentity(pc, userAccount);
if (user != null)
{
if (user.Enabled == false)
{
ret.message = "此帳號已被停用";
ret.err_code = "1007";
ret.ret = "no";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
string emailaddress = user.EmailAddress ?? "";
if (emailaddress != userEmail)
{
ret.message = "帳號與Email不符不是公司發給此帳號的Email";
ret.err_code = "1005";
ret.ret = "no";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
mailToken objMailToken = new mailToken();
objMailToken.mailToken_value = GlobalClass.CreateRandomCode(24);
objMailToken.mailToken_mail = userEmail;
objMailToken.mailToken_endDate = DateTime.Now.AddHours(12);
objMailToken.mailToken_account = userAccount;
conn.Insert<mailToken>(objMailToken);
string htmlBody = "";
htmlBody += "<H2>重設登入PC或公槽密碼確認信</H2>";
htmlBody += "<br/>如果您有重設登入PC或公槽密碼需求的話請點下面連結開始網頁重設密碼。如果沒有請忽略此信!";
htmlBody += "<br/><br/>重設密碼連結:<a href='" + "https://ad-pass.bremen.com.tw/Home/reset?token=" + objMailToken.mailToken_value + "' target='_blank'>" + "https://ad-pass.bremen.com.tw/Home/reset?token=" + objMailToken.mailToken_value + "</a>";
htmlBody += "<br/><br/>PS:此連結於" + objMailToken.mailToken_endDate.ToString("yyyy/MM/dd HH:mm") + "前有效!";
MailRequest mailRequest = new MailRequest();
mailRequest.ToEmail = userEmail;
mailRequest.Body = htmlBody;
mailRequest.Subject = "重設登入PC或公槽密碼確認信";
await SendEmailAsync(mailRequest);
ret.ret = "yes";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
else
{
ret.message = "User not found";
ret.err_code = "1006";
ret.ret = "no";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
}
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
[EnableCors("any")]
[Route("aduserList")]
[SupportedOSPlatform("windows")]
public ActionResult AduserList(IFormCollection obj) {
Result ret = new Result();
string query_token = obj["query_token"].ToString();
if (query_token == "") {
ret.message = "query_token is null";
ret.err_code = "1001";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
if (query_token != GlobalClass.appsettings("LdapSettings:query_token"))
{
ret.message = "query_token is wrong";
ret.err_code = "1002";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
List<String> expiringUsers = [];
DirectoryEntry entry = new DirectoryEntry($"LDAP://{_ldapServer}/{_baseDn}", GlobalClass.appsettings("LdapSettings:User"), GlobalClass.appsettings("LdapSettings:Password")); // 使用 LDAP 伺服器和基礎 DN 建立 DirectoryEntry 物件。
DirectorySearcher mySearcher = new DirectorySearcher(entry);
mySearcher.Filter = "(&(objectCategory=person)(objectClass=user))"; // 篩選有「上次密碼設定時間」、「Mail」的「使用者」。
// 電子郵件
foreach (SearchResult result in mySearcher.FindAll())
{
string userSAMAccountName = result.Properties["sAMAccountName"][0].ToString() ?? string.Empty; // AD 帳號
string userDisplayName = "";
string userMail = "";
if (result.Properties["displayName"].Count > 0)
userDisplayName = result.Properties["displayName"][0].ToString();
else
userDisplayName = userSAMAccountName; // 顯示名稱
if (result.Properties["mail"].Count > 0) {
userMail = result.Properties["mail"][0].ToString() ?? string.Empty;
}
int flags = (int)result.Properties["userAccountControl"][0];
string expiringUsersInfo = $"{userSAMAccountName};{userDisplayName};{userMail}";
adUser adUser = new adUser
{
userAccount = userSAMAccountName,
userDisplayName = userDisplayName,
userMail = userMail
};
if (!Convert.ToBoolean(flags & 0x0002) && (userMail != "")) {
ret.data.Add(adUser); // 如果帳號沒有被停用,且有電子郵件,就加入結果列表。
}
}
ret.ret = "yes";
return Content(JsonConvert.SerializeObject(ret), "application/json;charset=utf-8");
}
public async Task SendEmailAsync(MailRequest mailRequest)
{
var email = new MimeMessage();
email.Sender = MailboxAddress.Parse(GlobalClass.appsettings("MailServer:smtp_username"));
email.To.Add(MailboxAddress.Parse(GlobalClass.appsettings("MailServer:smtp_username")));
foreach (string item in mailRequest.ToEmail.Split(','))
{
email.Bcc.Add(MailboxAddress.Parse(item));
}
email.Subject = "重設登入PC或公槽密碼確認信";
var builder = new BodyBuilder();
if (mailRequest.attach != null)
{
builder.Attachments.Add(mailRequest.attachName, mailRequest.attach);
}
builder.HtmlBody = mailRequest.Body;
email.Body = builder.ToMessageBody();
using var smtp = new MailKit.Net.Smtp.SmtpClient();
smtp.Connect(GlobalClass.appsettings("MailServer:smtp_host"), int.Parse(GlobalClass.appsettings("MailServer:smtp_port")), SecureSocketOptions.StartTls);
smtp.Authenticate(GlobalClass.appsettings("MailServer:smtp_username"), GlobalClass.appsettings("MailServer:smtp_password"));
await smtp.SendAsync(email);
smtp.Dispose();
}
public class Result
{
public string ret = "no";
public string err_code = "0000";
public string message = "";
public List<adUser> data = new List<adUser>();
}
public class adUser
{
public string userAccount { get; set; } = string.Empty; // AD 帳號
public string userDisplayName { get; set; } = string.Empty; // 顯示名稱
public string userMail { get; set; } = string.Empty; // 電子郵件
}
}
}