구글 맵만 표시하고, 사용자가 원하는 위치를 확인하려면, 터치 좌표를 확인하는 것이 필 수 인데요. 그것을 사용하려면, 구글 맵 공식 문서의 events 페이지를 보면 됩니다. 설명과 시각적인 표시가 잘되어 배우기 쉽지만, 모든 이벤트가 들어 있어 필요한 부분만 골라써야 합니다. 어렵지는 않습니다. 일단 구글 맵 표시 부분을 먼저 보시고 숙지하시는 것이 좋을 것 같습니다. 그래야, 필요한 코드가 어떤 것인지 쉽게 확인할 수 있습니다.

 

[공식문서]

Google Mpas Platform Map > javascript Overview : https://developers.google.com/maps/documentation/javascript/tutorial .
Google Mpas Platform Map > javascript Events : https://developers.google.com/maps/documentation/javascript/events .
Google Mpas Platform Map > javascript Reverse Geocoding : https://developers.google.com/maps/documentation/javascript/examples/geocoding-reverse .

 

[선행작업]

구글 지도 표시 : https://nicgoon.tistory.com/240 .

 

 

1. 사용 이벤트들 확인하기.

Event 공식 문서를 보면, 발생하는 이벤트를 시각적으로 표시해 주는 뷰가 하나 있습니다. 여기서 확인해 원하는 이벤트를 받아 주면 되겠습니다.

 

2. 클릭 이벤트 적용.

클릭 이벤트 리스너를 사용하면 됩니다. 처음 맵이 생성되면 콜백을 받는 메소드가 있습니다. 공식문서에는 initMap() 메소드인데, api키와 함께 지정할 수 있는데, 굳이 바꿀필요가 없어 대체로 저 이름으로 되어 있을 것 입니다. 이 속에 아래와 같이 이벤트를 걸어 주면됩니다.

  map.addListener('click', function(e) {
	// 여기에 맵의 클릭 이벤트를 넣어 줍니다.
  });

 

위경도 좌표는 다음 과 같이 볼 수 있습니다.

map.addListener('click', function(e) {

  console.log( e.latLng );

});

 

 

3. 받은 위경도 좌표를 우리가 인식할 수 있는 주소로 변환하기.

가이드를 이용해 만들 수 있고, 구글에서는 이 상황에 대비해 샘플로 공개 해 두었습니다. 위에 걸어 놓은 공식 문서 Google Mpas Platform Map > javascript Reverse Geocoding 의 내용을 보시면 되겠습니다.

 

먼저 geo 코드를 가지고 옵니다.

var geocoder = new google.maps.Geocoder;

 

그리고, 받은 위경도 좌표를 다음과 같이 요청할 수 있는 데이터로 변경합니다.

var latlng = {
  lat: e.latLng.lat(),
  lng: e.latLng.lng()
};

 

그리고, 주소는 다음과 같이 확이할 수 있습니다.

geocoder.geocode({'location': latlng}, function(results, status) {

  if( status === "OK" )
  {
    // console.log( results );
    alert( JSON.stringify( results ) );
  }else{
    alert("주소를 못 가지고 왔습니다. 사람 사는 곳이 아닌 것 같습니다.");
  }

});

 

 

 

4 전체 코드 보기.

전체 코드는 모두 초기 콜백 메소드인 initMap() 속에 다 넣을 수 있었고, 이 메소드만 보여 드립니다. 크게 어려움 없이 동작할 것 입니다.

    <script>
      var map;
      function initMap() {

        // 맵의 초기 위치 지정.
        map = new google.maps.Map(document.getElementById('map'), {
          center: {lat: -34.397, lng: 150.644},
          zoom: 8
        });


        // 각 값들을 가지고 옵니다.
        var geocoder = new google.maps.Geocoder;


        // 클릭한 위치 확인.
        map.addListener('click', function(e) {
          // alert(e.latLng.lat());

          console.log( e );


          // 위경도 좌표를 요창할 객체를 만들어 줍니다.
          var latlng = {
            lat: e.latLng.lat(),
            lng: e.latLng.lng()
          };

          console.log( latlng );



          geocoder.geocode({'location': latlng}, function(results, status) {

            if( status === "OK" )
            {
              // console.log( results );
              alert( JSON.stringify( results ) );
            }else{
              alert("주소를 못 가지고 왔습니다. 사람 사는 곳이 아닌 것 같습니다.");
            }

          });



        });

        // 클릭한 좌표를 주소 형태로 변환.



      }
    </script>

 

 

 

 

 

 

 

 

 

 

 

'솔루션 > google Maps Platform' 카테고리의 다른 글

구글 맵 표시 ( javascript 이용)  (0) 2019.06.16
Posted by 창업닉군
,

웹페이지에 맵을 넣을 일이 있어, 구글맵을 적용하고, 잊지 않기 위해 글을 남겨 둡니다.

 

[공식문서]

Maps JavaScript API : https://developers.google.com/maps/documentation/javascript/tutorial .

 

[참고 사이트]

Google Maps Platform : https://cloud.google.com/maps-platform .

 

 

1. API키 받기.

먼저 구글 지도 플랫폼으로 들어 갑니다. 그리고 오른쪽 상단의 시작하기 버튼을 눌러 줍니다.

 

그리고 사용할 지도 플랫폼을 지정합니다. 일단 지도만 있으면 될것 같지만, 지역정보도 함께 선택해 둡니다.

 

그리고 새로운 프로젝트를 생성합니다. (기존의 프로젝트도 사용해도 상관은 없습니다.)

 

여기까지 들어 오면, 생성한 프로젝트에 결제 사용을 설정할 수 있습니다. 결제 계정을 만들어 줍니다.

 

결제계정을 지정하였다면 아래와 같이 프로젝트가 설정되고, 지도 사용을 위한 API 키가 나옵니다.

 

2. 소스 작성.

소스 작성은 공식 문서 Maps JavaScript API 에 있는 코드를 그대로 복사해 사용하면 됩니다.api키만 바꾸시면됩니다.

<!DOCTYPE html>
<html>
  <head>
    <title>Simple Map</title>
    <meta name="viewport" content="initial-scale=1.0">
    <meta charset="utf-8">
    <style>
      /* Always set the map height explicitly to define the size of the div
       * element that contains the map. */
      #map {
        height: 100%;
      }
      /* Optional: Makes the sample page fill the window. */
      html, body {
        height: 100%;
        margin: 0;
        padding: 0;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>
    <script>
      var map;
      function initMap() {
        map = new google.maps.Map(document.getElementById('map'), {
          center: {lat: -34.397, lng: 150.644},
          zoom: 8
        });
      }
    </script>
    <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap"
    async defer></script>
  </body>
</html>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Posted by 창업닉군
,

구글 플레이는 복잡하고 탈도 많아 (사실 넣기는 쉬운데, 갑자기 버전업 같은 것 하면 아주 말썽을 부립니다.), 사용하지 않으려 했으나, 탭조이를 쓰려고 하니, 구글 플레이 서비스를 필요로 하는 것 같습니다. 그래서 일단 구현을 해 보려고 하는데, 썩 내키지는 않습니다.

 

[공식문서]

유니티 플레이 서비스 : https://github.com/playgameservices/play-games-plugin-for-unity .

 

[참고사이트]

 

 

[예제사이트]

잠자머 : https://m.blog.naver.com/lyw94k/221290526967 .
너랑나랑개발자이야기 : https://you-rang.tistory.com/158 .

 

 

다음에 계속 이어 쓰도록 하겠습니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

'유니티' 카테고리의 다른 글

unity inapp 결제  (0) 2019.04.29
unity Tapjoy offerwall  (1) 2019.04.29
탭조이 유니티 계정생성하기  (0) 2019.04.28
adpopcorn Unity 연동 - android  (0) 2019.04.28
adpopcorn Unity 연동 - 계정추가 (1/3)  (0) 2019.04.28
Posted by 창업닉군
,

OAuth 2.0 을 이용해 Token을 얻어, 이  토큰으로 REST API를 통한 서버의 자원에 접근해 이용하는 방법은 이제 보편화된 방법 입니다. OAuth.2.0은 대부분 http/1.1을 이용하기 때문에, 대부분은 웹서버라면 다 이용할 수 있습니다.

요즘 많이 사용하게 되어 한 번쯤 정리해 둘 필요가 있을 것 같아 블로그에 글을 남겨 둡니다.

 

[공식 문서]

구글 OAuth 2.0 OverView : https://developers.google.com/identity/protocols/OAuth2?hl=ko .
구글 OAuth 2.0 for Web Server Applications : https://developers.google.com/identity/protocols/OAuth2WebServer?hl=ko .
유저 프로필 요청 : https://developers.google.com/gmail/api/v1/reference/users/getProfile .

 

[주요 사이트]

구글 클라우드 콘솔 : https://console.developers.google.com .

 

 

1. 구글 클라우드 콘솔에 프로젝트 및 Gamil 라이브러리 사용설정.

구글 로그인 기능은 자신의 구글 자원에 접근(구글 드라이브, 메일 등) 하기 위해 처음 로그인 하는 부분만 활용해 로그인 연동 처리를 하는 것 입니다. 그래서 최소 하나의 API를 사용하겠다 라고, 신청을 해야 그 다음 부터 이용이 가능합니다. 우리는 Gmail을 신청할 것 입니다. 구글 사용자라면 누구나, Gmail을 이용하고, 모든 유저가 활성화 되어 있기 때문입니다.

1) 프로젝트 생성.

목적별로 프로젝트를 생성한 후, 그 프로젝트에 Gmail을 생성합니다. 우리는 php google oauth 라는 프로젝트를 만들어 보도록 합시다. 처음 구글에 접속하면 다음과 같은 페이지가 표시될 것 입니다. 여기서 만들기를 눌러 프로젝트 만들기 창으로 접근합니다.

모든 사항을 입력한 후 만들기 버튼을 눌러 줍니다. (프로젝트 아이디를 변경해도 상관없습니다. 하지만 여기서는 하지 않았습니다.).

2) Gmail 라이브러리 추가.

그럼 php google oauth 프로젝트가 자동으로 선택되고 (하나 뿐 이므로), API 라이브러리를 추가하라는 메시지를 만납니다. 여기서 우리가 필요로 하는 Gmail API를 추가 해 보도록 합시다.

그럼.  API 라이브러리를 관리하는 화면이 나오는데, 왼쪽 메뉴의 이메일을 선택해 줍니다.

Gmail API를 선택합니다. (이메일은 Gmail API 하나만 있지만, 다른 카테고리는 여러개의, API가 표시될 수 있습니다.)

Gmail API 상세화면에서 사용설정 버튼을 눌러 사용할 수 있도록 해 줍니다.

 

2. OAuth 2.0 동의 화면 설정.

OAuth 로그인을 하는 과정에서 어떤 권한을 사용하는지등을 나타내는 화면이 표시 됩니다. 이 화면을 표시하기 위한 동의 화면을 구성하도록 하겠습니다.

아래와 같이 OAuth 동의 화면 탭을 선택해 나온 페이지에 애플리케이션 이름을 입력하고, 하단의 저장 버튼을 눌러 줍니다.

 

 

3. OAuth 2.0을 위한 클라이언트 ID 만들기.

구글 클라우드 API를 사용하기 위해서는 반드시 OAuth 2.0 방식을 통한 로그인 후 토큰을 획득해야 합니다. 이 과정에서 프로젝트를 구분하는 클라이언트 ID가 필요한데, 지금 만들어 보도록 하겠습니다.

아래와 같이 사용자 인증 정보 탭을 선택하고, OAuth 클라이언트 ID 생성을 눌러 줍니다.

클라이언트 성성 화면에서, 웹 애플리케이션을 선택하고, 이름은 적당히 입력해 주고, 생성 버튼을 눌러 줍니다.

그리고 나면 OAuth 클라이언트 정보를 확인시켜 주는 창이 뜰 텐데 일단 확인을 누르고 닫아 줍니다.

 

4. 리디렉션 주소 설정.

OAuth 2.0에서는 필연적으로 사용자가 계정의 아이디 및 패스워드를 입력하게 됩니다. 이런 과정을 통해 서버 운영자인 우리는, 사용자의 계정이나 패스워드를 저장할 필요성이 사라집니다. 사용자가 로그인을 무사히 완료하면, 서버쪽으로 성공 결과 및 인증코드를 돌려 주는 데, 그 주소를 리디렉션 주소라고 합니다. 이 값은 중요하므로, 구글에 등록된 주소로만 리디렉션 해 줍니다.

이 과정에서 도메인이 필요한 데, 우리는 테스트 과정이므로, localhost를 사용할 것 입니다. 실제 서비스를 한다면, 도메인을 이용해 구성해 주세요.

저는 웹페이지 중 http://localhost/p999/google_OAuth2/token_exchange.php 라는 주소를 설정할 것 입니다. 파일이름이 token_exchange.php 인 이유는 받은 인증 코드를 이용해 토큰으로 교환할 것 이기 때문입니다.

사용자 인증탭에 OAuth 2.0에 사용할 클라이언트 ID의 수정 버튼을 눌러 줍니다. 그리고, 나온 페이지에 승인된 리디렉션 URI에 리디렉션 주소를 입력하고( 꼭 엔터를 눌러 줍니다. ), 저장 버튼을 눌러 줍니다.

 

5. 인증을 구현을 위한 필요 정보 조사.

인증에 사용할 클라이언트 ID를 눌러 주도록 합니다.

페이지에서 각각의 정보를 수집합니다.

클라이언트 ID : 107557211118-lpfm0l4gs5ffpas8cbjn5bp71f2hbag5.apps.googleusercontent.com
크라이언트 보안 비밀 : NaJSvmGdShGg1kkXkGdvHp4T
승인된 리디렉션 URI : http://localhost/p999/google_OAuth2/token_exchange.php

 

6. 인증서 코드 요청 페이지 만들기.

저는 PC의 웹서버에, /p999/google_OAuth2/ 폴더 속에서 웹 파일들을 만들어 주고 있습니다. 코드를 요청하는 페이지 이름은 request_code.php 로 정하고 코딩하였습니다. 이 페이지에서 사용되는 내용은, Using OAuth 2.0 for Web Server Application (위에 링크 있습니다.)공식 문서에 HTTP/REST 부분의, 내용 입니다.

scope 의 권한 부분은 OAuth 2.0 API Scopes ( 링크 )에서 확인할 수 있는 데, 우리는 메일의 모든 권한을 요청할 것 입니다. 그 권한은 ( https://mail.google.com/ ) 입니다.

state 값은 리디렉션 시 그대로 다시 전달 받을 값 입니다. 로그인 과정에서 수많은 유저가 동시에 접속하면, 어떤 유저의 로그인인지 확인할 필요가 있습니다. 이때 사용하면 좋으며, 세션을 사용한다면, 사용하지 않아도 상관이 없습니다.

코드 자체는 로그인할 주소를 입력한 뒤, 리디렉션 해 주면 끝이 납니다. 아래는, request_code.php 페이지의 내용 입니다.

<?php



    // 주요 값들.
    $client_id = "107557211118-lpfm0l4gs5ffpas8cbjn5bp71f2hbag5.apps.googleusercontent.com";
    $client_secret = "NaJSvmGdShGg1kkXkGdvHp4T";
    $redirection_url = "http://localhost/p999/google_OAuth2/token_exchange.php";
    $scope = "https://mail.google.com/";

    // 인증 코드 주소 생성.
    $reqAddr = "https://accounts.google.com/o/oauth2/v2/auth"
    . "?client_id=" . $client_id
    . "&redirect_uri=" . urlencode( $redirection_url )
    . "&scope=" . urlencode( $scope )
    . "&state=OK"
    . "&access_type=offline"
    . "&include_granted_scopes=true"
    . "&response_type=code"
    ;

    // 지정한 주소로 리디렉션 시키기.
    header( 'Location: ' . $reqAddr );

?>

인증 코드를 무사히 넘겨 받았을 때 결과를 리디렉션 받아 토큰을 교환하는 페이지의 소스는 일단 아래와 같이 둡니다.

<?php


    print_r( $_GET );

자그럼 request_code.php 파일을 실행해 보도록 합시다. 정상적으로 리디렉션 된다면, 아래와 같은 페이지를 만날 수 있습니다.

일반적으로 구글 로그인 화면이므로, 쉽게 무엇을 넣어야 할 지 알 수 있을 것 입니다. 계속해서 로그인을 하도록 합니다.

로그인이 완료되면, 우리가 scope로 요청했던, Gmail의 모든 권한을 부여해달라는 페이지가 뜹니다. 우리는 현재 우리 계정으로 로그인하지만, 일반 유저가 우리 홈페이지에 접근할 때, 이 페이지를 보개 될 것이며, 자신의 Gmail을 이용할 것을 알게 됩니다. 일단 계속 해서 허용을 해 봅시다.

자 그럼 우리가 설정해 놓은 리디렉션 페이지로 GET을 통해 code, scope, state 값이 넘어 온 것을 확인할 수 있습니다.

 

7. 토큰 교환

우리가 리디렉션 받은 페이지에서, 받은 코드값을 사용해 토큰을 받아 오도록 하겠습니다. 이 부분은 서버에서 POST 통신을 해야 하므로, 약간의 난이도(?)가 있습니다.

POST 통신을 위해, fsocketopen 메소드를 상용하겠습니다. 공식 문서에 보면, 아래와 같이 데이터를 보내 도록 되어 있습니다. 우리도 그 값 그대로 보내면 되겠습니다. 공식 문서에는 endpoint가 https://www.googleapis.com/oauth2/v4/token 라고 되어 있습니다. 여기로 접속할 것 입니다.

POST /oauth2/v4/token HTTP/1.1
Host: www.googleapis.com
Content-Type: application/x-www-form-urlencoded

code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=your_client_id&
client_secret=your_client_secret&
redirect_uri=https://oauth2.example.com/code&
grant_type=authorization_code

아래는 토큰 교환을 하는 코드 입니다.

    // 주요 값들.
    $client_id = "107557211118-lpfm0l4gs5ffpas8cbjn5bp71f2hbag5.apps.googleusercontent.com";
    $client_secret = "NaJSvmGdShGg1kkXkGdvHp4T";
    $redirection_url = "http://localhost/p999/google_OAuth2/token_exchange.php";
    $scope = "https://mail.google.com/";



    // 보낼 쿼리 만들기.
    $sendQuery = ""
    . "code=" . $_GET['code']
    . "&client_id=" . $client_id
    . "&client_secret=" . $client_secret
    . "&redirect_uri=" . urlencode( $redirection_url )
    . "&grant_type=authorization_code"
    ;


    // 보낼 데이터를 만들어 주기 위한 기본값을 설정합니다.
    $endline = "\r\n";
    $req = "";
    
    
    // 구글에서 요청한 필수 헤더를 추가합니다.
    $req = "POST /oauth2/v4/token HTTP/1.1" . $endline
    . "Host: www.googleapis.com" . $endline
    . "Content-Type: application/x-www-form-urlencoded" . $endline
    ;

    
    // POST 데이터를 보내기 위한 기본 헤더를 추가힙니다.
    $req .= "Content-Length: " . strlen($sendQuery) . $endline
    . "Connection: Close" . $endline
    ;
    
    // 헤더의 끝을 표시하는 빈 문자열을 설정합니다.
    $req .= $endline;
    
    // 내용을 추가해 보내어 줍니다.
    $req .= $sendQuery;
    ;

    // 해당 구글 서버와 연결을 시도합니다.
    $fsock = @fsockopen( "ssl://www.googleapis.com", 443 );

    // 구글 서버에 접속 실패한 경우.
    if( !$fsock )
    {
        echo "구글 서버에 접속 실패하였습니다.!";
        exit;
    }
    
    // 데이터 보내기를 합니다.
    fwrite( $fsock, $req );


    // 데이터 받기를 위해 필요한 값들을 선언합니다.
    $headPassed = false;
    $TokenJson = "";


    // 데이터 받기가 완료될 때 까지 대기하면 데이터를 받아 출력합니다.
    while( !feof($fsock) )
    {

        // 한 줄 라인을 가지고 옵니다.
        $line = fgets($fsock, 128);

        // 아직 헤더는 아니지만, 헤더의 끝을 만난 경우, 헤더가 끝났음을 마킹하고, 종료합니다.
        if( $line == "\r\n" && !$headPassed )
        {
            $headPassed = true;
            continue;
        }

        // 헤더가 아닌 경우만, 값을 출력하도록 합니다.
        if( $headPassed )
        {
            $TokenJson .= $line;
        }

    }

    // 연결을 닫아 주도록 합니다.
    fclose( $fsock );

    // 받아 온 Token Json을 토큰 객체로 만들어 줍니다.
    $TokenObj = json_decode( $TokenJson );

    // 받아 온 토큰을 출랙해 줍니다.
    echo "받은 토큰은 아래와 같습니다.<br>";
    print_r( $TokenObj );
    echo "<br>---------------------------<br><br>";

 

8. 유저 프로필 요청.

gmail의 간단한 사용자의 정보를 가지고 옵니다. GET 타입이므로, 리디렉션 처리를 하면 간단하지만, 우리는 지금 학습단계이므로, fsockopen 을 이용해 구현해 보도록 하겠습니다.

gmail 의 유저 프로필 요청을 합니다. 공식 문서를 참고해 주시고, 아래 코드를 추가하면 됩니다. 아마 별다른 설명은 필요 없을 것이라 봅니다.

    // 보낼 문장을 반들어 줍니다.
    $userinfor_req = "GET /gmail/v1/users/me/profile HTTP/1.1" . $endline
    . "Authorization: Bearer " . $TokenObj->access_token . $endline
    . "Host: www.googleapis.com" . $endline
    . "Connection: Close" . $endline

    . $endline


    ;


    // 해당 구글 서버와 연결을 시도합니다.
    $fsock = @fsockopen( "ssl://www.googleapis.com", 443 );

    // 구글 서버에 접속 실패한 경우.
    if( !$fsock )
    {
        echo "구글 서버에 접속 실패하였습니다.!";
        exit;
    }
    
    // 데이터 보내기를 합니다.
    fwrite( $fsock, $userinfor_req );




    // 데이터 받기를 위해 필요한 값들을 선언합니다.
    $headPassed = false;
    $profileJson = "";


    while( !feof($fsock) )
    {

        // 한 줄 라인을 가지고 옵니다.
        $line = fgets($fsock, 128);

        // 아직 헤더는 아니지만, 헤더의 끝을 만난 경우, 헤더가 끝났음을 마킹하고, 종료합니다.
        if( $line == "\r\n" && !$headPassed )
        {
            $headPassed = true;
            continue;
        }

        // 헤더가 아닌 경우만, 값을 출력하도록 합니다.
        if( $headPassed )
        {
            $profileJson .= $line;
        }

    }


    // 연결을 닫아 주도록 합니다.
    fclose( $fsock );



    // 가지고 온 유저 데이터를 출력하도록 합니다.
    echo "확인한 유저 정보는 아래와 같습니다.<br>";
    echo $profileJson;
    

잘 실행되었다면, 아래와 같은 페이지를 볼수 있습니다.

 

 

마지막. 전체 코드 입니다.

<?php



    // 주요 값들.
    $client_id = "107557211118-lpfm0l4gs5ffpas8cbjn5bp71f2hbag5.apps.googleusercontent.com";
    $client_secret = "NaJSvmGdShGg1kkXkGdvHp4T";
    $redirection_url = "http://localhost/p999/google_OAuth2/token_exchange.php";
    $scope = "https://www.googleapis.com/auth/gmail.readonly";
    // $scope = "profile|email|openid";
    // $scope = urlencode( $scope );


    // 보낼 쿼리 만들기.
    $sendQuery = ""
    . "code=" . $_GET['code']
    . "&client_id=" . $client_id
    . "&client_secret=" . $client_secret
    . "&redirect_uri=" . urlencode( $redirection_url )
    . "&grant_type=authorization_code"
    ;


    // 보낼 데이터를 만들어 주기 위한 기본값을 설정합니다.
    $endline = "\r\n";
    $req = "";
    
    
    // 구글에서 요청한 필수 헤더를 추가합니다.
    $req = "POST /oauth2/v4/token HTTP/1.1" . $endline
    . "Host: www.googleapis.com" . $endline
    . "Content-Type: application/x-www-form-urlencoded" . $endline
    ;

    
    // POST 데이터를 보내기 위한 기본 헤더를 추가힙니다.
    $req .= "Content-Length: " . strlen($sendQuery) . $endline
    . "Connection: Close" . $endline
    ;
    
    // 헤더의 끝을 표시하는 빈 문자열을 설정합니다.
    $req .= $endline;
    
    // 내용을 추가해 보내어 줍니다.
    $req .= $sendQuery;
    ;

    // 해당 구글 서버와 연결을 시도합니다.
    $fsock = @fsockopen( "ssl://www.googleapis.com", 443 );

    // 구글 서버에 접속 실패한 경우.
    if( !$fsock )
    {
        echo "구글 서버에 접속 실패하였습니다.!";
        exit;
    }
    
    // 데이터 보내기를 합니다.
    fwrite( $fsock, $req );


    // 데이터 받기를 위해 필요한 값들을 선언합니다.
    $headPassed = false;
    $TokenJson = "";


    // 데이터 받기가 완료될 때 까지 대기하면 데이터를 받아 출력합니다.
    while( !feof($fsock) )
    {

        // 한 줄 라인을 가지고 옵니다.
        $line = fgets($fsock, 128);

        // 아직 헤더는 아니지만, 헤더의 끝을 만난 경우, 헤더가 끝났음을 마킹하고, 종료합니다.
        if( $line == "\r\n" && !$headPassed )
        {
            $headPassed = true;
            continue;
        }

        // 헤더가 아닌 경우만, 값을 출력하도록 합니다.
        if( $headPassed )
        {
            $TokenJson .= $line;
        }

    }

    // 연결을 닫아 주도록 합니다.
    fclose( $fsock );

    // 받아 온 Token Json을 토큰 객체로 만들어 줍니다.
    $TokenObj = json_decode( $TokenJson );

    // 받아 온 토큰을 출랙해 줍니다.
    echo "받은 토큰은 아래와 같습니다.<br>";
    print_r( $TokenObj );
    echo "<br>---------------------------<br><br>";





    // [-- 아래는 유저 프로필 가지고 오기 관련 --]

    
    // 보낼 문장을 반들어 줍니다.
    $userinfor_req = "GET /gmail/v1/users/me/profile HTTP/1.1" . $endline
    . "Authorization: Bearer " . $TokenObj->access_token . $endline
    . "Host: www.googleapis.com" . $endline
    . "Connection: Close" . $endline

    . $endline


    ;


    // 해당 구글 서버와 연결을 시도합니다.
    $fsock = @fsockopen( "ssl://www.googleapis.com", 443 );

    // 구글 서버에 접속 실패한 경우.
    if( !$fsock )
    {
        echo "구글 서버에 접속 실패하였습니다.!";
        exit;
    }
    
    // 데이터 보내기를 합니다.
    fwrite( $fsock, $userinfor_req );




    // 데이터 받기를 위해 필요한 값들을 선언합니다.
    $headPassed = false;
    $profileJson = "";


    while( !feof($fsock) )
    {

        // 한 줄 라인을 가지고 옵니다.
        $line = fgets($fsock, 128);

        // 아직 헤더는 아니지만, 헤더의 끝을 만난 경우, 헤더가 끝났음을 마킹하고, 종료합니다.
        if( $line == "\r\n" && !$headPassed )
        {
            $headPassed = true;
            continue;
        }

        // 헤더가 아닌 경우만, 값을 출력하도록 합니다.
        if( $headPassed )
        {
            $profileJson .= $line;
        }

    }


    // 연결을 닫아 주도록 합니다.
    fclose( $fsock );



    // 가지고 온 유저 데이터를 출력하도록 합니다.
    echo "확인한 유저 정보는 아래와 같습니다.<br>";
    echo $profileJson;
    

 

 

 

 

 

 

 

Posted by 창업닉군
,

node js OAuth 2.0 Login

Node.js 2019. 4. 16. 11:10

node js는 패스포트를 이용하면, 거의 모든 SNS 로그인을 구현할 수 있습니다. 하지만, 새로운 SNS 사이트나 OAuth 2.0 기능을 가진 사이트의 요청을 필요로 할 때를 대비해 기능을 잘 알아 둘 필요가 있습니다. 그리고 모듈을 쓸 필요도 없을 만큼 매우 간단하고 쉽습니다.

[공식 문서]

구글 OAuth 2.0 OverView : https://developers.google.com/identity/protocols/OAuth2?hl=ko .
구글 OAuth 2.0 for Web Server Applications : https://developers.google.com/identity/protocols/OAuth2WebServer?hl=ko .
유저 프로필 요청 : https://developers.google.com/gmail/api/v1/reference/users/getProfile .


[주요 사이트]

Google APIs 콘솔 : https://console.developers.google.com .

 

[참고 문서]

php를 이용한 Google OAuth2.0 Login : https://nicgoon.tistory.com/208 . (전반부 구글 클라우드 콘솔 설정 숙지.).

 

1. 준비사항.

1) 본 문서를 보기전, 구글 클라우드 API에서 클라이언트 ID를 만들어야 합니다. 해당 내용은 위 참고 문서 php를 이용한 Google OAuth2.0 Login 부분을 참고 하시면됩니다. 

2) 익스프레스 서버 설정.

익스프레스를 이용해 서버를 설정하였다면, 웹을 처리를 할 라우트를 만들어 주세요 저는 아래와 같이 라우트 주소를 설정하였습니다.

구글 로그인 라우트 기본 주소 : http://localhost/oauth2
인증코드 요청 페이지 : 
http://localhost/oauth2/request_code
토큰 교환 페이지 : 
http://localhost/oauth2/exchange_token

3) 클라이언트 아이디 관련 값들.

클라이언트 아이디 : 107557211118-lpfm0l4gs5ffpas8cbjn5bp71f2hbag5.apps.googleusercontent.com
클라이언트 보안 비밀 : NaJSvmGdShGg1kkXkGdvHp4T
리디렉션 페이지 : http://localhost/oauth2/exchange_token

 

2. 라우트 기본 뼈대.

구글 로그인에서 사용되는 페이지는 최소 2개이고, 이 것을 저는 라우트를 하나 만들어 다음과 같은 코딩을 했습니다. request_code 는 인증코드 요청페이지, exchange_token 은 리디렉션 후 토큰 교환 입니다.

var express = require('express');
var router = express.Router();

/* GET home page. */
router.use('/:name', function(req, res, next) {
    


    // 요청한 파일명을 가지고 오는 메소드 입니다.
    let methodName = req.params.name;


    
    // 인증 코드를 요청한 경우 처리 분기 입니다.
    if( methodName == "request_code" )
    {
        request_code(req, res, next);
        return;                                     // 리턴 중요.
    }


    // 토큰 교환을 요청한 경우 처리 분기 입니다.
    else if( methodName == "exchange_token" )
    {
        exchange_token(req, res, next);
        return;                                     // 리턴 중요.
    }




    // 처리 방법을 확인하지 못한 경우. next 처리를 하도록 합니다.
    next();


});



// 인증 코드를 요청한 경우 처리 하는 메소드 입니다.
function request_code( req, res, next )
{
    res.setHeader( "Content-Type", "text/html; charset=UTF-8" );
    res.end( "코드 요청하는 메소드." );
}



// 토큰 교환 및 사용자 정보를 확인하는 경우 처리하는 메소드 입니다.
function exchange_token( req, res, next )
{
    res.setHeader( "Content-Type", "text/html; charset=UTF-8" );
    res.end("토큰을 교환하는 메소드.");
}





module.exports = router;

 

3. 유저 로그인 페이지 리디렉션하기.

주소를 만들때, 사용되는 옵션은 문서 처음에 있는 [구글 OAuth 2.0 for Web Server Applications] 링크를 참고 하시기 바립니다.

request_code 부분에 인증을 위한 주소를 만들어 리디렉션 하면, 사용자는 구글 로그인 창을 보게 됩니다. 코드는 아래와 같습니다.

// 인증 코드를 요청한 경우 처리 하는 메소드 입니다.
function request_code( req, res, next )
{

    // 공통적으로 사용하는 상수들 입니다.
    var scope = "https://mail.google.com/";
    var client_id = "107557211118-lpfm0l4gs5ffpas8cbjn5bp71f2hbag5.apps.googleusercontent.com";
    var client_secret = "NaJSvmGdShGg1kkXkGdvHp4T";
    var redriect_url = "http://localhost/oauth2/exchange_token";



    // 인증을 위한 주소를 만들어 줍니다.
    let reqAddr = "https://accounts.google.com/o/oauth2/v2/auth"
    + "?client_id=" + client_id
    + "&redirect_uri=" + encodeURIComponent( redriect_url )
    + "&scope=" + encodeURIComponent( scope )
    + "&state=OK"
    + "&access_type=offline"
    + "&include_granted_scopes=true"
    + "&response_type=code"
    ;

    

    res.redirect( reqAddr );


}

로그인 하고, 권한도 모두 주면, 리디렉션 페이지가 호출 됩니다. 우리는 여기서, 토큰 교환을 시도할 것 입니다.

 

4. 토큰 교환 처리.

정식 문서를 보면, 아래와 같은 값을 보내면, 토큰을 주는 것으로 되어 있습니다. 

POST /oauth2/v4/token HTTP/1.1
Host: www.googleapis.com
Content-Type: application/x-www-form-urlencoded

code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=your_client_id&
client_secret=your_client_secret&
redirect_uri=https://oauth2.example.com/code&
grant_type=authorization_code

우리가 받은 토큰 값등을 활용해 위의 페이지를 만들 것 입니다.

1) 리퀘스트 설치.

페이지를 요청하는 데 리퀘스트 객체를 사용할 것 입니다. 아래와 같이 리퀘스트를 설치해 주도록 합니다.

npm i request

2) 토큰 교환.

보내야 할 데이터 중 헤더 부분은 request가 알아서 채워 줍니다. (POST로 보낼 때 당연히 적어야할 부분). 그래서 데이터부분만 적어 주면됩니다. exchange_token 메소드를 다음과 같이 변경해 보도록 합니다.

// 토큰 교환 및 사용자 정보를 확인하는 경우 처리하는 메소드 입니다.
function exchange_token( req, res, next )
{


    // 요청할 데이터를 만들어 줍니다.
    let requestOption = {
        url:'https://www.googleapis.com/oauth2/v4/token',
        method:'POST',
        form:{
            code:req.query.code,
            client_id:client_id,
            client_secret:client_secret,
            redirect_uri: redriect_url,
            grant_type: 'authorization_code'
        }
    };

    request.post( requestOption, function( err, httpResponse, body ){


        res.setHeader( "Content-Type", "text/html; charset=UTF-8" );
    

        // 오류가 난 경우 오류를 반환해 줍니다.
        if( err )
        {

            res.end("오류가 났습니다.<br>" + err);
            return;

        }

        res.end( body );


    });



}

그리고 실행하면 정상적인 경우 다음과 같은 응답을 화면에 뿌려 줍니다. (자세히 보면 Access Token을 받아 온 것을 확인할 수 있을 것 입니다.)

5. 사용자 정보 가지고 오기.

교환된 토큰으로 아래와 같이 함수를 만들어 body와 res 값을 넣어 주면, 화면에 사용자 정보를 표시해 줍니다.

// 토큰 교환 및 사용자 정보를 확인하는 경우 처리하는 메소드 입니다.
function exchange_token( req, res, next )
{


    // 요청할 데이터를 만들어 줍니다.
    let requestOption = {
        url:'https://www.googleapis.com/oauth2/v4/token',
        method:'POST',
        form:{
            code:req.query.code,
            client_id:client_id,
            client_secret:client_secret,
            redirect_uri: redriect_url,
            grant_type: 'authorization_code'
        }
    };

    request.post( requestOption, function( err, httpResponse, body ){


        res.setHeader( "Content-Type", "text/html; charset=UTF-8" );
    

        // 오류가 난 경우 오류를 반환해 줍니다.
        if( err )
        {

            res.end("오류가 났습니다.<br>" + err);
            return;

        }

        // res.end( body );
        bodyobj = JSON.parse( body );
        read_profile( res, bodyobj.access_token );


    });



}


// 유저 정보를 확인하는 메소드 입니다.
function read_profile( res, token )
{

    // 요청할 데이터를 만들어 줍니다.
    let requestOption = {
        url:'https://www.googleapis.com/gmail/v1/users/me/profile',
        headers:{
            'Authorization': 'Bearer ' + token
        },
        rejectUnauthorized:false
    };



    request.get( requestOption, function( err, httpResponse, body ){

        if( err )
        {

            res.end("사용자 정보를 확인하던 중 오류가 났습니다.<br>" + err);
            return;

        }

        // 사용자 정보를 출력합니다.
        res.end( body );

    });

}

별다은 오류가 없다면 다음과 같은 페이지를 볼 수 있을 것 입니다.

 

6. 전체 소스

익스프레서 서버에서 사용하기 위한 전체 소스 코드는 아래와 같습니다.

var express = require('express');
var router = express.Router();


var request = require('request');


// 공통적으로 사용하는 상수들 입니다.
var scope = "https://mail.google.com/";
var client_id = "107557211118-lpfm0l4gs5ffpas8cbjn5bp71f2hbag5.apps.googleusercontent.com";
var client_secret = "NaJSvmGdShGg1kkXkGdvHp4T";
var redriect_url = "http://localhost/oauth2/exchange_token";


/* GET home page. */
router.use('/:name', function(req, res, next) {
    


    // 요청한 파일명을 가지고 오는 메소드 입니다.
    let methodName = req.params.name;


    
    // 인증 코드를 요청한 경우 처리 분기 입니다.
    if( methodName == "request_code" )
    {
        request_code(req, res, next);
        return;                                     // 리턴 중요.
    }


    // 토큰 교환을 요청한 경우 처리 분기 입니다.
    else if( methodName == "exchange_token" )
    {
        exchange_token(req, res, next);
        return;                                     // 리턴 중요.
    }




    // 처리 방법을 확인하지 못한 경우. next 처리를 하도록 합니다.
    next();


});



// 인증 코드를 요청한 경우 처리 하는 메소드 입니다.
function request_code( req, res, next )
{



    // 인증을 위한 주소를 만들어 줍니다.
    let reqAddr = "https://accounts.google.com/o/oauth2/v2/auth"
    + "?client_id=" + client_id
    + "&redirect_uri=" + encodeURIComponent( redriect_url )
    + "&scope=" + encodeURIComponent( scope )
    + "&state=OK"
    + "&access_type=offline"
    + "&include_granted_scopes=true"
    + "&response_type=code"
    ;

    

    res.redirect( reqAddr );


}



// 토큰 교환 및 사용자 정보를 확인하는 경우 처리하는 메소드 입니다.
function exchange_token( req, res, next )
{


    // 요청할 데이터를 만들어 줍니다.
    let requestOption = {
        url:'https://www.googleapis.com/oauth2/v4/token',
        method:'POST',
        form:{
            code:req.query.code,
            client_id:client_id,
            client_secret:client_secret,
            redirect_uri: redriect_url,
            grant_type: 'authorization_code'
        }
    };

    request.post( requestOption, function( err, httpResponse, body ){


        res.setHeader( "Content-Type", "text/html; charset=UTF-8" );
    

        // 오류가 난 경우 오류를 반환해 줍니다.
        if( err )
        {

            res.end("오류가 났습니다.<br>" + err);
            return;

        }

        // res.end( body );
        bodyobj = JSON.parse( body );
        read_profile( res, bodyobj.access_token );


    });



}


// 유저 정보를 확인하는 메소드 입니다.
function read_profile( res, token )
{

    // 요청할 데이터를 만들어 줍니다.
    let requestOption = {
        url:'https://www.googleapis.com/gmail/v1/users/me/profile',
        headers:{
            'Authorization': 'Bearer ' + token
        },
        rejectUnauthorized:false
    };



    request.get( requestOption, function( err, httpResponse, body ){

        if( err )
        {

            res.end("사용자 정보를 확인하던 중 오류가 났습니다.<br>" + err);
            return;

        }

        // 사용자 정보를 출력합니다.
        res.end( body );

    });

}




module.exports = router;

 

 

 

 

 

 

 

 

Posted by 창업닉군
,