현재 실행 중인 브라우져 쿠키 정보를 가져 올 수 있는 방법이 있을까요?

안녕하십니까
이리저리 구글링해봐도 참고해볼 정보가 없어서 문의드리게 되었습니다.

구현 하고 싶은 부분은
현재 실행 중인 Edge 브라우져에 접속(로그인 완료)되어 있는 사이트의 쿠키 정보를 가져 오는 부분입니다.
정확히는 로그인이 완료된 사이트의 JSESSIONID 값을 가져오는것이 목적입니다.

var processes = Process.GetProcessesByName(“msedge”);

foreach (var process in processes)
{
var windowHandle = process.MainWindowHandle;
if (windowHandle != IntPtr.Zero)
{
SetForegroundWindow(windowHandle);
AutomationElement root = AutomationElement.FromHandle(process.MainWindowHandle);
Condition condition = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.TabItem);
var tabs = root.FindAll(TreeScope.Descendants, condition);
}
}

위의 소스로 현재 실행 중인 Edge 브라우져 프로세스를 가져와
해당 (AutomationElement) root 객체에서 Tab 객체를 구하는 것까지는 성공 하였습니다.

그 이후로 HttpWebRequest 객체를 가져와 Cookie 정보를 구하는 방법을 찾지 못하고 있습니다.

요즘 chatGPT에도 검색해보면 URL 정보를 구해서 신규로 접속해서 구해오는 방법만 나와 헛발질만 계속 하고 있습니다. ㅜㅜ

2개의 좋아요

질문이
실행중인 ms엣지 브라우저로 접속되어 있는 로그인 되어 있는 사이트의 세션정보를 가져오는 것이 맞나요?


일단 각 사이트 마다 어떤 방식으로 로그인 세션을 처리 하는지에 따라 다릅니다.

브라우저로 접속되어 있는 사이트의 세션정보는 보통 쿠키로 관리 된다하면

HttpWebRequest 로 쿠키를 가져 오는 것이 아니라 이미 쿠키정보는 보통 로컬의 파일로 존재 하고 있습니다.

따라서 ms엣지가 사용하는 디렉토리의 쿠키 파일을 직접 File Open해서 해당 쿠키내용을 파싱해서 사용해야 합니다.

그렇게 쿠키 파일을 파싱해서 로그인 세션 정보를 추출 했다면 (보통 사이트라면 힘들거 같지만.,)
기타 쿠키 데이터와 로그인 세션 정보를 똑같이 조합해서

그제서야 CookieContainer 클래스를 이용해서 HttpWebRequest 클래스나 HttpClient 클래스 등을 이용해서 코드 상으로 요청을 해야 합니다.


이렇게 수동으로 브라우저로 인해 저장 되는 쿠키 데이터를 가지고 로그인 세션을 유지해서 http요청을 하는 것은 복잡하기 때문에

직접 로그인 처리를 HttpWebRequest / HttpClient 클래스 로 처리해서
CookieContainer 에 로그인 쿠키를 들고 있는 채로 로그인을 유지 한채로 이후 http요청을 수행 하는 것이 그나마 더 수월합니다.

4개의 좋아요

답변 주셔서 감사합니다.
제가 Web 프로그램만 하다보니 C#은 초보 입니다. ㅜㅜ

특정 (예 :test.com) 사이트의 쿠키정보 중 JSSIONID 값만 구하기만 하면 통신하는 부분은 별도의 Web서비스에 전달하기만 하면 통신하는건 문제가 되지 않을것 같습니다.
(기 테스트 완료)

해당 쿠키 파일을 구하는 방법과 읽어 오는 방법에 대해 예제를 구할 수 있을까요?

다른 영역의 개발을 하니 방황만 하게 되네요

3개의 좋아요

ms빙(GPT)에 물어보니 ms엣지 브라우저의 쿠키 파일 위치는 다음과 같다고 합니다.

C:\Users{사용자 이름}\AppData\Local\Microsoft\Edge\User Data\Default\Cookies


그리고 ms빙에서 추가로

ms엣지 브라우저는 쿠키파일을 Sqlite 로 관리하고 있다는 사실도 알게되었습니다.

따라서 다음과 같이 쿠키정보를 읽어서 파싱 할 수 있을거 같습니다.
(세션 정보가 암호화 되어있지 않다면요)

using System;
using System.Data.SQLite;

namespace CookieParser
{
    class Program
    {
        static void Main(string[] args)
        {
            // 쿠키 파일의 경로
            string cookiePath = @"C:\Users\{사용자 이름}\AppData\Local\Microsoft\Edge\User Data\Default\Cookies";

            // SQLite 연결 객체 생성
            SQLiteConnection conn = new SQLiteConnection("Data Source=" + cookiePath);

            // 연결 열기
            conn.Open();

            // SQL 명령 객체 생성
            SQLiteCommand cmd = new SQLiteCommand(conn);

            // 쿠키 테이블에서 모든 데이터 조회
            cmd.CommandText = "SELECT * FROM cookies";

            // 데이터 리더 객체 생성
            SQLiteDataReader reader = cmd.ExecuteReader();

            // 데이터 리더에서 한 행씩 읽기
            while (reader.Read())
            {
                // 각 필드의 값을 출력
                Console.WriteLine("Creation_utc: " + reader["creation_utc"]);
                Console.WriteLine("Host_key: " + reader["host_key"]);
                Console.WriteLine("Name: " + reader["name"]);
                Console.WriteLine("Value: " + reader["value"]);
                Console.WriteLine("Expires_utc: " + reader["expires_utc"]);
                Console.WriteLine("Is_secure: " + reader["is_secure"]);
                Console.WriteLine("Is_httponly: " + reader["is_httponly"]);
                Console.WriteLine("Last_access_utc: " + reader["last_access_utc"]);
                Console.WriteLine();
            }

            // 리더 닫기
            reader.Close();

            // 연결 닫기
            conn.Close();
        }
    }
}
4개의 좋아요

감사합니다.

제공해주신 소스를 접목해서 테스트 해보도록 하겠습니다.

절망속에서 희망을 주셔서 감사합니다. ^^

3개의 좋아요

제공해주신 정보 덕분에 잘 해결이 되었습니다.

다른분도 찾으실 것 같아 공유 합니다.
Cookies 파일이 Network 폴더 하위로 이동 된 부분과
Value가 암호화 되어 복화하는 방법입니다.


코드로 표시

internal class BrowserInfo
{
        class LocalStateDto
        {
            [JsonPropertyName("os_crypt")]
            public OsCrypt OsCrypt { get; set; }
        }

        class OsCrypt
        {
            [JsonPropertyName("encrypted_key")]
            public string EncryptedKey { get; set; }
        }
        private const string CookiesFileName = @"Default\Network\Cookies";
        private const string LocalStateFileName = "Local State";
        public static ICollection<Cookie> GetCookies(string baseFolder)
        {
            Console.WriteLine("GetCookies");
            byte[] key = GetKey(baseFolder);
            ICollection<Cookie> cookies = ReadFromDb(baseFolder, key);
            return cookies;
        }

        private static byte[] GetKey(string baseFolder)
        {
            Console.WriteLine("GetKey : " + baseFolder);
            string file = Path.Combine(baseFolder, LocalStateFileName);
            Console.WriteLine("file : " + file);
            string localStateContent = File.ReadAllText(file);
            LocalStateDto localState = JsonSerializer.Deserialize<LocalStateDto>(localStateContent);
            string encryptedKey = localState?.OsCrypt?.EncryptedKey;

            var keyWithPrefix = Convert.FromBase64String(encryptedKey);
            var key = keyWithPrefix[5..];
            var masterKey = ProtectedData.Unprotect(key, null, DataProtectionScope.CurrentUser);
            return masterKey;
        }
        private static ICollection<Cookie> ReadFromDb(string baseFolder, byte[] key)
        {
            Console.WriteLine("ReadFromDb : " + baseFolder);
            ICollection<Cookie> result = new List<Cookie>();
            string dbFileName = Path.Combine(baseFolder, CookiesFileName);
            Console.WriteLine("dbFileName : " + dbFileName);
            using (SQLiteConnection connection = new SQLiteConnection($"Data Source={dbFileName}"))
            {
                connection.Open();

                long expireTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
                SQLiteCommand command = connection.CreateCommand();
                command.CommandText =
                    @"select  * from cookies  WHERE path = '/' and (has_expires = 0 or (has_expires = 1 and expires_utc > $expireTime))
                    ";
                command.Parameters.AddWithValue("$expireTime", expireTime);
                using (SQLiteDataReader reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        string name = reader["name"].ToString();
                        string path = reader["path"].ToString();
                        string domain = reader["host_key"].ToString();
                        byte[] encrypted_value = (byte[])reader["encrypted_value"];
                        string value = DecryptCookie(key, encrypted_value);
                        Cookie cookie = new Cookie(name, value, path, domain);
                        result.Add(cookie);
                    }
                }

                return result;
            }
        }
        private static string DecryptCookie(byte[] masterKey, byte[] cookie)
        {
            byte[] nonce = cookie[3..15];
            byte[] ciphertext = cookie[15..(cookie.Length - 16)];
            byte[] tag = cookie[(cookie.Length - 16)..(cookie.Length)];

            byte[] resultBytes = new byte[ciphertext.Length];

            using AesGcm aesGcm = new AesGcm(masterKey);
            aesGcm.Decrypt(nonce, ciphertext, tag, resultBytes);
            string cookieValue = Encoding.UTF8.GetString(resultBytes);
            return cookieValue;
        }
}

사용 방법

      string userName = Environment.UserName;
      string baseFolder = @"C:\Users\" + userName + @"\AppData\Local\Microsoft\Edge\User Data";
      var cookies = BrowserInfo.GetCookies(baseFolder);
7개의 좋아요

```csharp
코드
```

하시면 코드가 좀 더 깔끔하게 보입니다.

3개의 좋아요