[원본] A Primer for OpenID with PHP | dev.aol.com
by Jack Herrington
September 21 2007
OpenID는 상당히 멋진 기술이지만 여러분에게는 생소할것입니다. OpenID는 웹을 사용하는 사람들에게 그들의 정보를 한곳에 등록하고 OpenID를 지원하는 어느 사이트에서도 사용가능하게 해주는 오픈소스 프로토콜입니다. OpenID를 사용하게 된다면 방문하려는 사이트마다 아이디와 비밀번호등을 만들고 일일이 기억해야 하는 불편이 사라지게 됩니다. 또한 웹 사이트는 복잡한 사용자 관리 프로세스를 구축 할 필요없이 인증된 사용자를 구분할 수 있게 됩니다. OpenID를 지원하는 서비스들은 계속해서 증가하고 있지만 OpenID가 얼마나 유용하고 멋진 기술인가에 비해서는 더딘 편이라 하겠습니다. 이 글이 OpenID가 널리 보급되는데 도움이 되었으면 합니다.
OpenID의 근간을 이루는 개념은 매우 단순합니다. 웹사용자가 OpenID를 제공하는 사이트에 ID를 등록하면 OpenID를 지원하는 다른 모든 웹사이트들에서 사용할 수 있게 하겠다는 것입니다.

우선 사용자는 OpenID를 제공하는 사이트에 계정을 생성합니다. 이런 사이트에는 Verisign이나 AOL이 있습니다. AOL과 AOL의 메신저(AIM)을 사용하시는분들은 해당 계정을 이미 OpenID로 사용가능 합니다. 자신의 OpenID를 갖게 되었다면 OpenID를 지원하는 다른 웹사이트에 로그인 할 수 있습니다.(역자주, 비단 웹사이트 뿐만아니라 웹상에서 구동되는 작은 어플리케이션에서도 사용가능합니다. OpenID를 제공하는 사이트를 "OpenID provider"라고 하고 OpenID로 로그인할 수 있게끔 지원하는 사이트를 "OpenID consumer web-site", "OpenID consumer web-application"이라고 한다네요. 중요한것은 provider - consumer개념인 듯 합니다.) 즉, 웹 어플리케이션(consumer)은 사용자의 OpenID를 입력받아 OpenID를 제공한 사이트(provider)에게 인증을 요청하게 됩니다.) OpenID를 지원하는 웹 어플리케이션(사이트)를 모아놓은 디렉토리 사이트도 있습니다.
이 글에 나와있는 코드를 보면 알 수 있겠지만 OpenID를 지원하는 일은 아주 쉽습니다. 여러분은 이미 나와있는 라이브러리(추가비용없이 대부분의 언어에 사용가능한 라이브러리가 있습니다.)를 사용하거나 직접 작성할 수도 있습니다. 물론 여러분이 직접 작성하는것이 OpenID 프로토콜을 이해하는데 많은 도움이 되겠지만 연습삼아 해보기로 하고 실질적으로는 배포되는 라이브러리를 사용하는 것이 쉬울겁니다.
OpenID는 이를 지원하는 사이트나 이를 사용하는 사람들 모두에게 큰 이점을 가져다 줍니다. 사용자는 하나의 OpenID를 가지고 많은 서비스를 이용할 수 있습니다. 특히나 여러군데의 사이트를 이용하는 분들은 특정 사이트의 ID와 비밀번호를 잊어버리는 경우가 종종 있기 때문입니다. 사용자들이 OpenID를 사용하기 때문에 OpenID를 지원하는 사이트는 사용자계정을 따로 관리할 필요가 없게되며 OpenID를 사용하는 많은 사용자들을 잠재적인 고객으로 확보 할 수 있습니다.
OpenID를 지원하기 위해서 OpenID를 제공해야하지는 않습니다. 특별한 소프트웨어나 서비스를 필요로 하지도 않습니다. 단지 HTTP 요청을 할수 있는 프로그래밍 언어만 필요할 뿐입니다. (대부분의 웹프로그래밍 언어는 이것이 가능합니다.)
OpenID를 지원하게 끔하기 위해서 우선 OpenID를 얻어야 할 것입니다. 다행히도 공짜로 OpenID를 제공하는 곳이 많이 있습니다. 이 글에서 사용할 OpenID는 pip.verisignlabs.com에서 얻었습니다. signon.com이나 다른 OpenID를 제공하는 사이트에서 얻더라도 무방합니다. OpenID는 실질적으로 URL입니다. 다음의 URL이 이 글에서 사용할 OpenID입니다.
이 URL은 실제로도 동작합니다. 여타 다른 URL처럼 HTML페이지가 들어있습니다. 이 HTML안에는 OpenID를 제공한 사이트에 대한 링크가 들어있으며 그 링크를 따라가게되면 사용자정보를 확인할 수 있습니다.
UNIX를 사용중이라면 cURL을 이용하여 OpenID URL의 HTML을 볼 수 있을것이고 브라우저를 통해서 소스보기로 HTML을 확인 할 수 있을 것입니다. 아래는 cURL을 이용하여 출력한 결과입니다.
중요한 부분은 rel속성에 openid.server값을 가지고있는 <link>태그입니다. 이것은 OpenID를 지원하는 사이트로 하여금 OpenID의 인증을 수행할 수 있는 (OpenID를 제공한 사이트의)주소를 알 수 있게 합니다.
여기에서 살펴봐야할 두가지 중요한 점은
(역 자주, 만약 당신이 일반 사용자이고 당신의 블로그 주소를 OpenID로 사용하고 싶다면 당신의 블로그에 위와 같은 <link>태그를 집어넣으면 됩니다. 예를들어 http://blog.naver.com/username 에 위와같은 <link>태그를 넣어두면 당신의 블로그 주소는 그대로 OpenID가 됩니다. 물론 href에 들어갈 'OpenID를 제공한 사이트'의 주소는 다를것입니다.)
이제까지 OpenID를 사용하는 일반사용자의 입장에서 살펴본 핵심개념들입니다. 이제 좀더 자세히 이해하기 위해서 OpenID를 지원하는 사이트는 어떻게 구축하는지, OpenID를 제공하는 사이트는 어떻게 만드는지 살펴보겠습니다.
다음은 PHP로 구축된, OpenID를 지원하는 사이트의 흐름도 입니다.

왼쪽에서 오른쪽으로 가는 화살표는 사용자가 경험하게 되는 페이지들의 흐름입니다. 아래쪽의 구름모양은 사용자 모르게 처리하는 것들입니다.
왼쪽 끝에 있는 Index.php는 사용자가 처음 접하는 로그인페이지입니다. 여기에는 OpenID를 입력할 수 있는 텍스트 필드가 있고 사용자가 Submit을 클릭하면 Forword.php로 이동하게 됩니다. Forward.php와 Complete.php는 점선으로 그려져있는데 사용자에게 실질적으로는 보이지 않는다는 의미입니다. (역자주, redirect시키는 페이지 이므로 브라우저에 표시할 내용이 없습니다.)
Forward.php는 사용자가 입력한 OpenID URL로 cURL을 이용하여 openid.server의 URL을 찾아냅니다. 결국 OpenID를 제공한 사이트의 URL에 OpenID와 추가적인 파라미터를 함께 보내줍니다.
사용자는 OpenID를 제공한 사이트로 이동하게 되고 비밀번호나 혈액샘플, 망막스캔등 어떠한 방식으로든 로그인하게 됩니다. 다음으로 OpenID를 제공한 사이트는 사용자가 방문한 원래의 사이트--여기서는 Complete.php의 URL이 해당됩니다--로 OpenID를 되돌려 줍니다. 이때 몇몇 추가적인 파라미터도 함께 보내줍니다.
Complete.php는 되돌아온 OpenID가 정확하게 인증된것인지 또는 다른 스푸핑 사이트에서 온것이 아닌지 OpenID를 제공한 사이트에 cURL을 이용하여 확인작업을 합니다. 확인이 완료되면 이제 사용자는 방문한 사이트에 "로그인" 되었으며 사이트가 제공하는 서비스를 "로그인"된 사용자로서 이용할 수 있게 됩니다.
Complete.php에서는 OpenID를 제공한 사이트로 부터의 응답을 재차 확인하지 않아도 됩니다. 처음에 사용자를 OpenID를 제공한 사이트로 포워딩 시킬 때 비밀키를 함께 보내고 되돌아온 응답에대한 서명을 체크할 수 있습니다. 그러나 이 글에서는 이해하기 쉽도록 이부분에 대한 언급은 하지 않겠습니다.
복잡하고 어렵게 보이겠지만 사실은 그렇지 않습니다. OpenID를 이용한 로그인 과정을 브라우저를 통해서 살펴보겠습니다.

아주 간단합니다. OpenID를 입력할 수 있는 텍스트 필드와 Submit버튼 뿐입니다. PHP가 아니더라도 상관 없습니다.
Submit버튼을 클릭하면 Forward.php로 이동하게 됩니다.

사용자는 일반적으로 이 페이지를 볼 수 없습니다. PHP에서 바로 OpenID를 제공한 사이트로 포워딩 시켜버리면 되기 때문입니다. 그러나 이 글에서는 어느 URL로 보내지는지 직접 확인해 보기위해서 출력했을 뿐입니다.
OpenID를 제공한 사이트로 이동하는 URL의 파라미터를 살펴봅시다. openid.identity는 사용자가 입력한 OpenID입니다. openid.mode=checkid_setup은 요청한 OpenID가 맞는지 확인하고 로그인을 시도할 것을 의미합니다. openid.return_to는 성공적으로 로그인이 되었을때 되돌아올 URL입니다.
사용자가 OpenID를 제공한 사이트로 성공적으로 포워딩 되었다고 가정했을때 그 다음은 OpenID를 제공한 사이트에 있는 페이지입니다.

여기서는 로그인한 세션을 얼마나 지속시킬것인지 등을 설정 할 수 있습니다. (역자주, 비밀번호를 입력한다던가 하는 부분이 화면상에서는 보이지 않는듯 합니다.) 이 예제에서는 그다지 중요하지 않습니다. OK를 클릭하게 되면 사용자는 원래 방문한 사이트의 Complete.php로 보내집니다.

성공적으로 로그인 되었음을 보여주는 이 페이지는 언뜻보기엔 상당히 간단해 보입니다. 그러나 실제로는 스푸핑 되지 않았음을 확인하기 위해서 OpenID를 제공한 사이트에 "인증"모드로 마지막으로 한번더 다녀왔습니다.
이제 좀더 상세하게 페이지들의 흐름을 실제로 동작하는 PHP코드를 통해서 사용자에게 어떻게 보여지는지 살펴보겠습니다.
처음은 로그인 페이지부터 시작합니다.
Index.php는 표준 HTML페이지로 하나의 텍스트 필드와 Submit버튼을 가지며 Forward.php로 데이타를 보내주는 폼으로 이루어져 있습니다. 다음은 Forward.php입니다.
이번엔 조금 복잡해 보입니다. 사용자가 입력한 OpenID URL에 해당하는 HTML을 가져오기 위해서 PHP에 내장되어있는 cURL라이브러리를 사용했습니다. 가져온 HTML로부터 정규식을 이용하여 openid.server에 해당하는 값을 추출해 냅니다.
OpenID를 제공한 사이트의 URL으로 checkid_setup하기위해서 추가적인 파라미터를 포함하여 사용자를 포워딩 시킵니다. 여기서는 URL을 직접확인하기 위해서 링크로 보여주었지만 실제로는 Response Header의 Location값으로 $url을 보냅니다.
마지막으로 OpenID를 제공한 사이트에서 사용자가 성공적으로 로그인 되었을 때 추가적인 파라미터와 함께 되돌아 오게 되는 Complete.php입니다.
소스코드의 위쪽부분은 Forward.php와 유사합니다. 사용자의 OpenID로부터 OpenID를 제공한 사이트의 URL을 알아낸 다음 openid.mode=authenticate를 포함하여 OpenID 규약에 명시된 다른 파라미터와 함께 URL을 생성합니다.
생성한 URL은 cURL을 이용하여 OpenID를 제공한 사이트로부터 인증 결과를 가져오는데 사용됩니다. 결과는 $ca_resp에 저장됩니다. 결과에 is_valid:true가 있다면 우리는 이 Complete.php가 OpenID를 제공한 사이트로부터 불려졌음을 확인한 것이며 이 OpenID가 인증되었음을 알 수 있습니다.
이제 우리가 만든 OpenID를 지원하는 예제 사이트는 이 OpenID를 세션변수에 저장해 두고 사용할 수 있습니다.
이것으로 우리는 OpenID 식의 "hello word" 예제를 살펴보았습니다. 이 예제를 실제로 사용하는데에는 무리가 있을 것입니다. 정규식을 너무 제한적으로 만들었고 에러체크 등을 하지 않았습니다. 그러나 중요한 것은 간단하게나마 OpenID가 작동하는 방식을 살펴보고 어떤것이 OpenID를 지원하는 사이트에서 하는일이고 OpenID를 제공하는 사이트에서 하는일인지 알게되는 것입니다. OpenID의 정의에 대해 대충으로라도 알게 되었을 것입니다.
현업에서는 OpenID를 제공하거나 지원하기 위해서는 여러분 스스로가 선택한 언어로 작성된 OpenID라이브러리를 사용하게 될것입니다. 이 글의 나머지부분에서는 이에대해 이야기 할까 합니다.
다음으로 넘어가기 전에 몇가지 요약해 봅시다.
이제 PHP로 구현된 라이브러리를 살펴봅시다.
PHP로 된 몇가지 OpenID 라이브러리가 있습니다만 여기서는 JanRain에서 나온 라이브러리를 살펴보겠습니다. OpenID Enabled site에 링크되어있습니다. 최신버전을 다운로드 하여 Apache서버의 Document디렉토리에 복사합니다. (역자주, 글쓴이가 사용한 라이브러리의 정확한 버전을 알 수 없었습니다. 최신버전과는 경로나 파일명이 다를 수 있습니다.)
다음으로 README파일에 나와있는데로 Examples/detect.php를 실행시킵니다. 저의 Mac OS X에는 PHP5가 설치되어있습니다. cURL라이브러리를 사용하는데 필요한 GMP, BCMath나 PEAR DB함께 설치되어야 할 수 있습니다. 또한 XML을 처리할 수 있는 XML_DOM라이브러리도 필요합니다. README파일에 모두 명시되어있고 detect.php를 실행시켜보면 알 수 있습니다.
README파일에는 이 OpenID라이브러리를 PEAR모듈의 형태로 설치하는것에 대해 언급하고 있지만 굳이 그렇게 하지 않아도 됩니다. 제일먼저 해야할 것은 examples/consumer/index.php를 열어보는 것입니다.

OpenID를 입력하면 OpenID를 제공한 사이트로 이동하게되고 로그인을 합니다. 그후엔 다시 예제로 돌아오게됩니다.

OpenID로 로그인되었을 뿐만아니라 e-mail주소와 성명, 닉네임등도 받아왔습니다. 잘 되는군요!
소스코드를 조금만 살펴본다면 이 라이브러리를 이용하여 OpenID를 지원하는 사이트를 만들 수 있을 것입니다. 사실 이 라이브러리가 위에서 우리가 작성한 코드와 비교해서 별 차이가 없어 보이지만 좀더 안정적이고 많은 에러상황에 대처할수 있는 코드들이 포함된 훌륭한 라이브러리 입니다.
이제 마지막으로 OpenID PHP라이브러리를 이용하여 OpenID를 제공하는 사이트에 대해 살펴봅시다.
OpenID를 제공하는 사이트를 구축하기 위해서 제일 처음 해야하는 설정화면입니다. 사용자 정보를 저장하기 위해서 파일시스템을 사용하거나 SQL서버를 사용할 수 있습니다. Setup.php가 설정페이지입니다.

설정을 끝냈다면 Config.php에 사용할 수 있는 소스코드가 출력됩니다.

After that you take the contents of this page and copy them into Config.php in the examples/server directory. From there you go to Server.php, which gives you some of the basic details of the provider. Most importantly, what to use as the <link> in your own pages to have this provider support your OpenIDs.
출력된 소스코드를 복사하여 examples/server/Config.php에 붙여넣기 합니다.

From here I can build my own OpenID with this provider by adding /userpage/user=<username> to the end of the provider URL. This returns an identity page.

That’s the same kind of identity page that other services, like the Verisign one that I used at the start of this article, return for OpenID services. This page is shown as HTML in Listing 4.
Because I’ve installed this on localhost the OpenID provider that I installed isn’t going to do much good on the Web. From here I need to install this on my Web site, get it hooked into my database, and use it from there.
The consumer and provider examples provided here serve only as templates on which you can base your own work. You could, for example, use the OpenID consumer example to add the ability to log in using an OpenID URL as an account to your online services. Or you could use the provider example to provide OpenIDs to all of the users on your service for free.
비록 이 글에서 OpenID가 무엇이고 어떠한 것들을 할 수 있는지 이야기 했지만 모든 형태의 웹사이트에 적용하는것은 추천하지 않습니다. 특별한 규칙 없이는 은행권과 같은 사용자정보와 인증에 민감한 사이트에는 적합하지 않습니다. 따라서 전자상거래나 금융권 사이트에는 적용하지 않는것이 좋을 것입니다. 그러나 웹 상에는 그렇지 않은 사이트가 훨씬 더 많습니다.
OpenID directory에는 OpenID를 적용한 블로그나 토론게시판, 사람들끼리 어울리기위한 사이트, 위키나 심지어 지역모임을 위한 것들까지 수많은 사이트들이 목록화 되어 있습니다. 웹은 본질적으로 많은 사용자를 기반으로 하고있습니다. 각각의 사용자를 구분하고 각 사용자의 연속성을 보장해주어야 합니다. 특정 형태의 사이트에서는 이러한 사용자 인증이 강력하게 필요한 경우가 있지만 대부분은 그렇지 않습니다.FaceBook과 Wells Fargo을 비교해본다면 아실 수 있을겁니다. (역자주, me2DAY와 국민은행을 비교해본다면?)
OpenID에 대해 좀더 알고싶으신분은 OpenID.net을 방문해 보세요. OpenID에 대한 소개와 OpenID 규약, OpenID를 지원하는 사이트 및 OpenID를 제공하는 사이트를 만들기 위한 여러 프로그래밍언어로 작성된 라이브러리 목록을 제공합니다. 또한 OpenID 프로토콜이 어떻게 작동하는지 사용자 인증을 위해서 HTTP request를 어떻게 사용하면 되는지 단계별로 설명하고 있는 OpenID book을 온라인으로 볼 수 있습니다.
OpenID는 여러 회사나 웹사이트, 조직들 에게 많은 가능성을 가져다 줄 수 있는 사용자 인증 프레임워크 입니다. 좋은 예로 AOL은 OpenID를 지원하기 위해서 Open Authentication API (OpenAuth)서비스를 구축하였습니다. OpenID를 지원하는 가장 손쉬운 방법중에 하나는 AOL이 제공하는 OpenAuth를 사용하는 것입니다. 그러면 AIM과 AOL사용자들을 함께 흡수 할 수 있을 것입니다. 마지막으로 하고싶은 말은 OpenID의 전망은 아주 밝다는 것입니다. OpenID는 웹 서비스를 보다 쉽게 할것이고 이는 사이트와 사용자 모두에게 이득이 될것입니다.