Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 4개 있습니다.)
(시리즈 글이 7개 있습니다.)
.NET Framework: 193. 페이스북(Facebook) 계정으로 로그인하는 C# 웹 사이트 제작
; https://www.sysnet.pe.kr/2/0/953

.NET Framework: 198. 윈도우 응용 프로그램에 Facebook 로그인 연동
; https://www.sysnet.pe.kr/2/0/970

.NET Framework: 245. ASP.NET 서버 측 코드에서 페이스북 계정 연동하는 방법
; https://www.sysnet.pe.kr/2/0/1143

개발 환경 구성: 313. Nuget Facebook 라이브러리를 이용해 ASP.NET 웹 폼과 로그인 연동하는 방법
; https://www.sysnet.pe.kr/2/0/11182

개발 환경 구성: 436. 페이스북 HTTPS 인증을 localhost에서 테스트하는 방법
; https://www.sysnet.pe.kr/2/0/11855

개발 환경 구성: 482. Facebook OAuth 처리 시 상태 정보 전달 방법과 "유효한 OAuth 리디렉션 URI" 설정 규칙
; https://www.sysnet.pe.kr/2/0/12189

닷넷: 2201. C# - Facebook 연동 / 사용자 탈퇴 처리 방법
; https://www.sysnet.pe.kr/2/0/13526




페이스북(Facebook) 계정으로 로그인하는 C# 웹 사이트 제작

트위터 계정 연동을 알아보았는데요.

트위터 계정으로 로그인하는 C# 웹 사이트 제작
; https://www.sysnet.pe.kr/2/0/948

기왕 하는 거 ^^ 페이스북도 알아봐야 하지 않을까요?
어차피 모두 OAuth 인증 방식을 도입했기 때문에 접근 방법도 비슷해서 부담이 적습니다.




지난 번처럼, 우선 .NET 용 라이브러리를 찾아야 할텐데요. 오픈 소스로 되어 있는 다음의 라이브러리가 Facebook에 의해서 링크되어 있습니다.

C# SDK for Facebook Platform 
; https://github.com/facebook/csharp-sdk

소스 코드로만 공개되어 있기 때문에 번거롭지만 다운로드 받아서 빌드를 직접 해줘야 합니다. (FacebookAPI.dll)

그다음, 트위터와 마찬가지로 페이스북 역시 여러분들의 응용 프로그램을 등록해 줘야 합니다. 검색을 해보니, 아래의 사이트에서 잘 설명을 해주고 있습니다. ^^

SNS - 페이스북에 어플리케이션 올리기
; http://sherlockpj.blog.me/70091818802

위에서 일러준데로, http://www.facebook.com/developers 링크로 이동해서 로그인을 하고, 아래의 허가 요청에 대해서 허용을 합니다. (특이하게도, 페이스북 내부의 개발자 설정 역시도 페이스북의 '외부 응용 프로그램'처럼 대우를 하는군요.)

integrate_facebook_auth_1.png

다음으로, "새 어플리케이션 설정" 버튼을 누르고,

integrate_facebook_auth_2.png

응용 프로그램 이름을 입력하고, 생성!

integrate_facebook_auth_3.png

이후의 과정은 각자 응용 프로그램 상황에 맞게 설정하고 확인을 누르면 완료.




트위터의 경우에 "Consumer Key"와 "CustomerSecret"를 얻을 수 있었던 것처럼, 페이스북에서도 비슷한 값들을 "Application ID"와 "Application Secret"으로 제공하고 있습니다.

하지만, 인증 서비스에 있어 페이스북이 좀 더 다양한 기능들을 제공해 주고 있는데요. 개인적으로 마음에 드는 것이 SSO(Single-Sign-on) 기능과 "Deauthorize URL" 등록 기능입니다.

우선, ASP.NET에서의 SSO 구현은 다음의 웹 사이트에서 자세히 설명하고 있습니다.

Facebook Platform's OAuth 2.0 Protocol and ASP.NET MVC
; http://amirrajan.net/Blog/asp-mvc-and-facebook-single-sign-on

위와 같이 서버 측에서 제어하는 것도 가능한데요. 페이스북은 클라이언트의 JavaScript에서도 SSO 인증이 되도록 하는 js 파일을 공개해 주고 있습니다. 이에 대해서는 다음의 글에서 "Single Sign-on" 부분을 참고하실 수 있습니다.

Facebook for Websites
- Single Sign-on
; http://developers.facebook.com/docs/guides/web

위의 글에서 설명된 것처럼 SSO 구현은 여러분들의 웹 사이트에 다음과 같은 HTML 및 Javascript 링크와 코드를 추가해 주는 것으로 간단하게 적용될 수 있습니다.

<div id="fb-root"></div>
<script src="http://connect.facebook.net/en_US/all.js"></script>
<script>
  FB.init({appId: '[응용 프로그램 등록 시 받는 Application ID]', status: true, cookie: true, xfbml: true});
  FB.Event.subscribe('auth.sessionChange', function(response) {
    if (response.session) 
    {
        // 로그인 상태로 판정될 때 실행되는 코드
    } else {
        // 로그아웃 상태로 판정될 때 실행되는 코드
    }
  });
</script>

<fb:login-button></fb:login-button> <!-- 로그인 버튼 이미지 -->


<fb:login-button />으로 표시되는 로그인 버튼 이미지를 사용자가 클릭하면 페이스북 측에서 제공하는 로그인 화면이 팝업창으로 뜨고 사용자는 페이스북 로그인 하듯이 사용자 정보를 입력합니다. 물론, 웹 사이트 측에는 트위터에서 그랬던 것처럼 사용자 계정에 대해서는 어떠한 정보도 알려주지 않고 access_token 값 만을 넘겨주게 됩니다.

FB.init / FB.Event.subscribe의 자바스크립트 역할은 간단합니다. 만약, 사용자가 Facebook 로그인에 대해서 "로그인 상태 유지(Remember Me)"를 체크해 놓고 로그인 한 적이 있다면, 위의 자바 스크립트 함수를 포함하는 웹 사이트를 방문하면 초기 FB... 메서드 실행 시에 페이스북 사이트로부터 정보를 조회해서 로그인 처리를 하게 됩니다. 반대로, 현재 로그인 해서 사용하고 있는 웹 사이트와는 별개의 창으로 떠 있는 웹 브라우저에서 방문중인 페이스북에서 로그아웃을 하는 경우에도, 위의 자바스크립트가 실행되면 '로그 아웃' 부분에 해당하는 자바 스크립트 코드가 실행될 수 있습니다.

인증처리를 서버측에서 하느냐, 자바스크립트로 하느냐에 대해서는 장단점이 있습니다. 자바스크립트를 활용하게 되면 서버 측에서 지저분하게 인증 관련 코드를 넣을 필요가 없어서 좋긴 하지만 대부분의 경우 다시 화면을 refresh 해주는 코드를 자바스크립트에 넣어주어서 화면 깜빡임이 발생하게 됩니다.

SSO를 조금이라도 아시는 분들이라면, 그 방법이 쿠키임을 짐작하실 테고, 그렇다면 쿠키가 적용되는 도메인 영역이 지정되어야 할 텐데, 페이스북은 어떻게 이를 판단할까요? 네... 이 부분은 응용 프로그램 등록화면에서 쿠키가 적용될 도메인 영역을 다음과 같이 미리 지정해 주었어야 합니다.

integrate_facebook_auth_4.png

로그인 된 경우, 지정된 도메인 영역으로 다음과 같은 쿠키 설정이 추가됩니다.

fbs_[AppId]="access_token=[AppId]...&base_domain=[사이트 도메인]&expires=...[인증유효기간]...&secret=....&session_key=....&sig=....&uid=...";


페이스북 로그인 연동이 적용된 제 웹 사이트의 경우에 풀어보면 다음과 같습니다.

fbs_[AppId]="...[이하 아래의 값들이 개행문자 없이 나열됨]..."

access_token: ...[생략]...
base_domain: www.sysnet.pe.kr
expires: 1290085200
secret: ...[생략]...
session_key: ...[생략]...
sig: ...[생략]...
uid: ...[생략]...
name : SeongTae Jeong
email: ...[생략]...
website: https://www.sysnet.pe.kr

위의 정보에서 중요한 것은 "access_token" 값입니다. 그 값을 기반으로 이전에 빌드해 둔, FacebookAPI.dll을 이용하여 페이스북 웹 사이트로부터 제공되는 다양한 API를 접근하게 되는데, 이와 관련해서 자세한 개발 관련 정보는 아래의 웹 페이지에서 찾아볼 수 있습니다.

Graph API Overview
; http://developers.facebook.com/docs/api

Graph API Reference
; http://developers.facebook.com/docs/reference/api/

예를 들어, "사용자" 정보를 조회하고 싶다면, "Graph API Reference"에서 살펴보고 http://developers.facebook.com/docs/reference/api/user에서 설명되고 있는 것임을 인식하고, 그 페이지에 제시된 쿼리 URL을 아래와 같이 찾을 수 있습니다.

User
A user profile. This object supports Real-Time Updates for all properties except the verified property.

예
https://graph.facebook.com/me (current user) 

도메인 까지의 쿼리 주소는 FacebookAPI에서 붙여주기 때문에 뒤의 "/me"만 붙여서 다음과 같이 조회를 해 올 수 있습니다.

Facebook.FacebookAPI api = new Facebook.FacebookAPI(...[쿠키에서 구해온 access_token 값]...);
Facebook.JSONObject me = api.Get("/me");

그런 후, 반환되는 것은 해당 명세서에 보이는 것 처럼 id, first_name,... 등등의 값을 다음과 같이 조회해 올 수 있습니다.

string userName = me.Dictionary["first_name"].String;
string userId = me.Dictionary["id"].String;

여기까지 기본적인 인증 방법 및 사용법 설명은 끝입니다.




부가적으로, 더 설명드려야 하는 것이 있다면 "사용자 정보" 조회 등에 대해서 일부 정보는 반드시 사용자로부터의 허락을 받아야만 가져올 수 있다는 점입니다. (이 부분에 대해서는 페이스북 개발자에게 정말 박수를 쳐주고 싶습니다. ^^)

예를 들면, 위의 api.Get("/me"); 코드를 통해서 사용자 정보를 조회할 때 email을 조회하면 빈 문자열이 반환되는 것을 확인할 수 있습니다. 왜냐하면, email 정보는 "사용자"가 해당 응용 프로그램이 조회해도 좋다는 허락을 해줘야 하기 때문입니다.

이에 대해서는 "http://developers.facebook.com/docs/reference/api/user"에서도 다음과 같이 명시되어 있습니다.

email : Requires email permission

만약, 여러분들의 웹 애플리케이션(또는 응용 프로그램)에서 사용자의 이메일 정보가 필요하다면 명시적으로 요청을 해야 합니다. 위에서 설명한 "<fb:login-button />" 버튼을 이용한 경우 다음과 같이 간단하게 처리가 됩니다.

<fb:login-button perms="...[요구되는 정보를 위한 권한 문자열]..."></fb:login-button>

제 웹 사이트의 경우 사용자 정보에서 "email"과 "user_website" 정보 2가지를 요구하기 때문에 다음과 같이 설정되어 있고,

<fb:login-button perms="email,user_website"></fb:login-button>

사용자는 최초 페이스북 로그인 시에 다음과 같이 확인을 받게 됩니다.

integrate_facebook_auth_5.png




더욱 훌륭한 것은, 이메일 정보의 보호입니다. 사실, 자신이 사용하려는 웹 사이트가 이메일 정보를 요구한다면 "줄 수밖에 없는 상황"이 되어버리는 데요. (누군들, 사이트 약관을 읽어보고 정보 제공에 동의하고 싶겠습니까?) 페이스북은 이메일 주소를 외부적으로 노출되는 전용 이메일 계정을 별도로 제공해주는 데요. 이름하여 "proxied email"입니다. (사용자는 페이스북의 계정 정보 설정에서 이런 경우 "proxied email" 주소를 제공할 것인지, 실제 이메일 주소를 제공할 것인지를 선택할 수가 잇습니다.)

그래서, 페이스북 이외의 다른 응용 프로그램들은 원래의 사용자 이메일 정보를 알 수는 없고 페이스북에서 중계해주는 "proxied email" 주소만을 알 수 있습니다. 이에 대해서는 다음의 글에서 자세히 설명해 주고 있으니 참고하세요. ^^

Facebook App Notifications Moving to Your E-mail Inbox
; http://mashable.com/2010/01/20/facebook-applications-email/

사용자 정보 보호에 이런 세심함을 보여주는 웹 사이트를 보고 있노라니... 오히려 사용자 정보를 팔아먹는 못된 사이트들과 비교가 되는군요. ^^;




대부분의 외부 웹 응용 프로그램에서 취하는 형태가 바로 "페이스북 연동"일 것입니다. 기존 웹 애플리케이션 계정 정책에 페이스북 계정을 연동하기 위해서는 쿠키로부터 uid 값을 취해서 현재 "외부 웹 응용 프로그램"에 로그인한 사용자 계정과 연관지어 보관해 두어야 합니다.

access_token: ...[생략]...
base_domain: www.sysnet.pe.kr
expires: 1290085200
secret: ...[생략]...
session_key: ...[생략]...
sig: ...[생략]...
uid: 10302394932804
name : SeongTae Jeong
email: ...[생략]...
website: https://www.sysnet.pe.kr

이렇게 되면, 나중에는 페이스북 계정연동으로 인한 DB 자료들이 늘어나게 될 텐데요. 재미있는 점은, 사용자는 언제든지 아래에서 보는 것처럼 페이스북 웹 사이트로부터 여러분들의 웹 사이트와의 연동을 해제할 수 있다는 것입니다.

integrate_facebook_auth_6.png

따라서 이런 상황이 되면 웹 사이트 DB 에는 더 이상 쓸모없는 페이스북 관련 연동 정보가 쌓여만 가는 상황이 되는 것입니다.

정상적이라면, 이런 경우 페이스북 측에서 "어플리케이션 제거" 링크를 사용자가 누를 때 해당 웹 사이트에 통지를 해주면 좋을 텐데요. 바로 이 기능을 위해서 응용 프로그램 설정 화면에서 "Deauthorize URL" 입력란이 있는 것입니다.

integrate_facebook_auth_7.png

위에서는 "/user/removeuser.aspx" 웹 페이지를 부르도록 하고 있는데요. 페이스북은 사용자가 "어플리케이션 제거" 링크를 누르면 "removeuser.aspx" 호출 시에 POST 데이터에 여러 가지 정보를 넣어주는 데 이 중에서 "fb_sig_user" 값이 인증 시에 쿠키에 담겨 있던 "uid" 값이 되므로 사용자 정보를 DB에서 정상적으로 제거해 줄 수 있게 됩니다. 대략 다음과 같은 서버 측 코드를 구성해주면 됩니다.

public partial class removeuser : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        string userId = Request.Form["fb_sig_user"];

        if (string.IsNullOrEmpty(userId) == false)
        {
            ...[DB에서 제거]...
        }
    }
}

물론... 하필 사용자가 "어플리케이션 제거"를 할 때 여러분들의 웹 서버가 멈춰있다면... 어쩔 수 없겠군요. ^^



[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 6/28/2023]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2010-12-14 02시40분
[ㅠㅠ] 인증해제콜백 주소는 어플리케이션 사용자가 어플리케이션을 제거했을때 저 주소로 콜백 해주는 거죠?
저는 설정을 해놓았는데 해당 주소로 콜이 오지 않네요...
잘 되고 계시나요?
[guest]
2010-12-14 03시23분
저게... 테스트하기가 은근히 귀찮아서 지금 당장 해보기는 좀 그렇군요. ^^ 위의 글을 쓸 당시에는 잘 되었습니다. 2번 정도 정상적으로 테스트해서 호출되는 것을 확인했습니다. 직접 제 사이트에 테스트를 해보시겠어요? 여기서 로그인한 다음에 페이스북에서 해제하시고요. 저에게 ID 알려주시면 제 DB에서 삭제가 되었는지 말씀해드리겠습니다. ^^
정성태
2012-08-23 01시48분
[guest] 질문있습니다.
어떤 목적의 사이트에 접속하면 처음에 자동으로 페이스북 로그인 화면으로 뜨도록은 했습니다.
이제 거기서 페이스북에 로그인을 정상적으로 하게 되면 어떤 인증값을 받아서 처음 목적의 사이트에 로그인이 된 상태로 뜨도록 해야 합니다.
어떻게 해야 하나요? jsp로 구현을 해야 합니다. 도와주세요. 부탁드립니다.
[guest]
2012-08-23 04시22분
글쎄요. 뭐라고 더 설명드려야 할지 모르겠군요. 위의 내용을 읽어보시면 그에 대한 내용이 나옵니다. 본문에서 기능 구현을 클라이언트 측 javascript로 했기 때문에 jsp나 asp.net 상관없이 적용할 수 있습니다.
정성태
2013-05-21 06시12분
정성태

[1]  2  3  4  5  6  7  8  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
13838정성태12/4/2024632오류 유형: 935. Windbg - Breakpoint 0's offset expression evaluation failed.
13837정성태12/3/2024699디버깅 기술: 204. Windbg - 윈도우 핸들 테이블 (3) - Windows 10 이상인 경우
13836정성태12/3/2024922디버깅 기술: 203. Windbg - x64 가상 주소를 물리 주소로 변환 (페이지 크기가 2MB인 경우)
13835정성태12/2/2024985오류 유형: 934. Azure - rm: cannot remove '...': Directory not empty
13834정성태11/29/20241073Windows: 275. C# - CUI 애플리케이션과 Console 윈도우 (Windows 10 미만의 Classic Console 모드인 경우)파일 다운로드1
13833정성태11/29/20241077개발 환경 구성: 737. Azure Web App에서 Scale-out으로 늘어난 리눅스 인스턴스에 SSH 접속하는 방법
13832정성태11/27/20241110Windows: 274. Windows 7부터 도입한 conhost.exe
13831정성태11/27/2024977Linux: 111. eBPF - BPF_MAP_TYPE_PERF_EVENT_ARRAY, BPF_MAP_TYPE_RINGBUF에 대한 다양한 용어들
13830정성태11/25/20241069개발 환경 구성: 736. 파이썬 웹 앱을 Azure App Service에 배포하기
13829정성태11/25/20241026스크립트: 67. 파이썬 - Windows 버전에서 함께 설치되는 py.exe
13828정성태11/25/20241047개발 환경 구성: 735. Azure - 압축 파일을 이용한 web app 배포 시 디렉터리 구분이 안 되는 문제파일 다운로드1
13827정성태11/25/20241117Windows: 273. Windows 환경의 파일 압축 방법 (tar, Compress-Archive)
13826정성태11/21/20241174닷넷: 2313. C# - (비밀번호 등의) Console로부터 입력받을 때 문자열 출력 숨기기(echo 끄기)파일 다운로드1
13825정성태11/21/20241144Linux: 110. eBPF / bpf2go - BPF_RINGBUF_OUTPUT / BPF_MAP_TYPE_RINGBUF 사용법
13824정성태11/20/20241083Linux: 109. eBPF / bpf2go - BPF_PERF_OUTPUT / BPF_MAP_TYPE_PERF_EVENT_ARRAY 사용법
13823정성태11/20/20241084개발 환경 구성: 734. Ubuntu에 docker, kubernetes (k3s) 설치
13822정성태11/20/20241044개발 환경 구성: 733. Windbg - VirtualBox VM의 커널 디버거 연결 시 COM 포트가 없는 경우
13821정성태11/18/20241170Linux: 108. Linux와 Windows의 프로세스/스레드 ID 관리 방식
13820정성태11/18/20241127VS.NET IDE: 195. Visual C++ - C# 프로젝트처럼 CopyToOutputDirectory 항목을 추가하는 방법
13819정성태11/15/20241122Linux: 107. eBPF - libbpf CO-RE의 CONFIG_DEBUG_INFO_BTF 빌드 여부에 대한 의존성
13818정성태11/15/20241215Windows: 272. Windows 11 24H2 - sudo 추가
13817정성태11/14/20241100Linux: 106. eBPF / bpf2go - (BPF_MAP_TYPE_HASH) Map을 이용한 전역 변수 구현
13816정성태11/14/20241157닷넷: 2312. C#, C++ - Windows / Linux 환경의 Thread Name 설정파일 다운로드1
13815정성태11/13/20241100Linux: 105. eBPF - bpf2go에서 전역 변수 설정 방법
13814정성태11/13/20241214닷넷: 2311. C# - Windows / Linux 환경에서 Native Thread ID 가져오기파일 다운로드1
[1]  2  3  4  5  6  7  8  9  10  11  12  13  14  15  ...