PHP

[ PHP ] 네이버 간편로그인 회원가입 구현 , CSRF 방지 코드 추가

Khookie 2022. 10. 30. 16:27

네이버 로그인 API 를 처음 공부하고 써보면서 완성된 코드를 공유합니다.

 php 를 사용한 웹 애플리케이션을 위한 코드입니다.

공식 가이드와 함께 비교하며 참고해주세요

 

네이버 developers 로그인 구현 : 

https://developers.naver.com/docs/login/web/web.md

 

Web 애플리케이션 - LOGIN

네이버 로그인은 서버 사이드 언어인 PHP나 Java로 개발한 웹 애플리케이션에도 적용할 수 있습니다. 또한 프런트엔드에서 사용하는 JavaScript를 사용해도 적용할 수 있습니다. API 호출 예제 예제

developers.naver.com

 

1.애플리케이셔 등록

- 위 사이트에서 애플리케이션 등록을 통해 리디렉트 url 과 수집정보, 약관 정보 등의 설정이 필요합니다.

 

2.개발

 

로그인 HTML 부분

<!-- sns 간편로그인 -->
<?php include("./sns_login/naverlogin.php"); ?>
<a href="<?php echo $apiURL ?>"><img height="50" src="http://static.nid.naver.com/oauth/small_g_in.PNG"/></a>

naverlogin.php

<?php
// CSRF 방지를 위한 상태 토큰 생성 함수
function generate_state() {
    $mt = microtime();
    $rand = mt_rand();
    return md5($mt . $rand);
}

// 네이버 로그인 접근토큰 요청
$client_id = "xxx"; //YOUR_CLIENT_ID
$redirectURI = urlencode("http://localhost:3000/sns_login/callback.php"); //YOUR_CALLBACK_URL
$state = generate_state();//랜덤 상태토큰
$_SESSION['state'] = $state; // 추후 검증을 위해 세션 또는 별도의 저장 공간에 상태 토큰을 저장

$apiURL = "https://nid.naver.com/oauth2.0/authorize?response_type=code&client_id=".$client_id."&redirect_uri=".$redirectURI."&state=".$state;
?>

 

callback.php

<?php
  include("../db.php"); //세션 스타트와 DB연결 정보를 가진 파일       
  
  // 네이버 로그인 콜백 
  $client_id = "xxx"; //YOUR_CLIENT_ID
  $client_secret = "xxx"; //YOUR_CLIENT_SECRET
  $code = $_GET["code"];; //인증 코드
  $callback_state = $_GET["state"];; // 콜백 응답에서 state 파라미터의 값을 가져옴
  $redirectURI = urlencode("http://localhost:3000/sns_login/callback.php"); //YOUR_CALLBACK_URL
  $url = "https://nid.naver.com/oauth2.0/token?grant_type=authorization_code&client_id=".$client_id."&client_secret=".$client_secret."&redirect_uri=".$redirectURI."&code=".$code."&state=".$callback_state; //접근토큰 요청문 url
  $is_post = false;
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_POST, $is_post);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  $headers = array();
  $response = curl_exec ($ch);
  $status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  curl_close ($ch);
  $data = array();

  //echo "<script>console.log( 'status_code:".$status_code .";' );</script>";

  // CSRF 방지를 위한 상태 토큰 검증
  if( $callback_state != $_SESSION['state'] ) {
      header('HTTP/1.0 401 unauthorized'); //401 unauthorized
      die();
  }  

  if($status_code == 200) { 
      $result = json_decode($response); //토큰 정보

      $token = $result-> access_token;
      $header = "Bearer ".$token; // Bearer 다음에 공백 추가
      $url = "https://openapi.naver.com/v1/nid/me";
      $is_post = false;
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_URL, $url);
      curl_setopt($ch, CURLOPT_POST, $is_post);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
      $headers = array();
      $headers[] = "Authorization: ".$header;
      curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
      $response = curl_exec ($ch);
      $status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
      curl_close ($ch);

      if($status_code == 200) {
        $naver_login = json_decode($response); //프로필 정보
        
        $data['id'] = 'naver_'.$naver_login->response->id;
        $data['name'] = $naver_login->response->name;
        $data['phone'] = $naver_login->response->mobile;
        $data['email'] = $naver_login->response->email;
        $date= date("Y-m-d");

        // 아이디 존재여부 체크 후 없으면 등록, 로그인 처리
        $sql = "select * from sns_member where sns_id='".$data['id']."'";
        $stmt = $conn->query($sql);

        if($stmt->num_rows != 0) { // 이미 가입, 업데이트
          $sql ="update sns_member set hp='{$data['phone']}', name='{$data['name']}', email='{$data['email']}',sns_last_connect_date='{$date}' where sns_id='{$data['id']}'";
          $stmt = $conn->query($sql);

        }else{ //신규
          $sql = "insert into sns_member set sns_id='{$data['id']}' , hp='{$data['phone']}', name='{$data['name']}', email='{$data['email']}', regist_date='{$date}', sns_type='naver', sns_last_connect_date='{$date}'";
          $conn->query($sql);   
          echo "<script>alert('회원가입이 완료되었습니다.')</script>;";
        }    
          
        echo("<script>location.replace('http://localhost:3000/main.php');</script>");

      } else {
        echo "Error 내용:".$response;
      }
   
  } else {
    echo "Error 내용:".$response;
  }

?>

참고하세요. sql 쿼리문 부분은 데이터 테이블을 어떻게 구현 했느냐에 따라서 수정해야 합니다

 

 

*-도움이 되었다면 공감을 눌러주세요-*

< IT연구소 쿠키 랩 />