레이블이 Dev인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Dev인 게시물을 표시합니다. 모든 게시물 표시

2023/02/28

Visual Studio CS0518 에러 메시지 표시 관련

Visual Studio 2019 에서, 이전 버전에서 작업했던 ASP.NET MVC 프로젝트를 로드하면, cshtml 에서 c# 언어쪽 문자열에서 CS0518 개체 타입 관련 경고(오류) 표시가 쭈욱 나는 증상..

빈 새프로젝트를 생성해서 비교해 보니, 이건 또 경고창이 안뜬다. web.config 에서 compilers 항목의 버전 지정값이 다르긴 한데..

그래서, 다시 기존 프로젝트를 열었던 VS 를 종료후 다시 실행하니깐.. 응??? 이건 왜 또 경고창이 발생안해 ???.....;;  cshtml 파일 razor 타입 코딩된 페이지 열면 경고창이 떳는데, 메쏘드 부분만 잘라내기 후 다시 그자리에 붙이기 하니, 경고창이 없어진다.. ㅎㅎ 

이건 아무래도.. Visual Studio 소스 편집기 "버그" 인것 같음.. 이유는 위와 같이 어떨땐 경고표시되고 어떨땐 또 정상으로 잘 확인되고... 패턴을 모르겠음..

다른 문서를 찾아보면, mscorlib.dll 로딩 문제라고 하는데 그게 맞는건지도 모르겟고.. 원인 찾아볼려고 했는데... 다들 이런 저런 얘기가 있긴 한데,. 조금씩 다른 얘기들이라서 맞는건지도 모르겠고.. 그냥 이쯤에서 종료..;;





2022/10/12

Windows 8 / 2012 R2 TLS 1.2 Cipher suite (SSL/TLS 보안 채널 오류)

Windows 8 및 Windows Server 2012 R2 에서는,  아래와 같은 암호화 알고리즘을 지원하지 않는다. 지원은 Windows 10 및 Windows 2016 에서 부터이다.


https://learn.microsoft.com/en-us/windows/win32/secauthn/tls-cipher-suites-in-windows-8-1


# TLS 1.2 (suites in server-preferred order)

TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)   ECDH x25519

TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)   ECDH x25519



일부 서버에서, TLS 보안 강화 목적으로, SSL 은 물론이고, TLS 1.2 1.3 에서 'WEAK' 알고리즘을 제거하는 경우가 종종 있다.

그런 웹서버(웹사이트)에 접속하는 경우, "요청이 중단되었습니다. SSL/TLS 보안 채널을 만들 수 없습니다." 라는 오류를 만날수 있다.  특히.. Windows 자체 라이브러리를 활용하는 Client의 경우..

Proxy 를 이용한다고 해도, IP/MAC 등 필수 변환 정보외 나머지 패킷을 원본 서버것 그대로 전달하기 때문에, 동일하게 오류가 발생한다.

물론 크롬등과 같이 자체적으로 모듈을 가지고 있는 경우에는, OS 와 상관없이 자체적으로 처리하므로 상관이 없을수 있다.

해결책은 뭐.. 자체 알고리즘을 가지고 자체 작동하는 라이브러리를 참조하거나,... 아니면.. OS 를 업그레이드 하던가....

해외 일부 커뮤니티에는... 레지스트리를 바꿔봐라 뭐 이런 내용이 있는데, OS 자체에서 라이브러리가 없는데, 레지스트리에 글자 추가해봐야 뭔소용...


Windows Server 2016 까지는, TLS 1.2 까지만 지원되며, TLS 1.3 은 Windows Server 2019 부터 지원된다. TLS 1.3이 필요하거나, 또는 어느 시점에 되면 하위 버전은 웹브라우저(크롬등등)에서 제외 될텐데, 그때가 되면, 또 어쩔수 없이 상위 OS 버전으로 업그레이드를 해야 한다.

TLS 1.3에서 활용되는 TLS_CHACHA20_POLY1305_SHA256 알고리즘은, Windows Server 2022 에서 부터 지원된다.



----- Windows Server 2012R2 에서 지원되는 알고리즘 목록 -----

TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_256_GCM_SHA384
TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P384
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P384
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P384
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P256
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P384
TLS_RSA_WITH_AES_256_CBC_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384_P384
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P256
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384_P384
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P256
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P256
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P384
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P256
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P384
TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
TLS_DHE_DSS_WITH_AES_256_CBC_SHA
TLS_DHE_DSS_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA
TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
TLS_RSA_WITH_RC4_128_SHA
TLS_RSA_WITH_RC4_128_MD5
TLS_RSA_WITH_NULL_SHA256
TLS_RSA_WITH_NULL_SHA
SSL_CK_RC4_128_WITH_MD5
SSL_CK_DES_192_EDE3_CBC_WITH_MD5







2021/11/02

c# netstat 예제

netstat.exe 에서 확인하던 정보를 C# 으로..  


        public void NetStat()
        {
            IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
            TcpConnectionInformation[] tcpConnInfoArray = ipProperties.GetActiveTcpConnections();

            foreach (TcpConnectionInformation tcpConnInfo in tcpConnInfoArray)
            {
                //TcpState tcpState = tcpConnInfo.State;
                //IPEndPoint localEndPoint = tcpConnInfo.LocalEndPoint;
                //IPEndPoint remotrEndPoint = tcpConnInfo.RemoteEndPoint;
            }
        }



더 세부적으로 깊게 접근하고 싶다면, Win32 라이브러리를 참조..;;

[DllImport("iphlpapi.dll",SetLastError=true)] 






2021/02/20

Failed to add reference to '???'. Please make sure that it is in the Global Assembly Cache. 오류

심각도 코드 설명 프로젝트 파일 비표시 오류(Suppression) 상태

오류 Failed to add reference to 'System.Linq'. Please make sure that it is in the Global Assembly Cache. 0


> 기본 참조 라이브러리 목록에 없기 때문에, 직접 해당 dll 파일 위치를 찾아서 지정...? 이게 진정 해결책? C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Linq\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Linq.dll   이렇게 직접 지정 ???

Nuget 패키지 시스템 버그 인가..?


That's a very confusing error message since the GAC isn't used to resolve references at compile time. Visual Studio should be looking under C:\Program Files(x86)\Reference Assemblies but that location shouldn't be referred to as the Global Assembly Cache.  이런것?


C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\Facades 에는 System.Linq.dll 이 있는데 여기 폴더는 참조 안함.?




 



'GetPathsOfAllDirectoriesAbove() 식을 계산할 수 없습니다' 오류

기존 Webapp 에 컴파일 버전이 2.x 인데, Nuget 에서 3.8 로 업그레이드 실행. 그런데 오류나 가서 완료되지 않았고,..  다른 MS 기본 라이브러리 업데이트도 안됨..  다시 VS 실행하니 참조 라이브러리 모두 오류..


◯◯◯◯.csproj : error  : ""◯◯◯◯.cs".GetPathsOfAllDirectoriesAbove()" 식을 계산할 수 없습니다. 'System.String.GetPathsOfAllDirectoriesAbove' 메서드를 찾을 수 없습니다. ◯◯◯◯\packages\Microsoft.Net.Compilers.3.8.0\tools\Microsoft.Managed.Core.targets


일단, VS ◯◯◯◯.csproj 프로젝트 설정 파일에서, Microsoft.Net.Compilers.3.8.0 항목을 수동 제거하고, 프로젝트 다시 로딩... 일단 경고 에러는 안뜸...

  <Import Project="..\packages\Microsoft.Net.Compilers.2.10.0\build\Microsoft.Net.Compilers.props" Condition="Exists('..\packages\Microsoft.Net.Compilers.2.10.0\build\Microsoft.Net.Compilers.props')" />

  <Import Project="..\packages\Microsoft.Net.Compilers.2.3.2\build\Microsoft.Net.Compilers.props" Condition="Exists('..\packages\Microsoft.Net.Compilers.2.3.2\build\Microsoft.Net.Compilers.props')" />


   <ErrorText>이 프로젝트는 이 컴퓨터에 없는 NuGet 패키지를 참조합니다. 해당 패키지를 다운로드하려면 NuGet 패키지 복원을 사용하십시오. 자세한 내용은 http://go.microsoft.com/fwlink/?LinkID=322105를 참조하십시오. 누락된 파일은 {0}입니다.</ErrorText>

    </PropertyGroup>

    <Error Condition="!Exists('..\packages\Microsoft.Net.Compilers.2.3.2\build\Microsoft.Net.Compilers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Net.Compilers.2.3.2\build\Microsoft.Net.Compilers.props'))" />

    <Error Condition="!Exists('..\packages\Microsoft.Net.Compilers.2.10.0\build\Microsoft.Net.Compilers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Net.Compilers.2.10.0\build\Microsoft.Net.Compilers.props'))" />

  </Target>


닷넷 4.6.1 프로젝트에서는 컴파일 3.8 버전이 지원안되나..? (종속성에는 버전 제한이 없음)  오류 대상 .cs 파일에 위 에러 구문 연관 클래스를 사용한게 없는데.... 어떤글에선 VS.NET 2019 버전에서만 3.x 지원된다고.. (현재 VS2015, 닷넷 4.6.1 기반)

https://www.nuget.org/packages/Microsoft.Net.Compilers/2.10.0  내용을 보면, 닷넷 4.6.1 에서는 최대 2.1 버전 까지 이고, 3.x 버전은 4.7.2+ 필요하다고 되어 있음.. > Nuget 패키지 관리자에서는 왜 업데이트 하라고 띄운것이며, 종속성 검사는 왜 안한건지...?


■ OS 에 설치된 닷넷 파일 버전은 4.8 까지 표시가되고 있으나, VS.NET 에는 4.6.1 까지만 나옴.. 별도 지원 파일을 설치하면 가능 : https://dotnet.microsoft.com/download/visual-studio-sdks?utm_source=getdotnetsdk&utm_medium=referral  에서 4.8 개발자팩 다운로드 설치.


어쨌든... 닷넷 4.x 에서는 컴파일러 3.8 버전은 설치 안되는듯.. 닷넷 5 부터 되는듯.. 정말.?  아무튼 컴파일러 버전 업데이트 포기.. 



2020/03/12

C# Win32 API 이용해서 GUI 핸들 확인하기


키움증권 API 이용해서 직접 개발한 닷넷 기반 주식 자동 매매 GUI 프로그램의, 동작 모니터링과 자동 제어가 필요해서 위해서 참조했던 코드.

실행된 GUI 프로그램에서,  특정 핸들 개체(예를 들면 버튼)가 존재하는지 확인 후, 해당 개체에 바인딩된 Property 값을 가져오거나 클릭/글자입력 같은 Action 을 주기 위해서 활용.

Process _trader = Process.GetProcessesByName("Trader").Single();
IntPtr _handle = _trader.MainWindowHandle;
IntPtr _apiConnet1 = Win32WindowApi.FindWindowEx(_handle, IntPtr.Zero, "WindowsForms10.STATIC.app.0.34f5582_r32_ad1", "OpenAPI");

GUI 컨트롤이 계층 구조인 경우 단계적으로 찾아 가면서 접근하거나, 해당 프로세스 핸들에 속한 모든 하위 핸들을 리스트로 뽑거나 검색하여 해당 컨트롤에 대해서 제어

foreach (IntPtr _child in Win32WindowApi.GetChildWindows(pHandle))
{
    HandleRef _ref = new HandleRef(this, _child);
    int capacity = Win32WindowApi.GetWindowTextLength(_ref) * 2;

    if (capacity > 0)
    {
        StringBuilder stringBuilder = new StringBuilder(capacity);
        Win32WindowApi.GetWindowText(_ref, stringBuilder, capacity);
        Console.WriteLine(">" + stringBuilder);
    }
}

특정 컨트롤(핸들)를 찾기 위해서는, MS Spy++ 같은 유틸을 이용해서 핸들 검색시 고유한 값으로 사용할만한 부분을 미리 찾아 놓으면 됨



    class Win32WindowApi
    {
        public const int WM_COMMAND = 0x0111;
        public const int WM_LBUTTONDOWN = 0x0201;
        public const int WM_LBUTTONUP = 0x0202;
        public const int WM_LBUTTONDBLCLK = 0x0203;
        public const int WM_RBUTTONDBLCLK = 0x0206;
        public const uint WM_SETTEXT = 0x000C;  // 글자 설정
        public const int WM_CHAR = 0x0102;    // 타이핑
        public const int WM_SETFOCUS = 0x0007;
        public const int BM_CLICK = 0x00F5;
        public const int BN_CLICKED = 0;
        public const int MK_LBUTTON = 1;
 
        // Public Const WS_MINIMIZE = &H20000000
        // Public Const WS_MAXIMIZE = &H1000000
 
        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
        }
 
        public delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam);
 
        [DllImport("User32.dll")]
        public static extern Int32 FindWindow(String lpClassName, String lpWindowName);
 
        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
 
        [DllImport("user32.Dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool EnumChildWindows(IntPtr parentHandle, Win32Callback callback, IntPtr lParam);
 
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr GetClassName(IntPtr hWnd, System.Text.StringBuilder lpClassName, int nMaxCount);
 
        [DllImport("user32.dll")]
        public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, IntPtr lParam);
 
        [DllImport("user32.dll")]
        public static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
 
        [DllImport("user32.dll")]
        public static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
 
        [DllImport("user32.dll")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);
 
        [DllImport("user32.dll")]
        public static extern IntPtr GetWindowDC(IntPtr hWnd);
 
        [DllImport("user32.dll")]
        public static extern IntPtr GetWindowRect(IntPtr hWnd, ref RECT rect);
 
        private static bool EnumWindow(IntPtr handle, IntPtr pointer)
        {
            GCHandle gch = GCHandle.FromIntPtr(pointer);
            List<IntPtr> list = gch.Target as List<IntPtr>;
            if (list == null)
                throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
            list.Add(handle);
            return true;
        }
 
        public static List<IntPtr> GetChildWindows(IntPtr parent)
        {
            List<IntPtr> result = new List<IntPtr>();
            GCHandle listHandle = GCHandle.Alloc(result);
            try
            {
                Win32Callback childProc = new Win32Callback(EnumWindow);
                EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
            }
            finally
            {
                if (listHandle.IsAllocated)
                    listHandle.Free();
            }
            return result;
        }
 
        public static string GetWinClass(IntPtr hwnd)
        {
            if (hwnd == IntPtr.Zero)
                return null;
            StringBuilder classname = new StringBuilder(100);
            IntPtr result = GetClassName(hwnd, classname, classname.Capacity);
            if (result != IntPtr.Zero)
                return classname.ToString();
            return null;
        }
 
        public static IEnumerable<IntPtr> EnumAllWindows(IntPtr hwnd, string childClassName)
        {
            List<IntPtr> children = GetChildWindows(hwnd);
            if (children == null)
            {
                yield break;
            }
 
            foreach (IntPtr child in children)
            {
                string _clsName = GetWinClass(child);
                //Console.WriteLine("find. {0:X}", _clsName);
 
                if (_clsName == childClassName)
                {
                    yield return child;
                }
                foreach (var childchild in EnumAllWindows(child, childClassName))
                {
                    //yield return childchild;
                }
            }
        }
    }


2019/08/13

C# Google API Blogger 예제

주로 REST API 호출 예제가 많은데, 구글에서 제공되는 닷넷 API Lib 사용 예제. 인증 부분에서 한참을 헤메다가.. 그리고 API 통해서 포스트내 이미지 업로드 추가는 어떻게 하는건지 못찾음 (지원 안되는것 같음?)


using System.Net.Security;
using Google.Apis.Blogger.v3.Data;
using Google.Apis.Blogger.v3;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Util.Store;
using Google.Apis.Services;


// 인증

UserCredential credential;

using (var stream = new FileStream("client_secret_oauth.json", FileMode.Open, FileAccess.Read))
{
    credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
        GoogleClientSecrets.Load(stream).Secrets,
        new[] { "https://www.googleapis.com/auth/blogger" },    // https://developers.google.com/apis-explorer/#p/blogger/v3/ 에서 허용 설정
        "abc", // 구분값
        CancellationToken.None,
        new FileDataStore("Auth.Blogger")).Result;
}

string blogUrl = "http://bitsyrup.blogspot.com";
BloggerService BloggerService = new BloggerService(new BaseClientService.Initializer()
{
    HttpClientInitializer = credential,
    ApplicationName = "My Project 20108",
});

// 블로그 정보

var BlogResource = BloggerService.Blogs.GetByUrl(blogUrl);
Blog blog = BlogResource.Execute();
Console.WriteLine("Blog ID: " + blog.Id);

// 포스트 데이터

Post PostData = new Post();
PostData.Title = DateTime.Now.ToString() + " " + " - test";
PostData.Content = "◯◯◯23232  <br /><br /> ";
// PostData.Images.Add(◯◯◯);  // 이건 어떻게 작동? 활용 하는건지 못찾음. 예제 없음

// 포스트 올리기

PostsResource PostsResource = new PostsResource(BloggerService);
var post = PostsResource.Insert(PostData, blog.Id).Execute();
Console.WriteLine(post.Id);

// 포스트 목록

PostsResource.ListRequest _request = new PostsResource.ListRequest(_bloggerService, blog.Id);
_request.MaxResults = 50;
_request.FetchBodies = false;
_request.FetchImages = false;

foreach (var _item in _request.Execute().Items)
{
}

C# Google API PhotosLibrary 예제

C# 예제가 거의 전무 하다 시피해서... 한참을  이것 저것 테스트 헤매다가 어케 어케....


using Google.Apis.Auth.OAuth2;
using Google.Apis.Util.Store;
using Google.Apis.Services;
using Google.Apis.PhotosLibrary.v1;
using Google.Apis.PhotosLibrary.v1.Data;


// 인증

UserCredential credential;

using (var stream = new FileStream("client_secret_oauth.json", FileMode.Open, FileAccess.Read))
{
    credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
        GoogleClientSecrets.Load(stream).Secrets,
        new[] { PhotosLibraryService.Scope.Photoslibrary, PhotosLibraryService.Scope.DrivePhotosReadonly },
        "abcApp",   // 구분값
        CancellationToken.None,
        null).Result;
}

// 앨범 목록

PhotosLibraryService PhotosService = new PhotosLibraryService(new BaseClientService.Initializer()
{
    HttpClientInitializer = credential,
});

var albumsList = PhotosService.Albums.List().Execute();
foreach (var item in albumsList.Albums)
{
    Console.WriteLine("Album title: " + item.Title);
    Console.WriteLine("Album ID: " + item.Id);
}

// 사진 목록

SearchMediaItemsRequest x = new SearchMediaItemsRequest();
x.AlbumId = "AMhW9mr-M9UF3Tpo2";

var mitems = PhotosService.MediaItems.Search(x).Execute();  // 특정 앨범
foreach(var i in mitems.MediaItems)
{
    Console.WriteLine("Id : " +i.Id);
    Console.WriteLine("Filename : " + i.Filename);
    Console.WriteLine("BaseUrl : " + i.BaseUrl);
    Console.WriteLine("ProductUrl : " + i.ProductUrl);
}


2019/08/12

구글 API 인증 At least one client secrets (Installed or Web) should be set 에러


C#, Google.Apis.Blogger.v3 Auth

처리되지 않은 예외: System.InvalidOperationException: At least one client secrets (Installed or Web)
 should be set
   위치: Google.Apis.Auth.OAuth2.GoogleClientSecrets.get_Secrets()


json 인증값이, 구글 API 서비스 인증이 아닌 사용자 oAuth 인증으로 변경 적용해 볼 필요가 있음. (구글 여러 API 중에, 서비스 인증을 지원 안하는 API 인것 때문으로 보임)


2016/06/17

System.Security.Authentication.AuthenticationException: SSPI 예외

처리되지 않은 예외: System.Security.Authentication.AuthenticationException: SSPI를 호출하지 못했습니다. 내부 예외를 참조하십시오. ---> System.ComponentModel.Win32Exception: 예기치 않은 메시지를 받았거나 메시지의 형식이 잘못되었습니다
  --- 내부 예외 스택 추적의 끝 ---
  위치: System.Net.Security.SslState.CheckThrow(Boolean authSucessCheck)
  위치: System.Net.Security.SslState.get_SecureStream()
  위치: System.Net.Security.SslStream.Write(Byte[] buffer)

 

=> 원인은, 서버쪽에 설정된 SSL 관련 암호화 모듈중에, "SSL" 버젼 또는 "Tls" 버젼 일부를 비활성화(또는 제거) 설정되어 있기 때문에 서버쪽에서 허용 가능한 "SslProtocols" 버젼을 설정해서 AuthenticateAsClient 인증을 받아야 함.

보안에 취약한 "SSL" 및 "Tls" 버젼을 제거하는 것이 권장되고 있으며, 설정이 적용된 지원하지 않는 서버들이 증가하고 있다.

참고 :
How to disable PCT 1.0, SSL 2.0, SSL 3.0, or TLS 1.0 in Internet Information Services
https://support.microsoft.com/en-us/kb/187498

 

 => 그러면,.  고정된 서버에 접근하지 않고 익명의 다중 원격 서버에 접근하는 경우, 지원 버젼을 매번 알아낼수가 없다. 그래서 아래와 같은 or 형태로 지정을 해준다.

 

sslStream.AuthenticateAsClient(_host, certcoll,  SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12, false);

 

 


가장 많이 본 글