네이버 로그인 2

2024. 7. 30. 18:09Springboot-React

스프링 부트쪽 작성

 

application.properties

server.port=9011

#com.kh로 시작하는 패키지에 문제가 생기면 볼 수 있도록 확인하는 코드
logging.level.com.kh=debug

server.servlet.session.tracking-modes=cookie

#코드의 수정이 있을 때 자동으로 새로고침
spring.devtools.livereload.enabled=true

#코드의 변경이 있을 때 자동으로 다시 시작. mapper.xml 수정 해도 새로고침 하지 않고 바로 적용
spring.devtools.restart.enabled=true

#자동 캐시 지우기
spring.thymeleaf.cache=false

#네이버 로그인을 위한 키 작성하기
naver.client-id = 클라이언트키
naver.client-secret = 클라이언트 시크릿 키
#node.js에서는 로컬호스트3000이었지만 스프링부트는 9010이므로 맞춰서 작성
naver.redirect-uri = http://localhost:9011/api/naverLogin
naver.state = RANDOM_STATE

 

OAuthController.java

package com.kh.controller;

import java.util.Map;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import jakarta.servlet.http.HttpSession;

// NaverLogin을 한 후에 로그인한 내용을 리액트에서 볼 수 있도록 NaverLoginController 파일을 수정
// NaverLoginController.java 주소 (api url) 충돌을 막기 위해 @RequestMapping("/api")를 제거

@RestController
public class OAuthController {
	
	@Value("${naver.client-id}")
	private String clientId; 
	
	@Value("${naver.client-secret}")
	private String clientSecret;
	
	@Value("${naver.redirect-uri}")
	private String redirectUri;
	
	@Value("${naver.state}")
	private String state; 
	
	@GetMapping("/naverLogin") 
	public String naverLogin() {
		String api_url = "https://nid.naver.com/oauth2.0/authorize?response_type=code&client_id=" + clientId + "&redirect_uri=" + redirectUri + "&state=" + state;
		return "<a href='"+ api_url + "'><img height='50' src='http://static.nid.naver.com/oauth/small_g_in.PNG'/></a>";
	}
	@GetMapping("/callback")
	public String callback(@RequestParam String code, @RequestParam String state, HttpSession session) {
		String api_url = "https://nid.naver.com/oauth2.0/token?grant_type=authorization_code&client_id="
			     + clientId + "&client_secret=" + clientSecret + "&redirect_uri=" + redirectUri + "&code=" + code + "&state=" + state;

		RestTemplate restTemplate = new RestTemplate();
		
		// 앞의 값은 키 이름이기 때문에 String
		// 키 이름에 담긴 값은 String이라고 확정지을 수 없으므로 Object
		Map<String, Object> responseResult = restTemplate.getForObject(api_url, Map.class);
		System.out.println("Token response : " + responseResult);
		
		// token 인증받은 값을 가져오는 데 Bearer access_token 사용
		// 가져온 token 데이터를 문자열로 변환, 글자처럼 사용
		String accessToken = (String) responseResult.get("access_token"); 
		//네이버 개발자 문서에 access_token으로 로그인 허영된 값을 가져가라고 써있음
		
		String 유저정보가담긴Url = "https://openapi.naver.com/v1/nid/me";
		
		HttpHeaders headers = new HttpHeaders();
		headers.set("Authorization", "Bearer " + accessToken);
		HttpEntity<String> entity = new HttpEntity<>("", headers);
		//HttpEntity = 응답, 요청 모두 있음. 상세한 기능은 없음. ** ResponseEntity, RequestEntity = 각자 상세 기능 보유
		
		ResponseEntity<Map> userInfoRes = restTemplate.exchange(유저정보가담긴Url, HttpMethod.GET, entity, Map.class);
		
		Map<String, Object> userInfo = userInfoRes.getBody();
		session.setAttribute("userInfo", userInfo); //session에 로그인 정보를 담음

		return "redirect:";
	}
	
	//가져온 네이버 정보를 리액트로 전달할 GetMapping
	@GetMapping("/userInfo")
	//HttpSession - > import jakarta O - 신버전 / javax X - 구버전
	public Map<String, Object> userInfo(HttpSession session) {
		//httpSession을 Map으로 형변환
		Map<String, Object> userInfo = (Map<String, Object>)session.getAttribute("userInfo");
		return userInfo;
	}
	
	
}

 

 

** HttpHeaders에 인증에 대한 값을 Bearer로 가져오기
Bearer : 인증을 위해 서버에 제공되는 보안 토큰. 사용자가 인증을 받고 나서 API 요청을 할 때 사용

ex) 네이버에 로그인을 하고 나면 사용자에게 로그인 됐음을 인증하는 토큰을 발급
    추후 네이버에 로그인 된 기록을 가지고 어떠한 요청을 할 때 헤더에
    Authorization : Bearer{} 작성하고 요청을 해야함

    * Bearer = 소유자

    Authorization : Bearer{}
= 권한 부여 : 권한을 가진 사람{"권한을 가지고 있는 번호"}

 

 

NaverLoginController.java

package com.kh.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

//리액트와 스프링 프레임워크 연동을 위한 컨트롤러
//OAuthController와 api url 주소가 동일해서 나타나는 충돌을 막기 위해 모든 url 앞에 api가 붙도록 설정

@RestController
@RequestMapping("/api")
public class NaverLoginController {
	
	@Value("${naver.client-id}")
	private String clientId; // = YMEPgkqT9p7r23tbgj3h
	
	@Value("${naver.client-secret}")
	private String clientSecret; // = VaKtGlGPXp
	
	@Value("${naver.redirect-uri}")
	private String redirectUri; // = http://localhost:9010/naverLogin
	
	@Value("${naver.state}")
	private String state; // = RANDOM_STATE
	
	@GetMapping("/naverLogin") //  api/naverLogin
	public String naverLogin() {
		String api_url = "https://nid.naver.com/oauth2.0/authorize?response_type=code&client_id=" + clientId + "&redirect_uri=" + redirectUri + "&state=" + state;
		return "<a href='"+ api_url + "'><img height='50' src='http://static.nid.naver.com/oauth/small_g_in.PNG'/></a>";
	}
	//url에 {}=변수명 표시가 없으면 @RequestParam이나 @RequestBody
	//url에 {}=변수명 표시가 있으면 @PathVariable. {}안에 있는 변수명에 값을 집어넣음
	@GetMapping("/callback")
	public String callback(@RequestParam String code, @RequestParam String state) {
		
		String api_url = "https://nid.naver.com/oauth2.0/token?grant_type=authorization_code&client_id="
			     + clientId + "&client_secret=" + clientSecret + "&redirect_uri=" + redirectUri + "&code=" + code + "&state=" + state;

		//RestTemplate = http 메서드(get,post,put,delete)를 통해 데이터를 json 형식으로 데이터를 처리
		RestTemplate rt = new RestTemplate();
		
		//api_url 주소로 응답받은 결과를 String(문자열)으로 가져와서 사용
		String responseResult = rt.getForObject(api_url, String.class);
		return responseResult;
	}
	
}

 

** @Value : application.properties나 config.properties에 작성한 키 이름과 키에 담긴 값을 가져옴

 

 

** 네이버에서 로그인을 성공했을 때 받는 값

String api_url = "https://nid.naver.com/oauth2.0/token?grant_type=authorization_code&client_id="
     + clientId + "&client_secret=" + clientSecret + "&redirect_uri=" + redirectUri + "&code=" + code + "&state=" + state;
1. clientId = 어디 회사에 들어왔는가
2. clientSecret = 회사에 들어오기 위한 비밀번호
3. redirectUri = 들어오기 위한 심사를 완료했으면 나갈 위치로 전달
4. code = 네이버로부터 무사히 들어왔다는 인증코드를 받음
5. state = CSRF 공격을 방지하기 위해 사용



** @GetMapping("/naverLogin") //  api/naverLogin
public String naverLogin() {
String api_url = "https://nid.naver.com/oauth2.0/authorize?response_type=code&client_id=" + clientId + "&redirect_uri=" + redirectUri + "&state=" + state;
return "<a href='"+ api_url + "'><img height='50' src='http://static.nid.naver.com/oauth/small_g_in.PNG'/></a>";
}

 

↓ ↓ ↓

 

app.get('/naverLogin', function (req, res) {
api_url = 'https://nid.naver.com/oauth2.0/authorize?response_type=code&client_id=' + client_id + '&redirect_uri=' + redirectURI + '&state=' + state;
res.writeHead(200, {'Content-Type': 'text/html;charset=utf-8'});
res.end("</a href='"+ api_url + "'>http://static.nid.naver.com/oauth/small_g_in.PNG'/>");
});


와 맞추는 getmapping

 

 

실행 화면

 

로그인 안했을 때
아이콘을 눌렀을 때
로그인이 성공한 화면

'Springboot-React' 카테고리의 다른 글

이미지 여러개 올리기 2  (0) 2024.08.06
이미지 여러개 올리기 1  (0) 2024.08.06
네이버 로그인 1  (0) 2024.07.30
mysql-react-springboot 연결하기 2  (0) 2024.07.26
mysql-react-springboot 연결하기 1  (0) 2024.07.26