136 lines
3.1 KiB
C#
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);
|
|
}
|
|
}
|