-
Laravel + nuxt 소셜로그인 #sanctum #social #로그인 #소셜 #vue #nuxt #apiLaravel 2023. 3. 23. 22:50반응형SMALL
# What?
- API 방식으로 소셜로그인 구현하는 방법
# How?
- 기본원리
-> 클라이언트 서버쪽에서 API 서버쪽으로 redirect
-> API 서버에서 소셜로그인 후 callback 받기
-> callback 받은 후 로그인 or 가입처리 후 토큰생성 후 클라이언트쪽에 토큰값 넘겨주기
-> 클라이언트쪽에서 socialLogin페이지 따로 만들어놓고 token params받아 로그인 시도하기
-> API쪽에서 login 메소드에 token으로 로그인 요청 있는지를 확인하여 유저정보 및 token값 리턴하기
-> 클라이언트쪽에서 해당 정보로 로그인처리 완료하기
1. 백엔드 세팅
- 백엔드 sanctum 세팅 (sanctum글 참고)
- .env 세팅 -> 프론트 서버 url 및 소셜키값 세팅
@ .env
APP_CLIENT_URL=http://localhost:3000
@ app.php
'client_url' => env('APP_CLIENT_URL', 'https://whatpick.com'),
- 컨트롤러 세팅
@ Api/UserController - login과, socialLogin 메소드가 핵심
public function login(Request $request) { // 소셜로그인 시도 시 if($request->token && auth()->user()){ return $this->respondSuccessfully([ "token" => $request->token, "user" => UserResource::make(auth()->user()) ]); } $data = $request->validate([ "ids" => "required|string|max:500", "password" => "required|string|max:500", ]); if(auth()->attempt($request->only("ids", "password"))) { session()->regenerate(); $token = auth()->user()->createToken("auth"); return $this->respondSuccessfully([ "token" => $token->plainTextToken, "user" => UserResource::make(auth()->user()) ]); } return throw ValidationException::withMessages([ "ids" => [ __("socialLogin.invalid") ] ]); } public function openSocialLoginPop($social) { return Socialite::driver($social)->stateless()->redirect(); } public function socialLogin(Request $request, $social) { $socialUser = Socialite::driver($social)->stateless()->user(); // 일단 네이버 $user = User::where("social_id", $socialUser->id)->where("social_platform", $social)->first(); if(!$user) { $user = User::create([ "name" => $social, "social_id" => $socialUser->id, "social_platform" => $social ]); } $token = $user->createToken("auth")->plainTextToken; Auth::login($user); return redirect(config("app.client_url")."/socialLogin?token=".$token); }
- 프론트 세팅
@ socialLogin.vue
<template> </template> <script> export default { data(){ return { token: this.$route.query.token ? this.$route.query.token : null, } }, mounted() { this.$auth.loginWith('laravelSanctum', { data: { token:this.token } }).then(response => { this.$router.back(); }).catch((e) => { alert("소셜로그인에 실패하였습니다."); return this.$router.push("/"); }) } } </script>
@ login.vue
<template> <main class="login"> <div class="container col-group"> <div class="left-wrap row-group"> <div class="login-wrap"> <form @submit.prevent="login" @keydown="() => {form.errors.clear()}"> <h2 class="login-title scd6"> <span class="scd6">왓픽</span> 회원 로그인 </h2> <div class="login-form row-group"> <input type="text" placeholder="아이디를 입력해 주세요." v-model="form.ids"> <p class="m-input-error" v-if="form.errors.has('ids')">{{form.errors.get("ids")}}</p> <input type="password" placeholder="비밀번호를 입력해 주세요." v-model="form.password"> <p class="m-input-error" v-if="form.errors.has('password')">{{form.errors.get("password")}}</p> <button type="submit" class="login-submit scd5">로그인</button> <div class="col-group"> <label for="auto_login"> <input type="checkbox" id="auto_login"> <span class="check-icon"></span> 자동로그인 </label> <div class="find-account col-group"> <a href="find_id1.html">아이디 찾기</a> <a href="find_pw1.html">비밀번호 찾기</a> </div> </div> </div> <div class="sns-login-wrap col-group"> <p class="title"> <strong>SNS</strong> 계정 로그인 </p> <ul class="sns-login-list col-group"> <li> <a :href="`${$store.state.domain}/openLoginPop/naver`"> <img src="/images/sns_login_naver.png" alt=""> </a> </li> <li> <a :href="`${$store.state.domain}/openLoginPop/kakao`"> <img src="/images/sns_login_kakao.png" alt=""> </a> </li> <li> <a :href="`${$store.state.domain}/openLoginPop/google`"> <img src="/images/sns_login_facebook.png" alt=""> </a> </li> <li> <a :href="`${$store.state.domain}/openLoginPop/facebook`"> <img src="/images/sns_login_google.png" alt=""> </a> </li> </ul> </div> </form> </div> <a href="join.html" class="join-wrap col-group"> <div class="txt-box"> <h3 class="join-title scd5">아직 회원이 아니신가요?</h3> <p class="title"> <span class="red scd5">회원가입</span> 후 다양한 서비스를 만나보세요 </p> </div> <i class="xi-arrow-right"></i> </a> </div> <div class="right-wrap"> <div class="txt-box"> <span class="notice"> <i class="xi-info"></i> </span> <p class="title"> 왓픽은 중고차 <span class="scd5">구매 도우미</span> 입니다. </p> <p class="txt"> 왓픽은 중고차를 판매하지 않습니다. 왓픽은 중고차 매물의 진짜 정보를 제공합니다. </p> </div> <img src="/images/login_bg.png" alt=""> </div> </div> </main> </template> <script> import Form from "../utils/Form"; export default { name: 'Login', data(){ return { form : new Form(this.$axios, { ids:"", password:"" }) } }, methods: { login(){ this.$auth.loginWith('laravelSanctum', { data: this.form.data() }); /*this.$axios.get('/sanctum/csrf-cookie').then(response => { this.form.post("/api/login") .then(response => { this.$axios.defaults.headers.common["Authorization"] = `Bearer ${response.data.token}`; this.$store.commit("setToken", response.data.token); this.$store.commit("setUser", response.data.user); console.log(this.$store.state.user); }) .catch(error => { }) });*/ } } } </script>
* 실 배포 후 필수세팅
SESSION_DOMAIN=.whatpick.com // 본 도메인 SANCTUM_STATEFUL_DOMAINS=whatpick.com // 클라이언트 도메인
LIST'Laravel' 카테고리의 다른 글
초성검색 (ㄱ,ㄴ,ㄷ,ㅁ,ㅂ...) (0) 2023.04.04 유튜브 고유아이디 및 썸네일 url 얻기 #Youtube #유튜브 #썸네 (0) 2023.04.02 Custom validation throw 하는법 (422 에러 throw) (0) 2023.03.23 아임포트 계좌이체, 가상계좌 연동 시 주의사항 (419 error) # CSRF #TOKEN #웹훅 (0) 2023.02.13 구글 크롬 번역기 웹사이트에 적용하는법 (0) 2023.01.15