Closed AMYMEME closed 3 years ago
사실 뷰를 처음 써봐서 헤맨 과정을 적음
mounted() {
const script = document.createElement('script')
script.src = {JS script URL}
script.onload = () => {
this.initiate()
}
document.body.appendChild(script)
},
...
data() {
return {
initiate: (store) => {
const naverLogin = new naver.LoginWithNaverId(
...
이런식으로 해결
[x] 콜백 적용 네이버는 js 라이브러리에서 콜백함수 기능을 지원하는데, 이걸 사용하려면 콜백 페이지(리다이렉트 페이지)에서 처리를 해야함 따라서 위의 외부 js 스크립트를 적용하는 페이지가 두개있는것 (로그인 페이지, 콜백 페이지) 로그인 페이지에서는 init()만하고(버튼을 표시하기 위해서), 콜백 페이지에서는 init()이후에 콜백함수를 정의하면 됨(리다이렉트가 되면서 가져온 내용을 바탕으로 콜백함수가 실행되므로 로그인 페이지에서 콜백 설정해봤자 의미없음)
[x] 제공하는 JS에서 인증토큰을 기반으로 정보도 가져올 수 있기 때문에 백엔 서버에서 회원 프로필 조회 API
를 사용하지 않아도 됨
백엔서버에서 만약 따로 회원 프로필 조회 API를 쓰면 약간 골치아픈게, fe -> be -> 회원 프로필 조회 -> be로 리퀘스트와 리스펀스가 전달되므로, be에서 리스펀스가 두개라 회원을 디비에 저장할 경우 앞의 be의 url을 분리하는 등의 작업을 따로 해야함
url 분리가 안되면 빈 회원이 저장되거나...여러 문제가 생길수 있음
[x] 나는 네이버<->board-golang(내 웹페이지)도 토큰으로 작용하지만, 내 백엔드서버에서도 jwt를 만들어서 fe로 제공하고, Fe에서는 그걸 렌더링해서 헤더에 붙이고 로그인여부를 페이지 헤더바에 붙이려하는데(로그인 안될시 로그인 버튼, 아니면 로그아웃 버튼 등) 그러기 위해서 vue store를 이용함 문제는 js 스크립트를 적용할 때에 data.initiate함수를 이용했는데, 이 함수를 이용했을 때 store에 접근하기가 쉽지 않았음 method 도 인식하지 못하고, 그렇다고 이걸 mounted나 created로 빼자니 스크립트 인식을 못하는 등의 문제가 발생 -> 여러 삽질 끝에 this.initiate()를 this.initiate(this.$store)로 해주고 initiate에서 store.dispatch로 be에 네이버에서 가져온 이름과 uniqID를 이용해 golang서버로 전달하기로 함
정리하면,
로그인 창-> js script import 및 네아로연동 시도-> 처음 로그인시 이름 가져옴-> 안가져올 시 리다이렉트 페이지에서 콜백함수에 의해 다시 정보 가져오라고 함 -> 가져왔으면 가져온 사용자의 이름과 유니크 아이디를 golang으로 전달 -> golang에서는 provider가 naver고, provider_id가 유니크 아이디인 열을 확인-> 존재하지 않으면 디비에 새로 저장 이후 jwt값을 fe에 전달-> 존재하면 그냥 jwt값을 fe에 전달 -> fe에서는 받은 jwt값을 헤더에 붙이고(axios 렌더링) 로컬 스토리지에도 저장 -> 메인페이지로 리다이렉트 및 헤더바 상태 변경됨(로컬 스토리지에 값 있으면 상태 변경됨 by vue store)
이번에는 js sdk를 이용하지 않고, REST API 를 이용했더니 cors 문제 발생
mounted() {
const script = document.createElement('script')
script.src = {JS script URL}
script.onload = (() => {
this.kakaoLogin(this.$store)
})
document.body.appendChild(script)
},
...
methods: {
kakaoLogin(store) {
Kakao.init('JS APP ID')
Kakao.Auth.createLoginButton({
container: '#kakao-login-btn',
success: function() {
Kakao.API.request({
url: '/v2/user/me',
success: function (res) {
store.dispatch('loginWithKakao', res)
...
},
fail: function () {
alert('사용자 정보를 가져오는 데에 실패하였습니다. 다시 시도해 주세요.');
window.location.replace('/login');
},
})
}
})
},
...
이런식으로 해결
[x] 네이버와 다르게 콜백함수를 리다이렉트 페이지에서 쓰지 않아도 success function을 지정할 수 있음 네이버도 이런 기능이 있나 다시 API 명세서 찾아보기
[x] 마찬가지로, 제공하는 JS에서 인증토큰을 기반으로 정보도 가져올 수 있기 때문에 백엔 서버에서 회원 프로필 조회 API
를 사용하지 않아도 됨
[x] 내 사이트 Jwt도 네이버처럼 똑같이 만듦 이번에는 data가 아닌 methods를 이용함 이게 더 의미가 통해보임 네이버도 이렇게 바꿀것
카카오가 솔직히 API 명세가 깔끔해보였다 (내가 두번째 구현해 보는거라 쉬운 걸 수도 있음)
[x] 구글도 컴포넌트로 분리하기
[x] 인증이 되도 로그인 페이지에 접근할 수 없도록 로그인 페이지에서 data를 isLoggined 같은 것을 하나 가지도록하고, 로그인이 되면 각 자식 컴포넌트들 (구글, 네이버, 카카오)이 부모 컴포넌트인 login isLoggined값을 바꾸던가 하기, 아니면 store값에 따라 로그인 창 접근 안되게 하는것도 ㄱㅊ아보임(이게더 간편할듯)
라이브러리 이용한거 지우고 js script SDK를 이용해보기로 함
mounted() {
const script = document.createElement('script')
script.src = 'https://apis.google.com/js/api.js'
script.onload = (() => {
this.googleLogin(this.$store)
});
document.body.appendChild(script)
...
methods: {
googleLogin(store) {
var GoogleAuth
gapi.load('client:auth2', function () {
gapi.client.init({
'apiKey': 'app-key',
'clientId': 'client-id.googleusercontent.com',
'scope': 'https://www.googleapis.com/auth/userinfo.profile',
'discoveryDocs': ["https://people.googleapis.com/$discovery/rest?version=v1"]
}).then(function () {
GoogleAuth = gapi.auth2.getAuthInstance();
var googleLoginBtn = document.getElementById('google-login-btn');
googleLoginBtn.addEventListener('click', function () {
if (GoogleAuth.isSignedIn.get()) {
gapi.client.people.people.get({
'resourceName': 'people/me',
'requestMask.includeField': 'person.names'
}).then((res) => {
store.dispatch('loginWithGoogle', res.result.names[0])
.then(() => store.commit('backRedirect'))
})
} else {
GoogleAuth.signIn();
}
})
})
})
},
},
...
이런식으로 해결
[x] 네이버나 카카오와 살짝 다르게 gapi.client는 시작시에 API에 해당하는 scope와 discoveryDocs를 선택해야한다. 이걸 헷갈려서 (예제 코드에는 drive API를 기준으로 설명하기 때문) 조금 헤매었다.
[x] 마찬가지로, 제공하는 JS에서 인증토큰을 기반으로 정보도 가져올 수 있기 때문에 백엔 서버에서 회원 프로필 조회 API
를 사용하지 않아도 됨
[x] 내 사이트 Jwt도 똑같이 만듦 솔직히 API 명세 진짜 읽기 힘들었다.. 영어의 문제라기보단 가독성이 넘 떨어짐...
[x] 이미 구글 로그인이 되어있을 때는 ㄱㅊ지만, 새로 로그인할 경우 버튼을 한 번더 눌러야 하는 문제 발생
methods: {
googleLogin(store) {
var GoogleAuth
gapi.load('client:auth2', function () {
gapi.client.init({
'apiKey': 'app-key',
'clientId': 'client-id.googleusercontent.com',
'scope': 'https://www.googleapis.com/auth/userinfo.profile',
'discoveryDocs': ["https://people.googleapis.com/$discovery/rest?version=v1"]
}).then(function () {
GoogleAuth = gapi.auth2.getAuthInstance();
var googleLoginBtn = document.getElementById('google-login-btn');
googleLoginBtn.addEventListener('click', function () {
GoogleAuth.isSignedIn.listen(() => {
gapi.client.people.people.get({
'resourceName': 'people/me',
'requestMask.includeField': 'person.names'
}).then((res) => {
store.dispatch('loginWithGoogle', res.result.names[0])
.then(() => store.commit('backRedirect'))
})
});
if (!GoogleAuth.isSignedIn.get()) {
GoogleAuth.signIn();
} else {
gapi.client.people.people.get({
'resourceName': 'people/me',
'requestMask.includeField': 'person.names'
}).then((res) => {
store.dispatch('loginWithGoogle', res.result.names[0])
.then(() => store.commit('backRedirect'))
})
}
})
})
})
},
},
...
중복 코드가 발생한다는 문제점이 있지만, 따로 함수로 빼기에는 store 처리를 어떻게 해야할 지 모르겠고,, 일단 이렇게 처리함
naver 인증 구현 이슈
네이버에서 제공한 js 스크립트상에서 로그인을 시도하면,
[리다이렉트 url]/auth/naver#access_token={access_token}&state={state}&token_type=bearer&expires_in=3600
으로 응답을 뱉는다.해시뱅은 프래그먼트로 서버에 값이 전달되지 않아서 저 값들을 조회할수가 없음
-> FIXED 리다이렉트 url을 fe쪽으로 설정하고, 거기서 다시 be로 토큰값을 전달!