Files

136 lines
3.1 KiB
C#

using System;
using System.Runtime.InteropServices;
using System.Text;
using AxCopilot.Services;
namespace AxCopilot.Handlers;
public static class CredentialManager
{
private struct FILETIME
{
public uint dwLowDateTime;
public uint dwHighDateTime;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct CREDENTIAL
{
public uint Flags;
public uint Type;
public nint TargetName;
public nint Comment;
public FILETIME LastWritten;
public uint CredentialBlobSize;
public nint CredentialBlob;
public uint Persist;
public uint AttributeCount;
public nint Attributes;
public nint TargetAlias;
public nint UserName;
}
private const uint CRED_TYPE_GENERIC = 1u;
private const uint CRED_PERSIST_LOCAL_MACHINE = 2u;
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool CredRead(string target, uint type, uint flags, out nint credential);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool CredWrite([In] ref CREDENTIAL userCredential, uint flags);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern void CredFree(nint cred);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool CredDelete(string target, uint type, uint flags);
public static string? GetToken(string key)
{
if (string.IsNullOrEmpty(key))
{
return null;
}
try
{
if (CredRead(key, 1u, 0u, out var credential))
{
try
{
CREDENTIAL cREDENTIAL = Marshal.PtrToStructure<CREDENTIAL>(credential);
if (cREDENTIAL.CredentialBlobSize != 0 && cREDENTIAL.CredentialBlob != IntPtr.Zero)
{
return Marshal.PtrToStringUni(cREDENTIAL.CredentialBlob, (int)cREDENTIAL.CredentialBlobSize / 2);
}
}
finally
{
CredFree(credential);
}
}
}
catch (Exception ex)
{
LogService.Warn("Windows Credential Manager 읽기 실패 (" + key + "): " + ex.Message);
}
return Environment.GetEnvironmentVariable(key.ToUpperInvariant());
}
public static void SetToken(string key, string token)
{
if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(token))
{
return;
}
byte[] bytes = Encoding.Unicode.GetBytes(token);
nint num = Marshal.AllocHGlobal(bytes.Length);
nint num2 = Marshal.StringToCoTaskMemUni(key);
nint num3 = Marshal.StringToCoTaskMemUni(Environment.UserName);
try
{
Marshal.Copy(bytes, 0, num, bytes.Length);
CREDENTIAL userCredential = new CREDENTIAL
{
Type = 1u,
TargetName = num2,
UserName = num3,
CredentialBlobSize = (uint)bytes.Length,
CredentialBlob = num,
Persist = 2u
};
if (!CredWrite(ref userCredential, 0u))
{
LogService.Error($"토큰 저장 실패: {key}, 오류 코드: {Marshal.GetLastWin32Error()}");
}
else
{
LogService.Info("토큰 저장 완료: " + key);
}
}
finally
{
Marshal.FreeHGlobal(num);
Marshal.FreeCoTaskMem(num2);
Marshal.FreeCoTaskMem(num3);
}
}
public static bool DeleteToken(string key)
{
return !string.IsNullOrEmpty(key) && CredDelete(key, 1u, 0u);
}
}