File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
<template>
<div class="login-page page">
<div class="flex-column justify-center align-center content">
<div class="login-wrap pd30 border">
<div v-show="pageStep === 0">
<div class="page-title text-ct mb40">LOGIN</div>
<div class="input-group field mb20">
<input type="text" name="" id="id" class="full-input login-input" placeholder="아이디를 입력하세요"
v-model="member['lgnId']" />
<label for="id" class="login-label">아이디</label>
</div>
<div class="input-group field mb20">
<input type="password" name="" id="pw" class="full-input login-input" placeholder="비밀번호를 입력하세요"
v-model="member['mbrEncptPswd']" @keyup.enter="fnValid" />
<label for="pw" class="login-label">비밀번호</label>
</div>
<div class="find-zone flex justify-end align-center mb40">
<p class="detail-text pl10 pr10" @click="goFindInfo('id')">아이디 찾기
<!-- <router-link :to="{ name: 'FindInfo', params: { type: 'id' } }">아이디 찾기</router-link> -->
</p>
<p class="detail-text pl10 pr0" @click="goFindInfo('pw')">비밀번호 찾기
<!-- <router-link :to="{ name: 'FindInfo', params: { type: 'password' } }">비밀번호 찾기</router-link> -->
</p>
</div>
<button class="large-btn darkg-btn fw-bold" title="로그인" @click="fnValid">
로그인
</button>
</div>
<div v-show="pageStep > 0">
<div class="logo">
<h1 v-show="pageStep < 3" class="text-ct mb30">OTP 설정</h1>
<h1 v-show="pageStep > 2" class="text-ct mb30">OTP 인증</h1>
</div>
<progressBar v-if="pageStep !== 4" :steps="steps" :pageNumber="pageStep" />
<!-- 1,2 step은 최초에만 -->
<div v-show="pageStep === 1">
<p class="mt30 mb30">본인 인증을 위해 Google OTP 인증이 필요합니다. OTP 인증을 위해 아래 링크를 따라 휴대폰에 인증 앱을 설치해주세요.</p>
<div class="flex jusitfy-start align-center mb30 login-step">
<div class="gd-6 pl0">
<a href="https://play.google.com/store/search?q=google+authenticator&c=apps" class="otp-img"><img src="../../../resources/img/google.png" alt="구글스토어 아이콘" ></a>
</div>
<div class="gd-6 pr0">
<a href="https://apps.apple.com/kr/app/google-authenticator/id388497605" class="otp-img"><img src="../../../resources/img/appstore.png" alt="앱스토어 아이콘" ></a>
</div>
</div>
<button class="large-btn blue-btn ml0" title="다음" @click="OTPgenerate()">다음</button>
</div>
<div v-show="pageStep === 2">
<div class="mt30 mb15">
<p class="mb10">설치한 Google OTP 앱으로 아래 QR코드를 스캔하세요 또는 앱에서 수동으로 하단 코드를 직접 입력하세요.</p>
<div class="qr-zone mb10 text-ct" id="qrcode">
<img :src="qrCodeSrc" alt="QR Code" class="inline" />
</div>
<input type="text" class="full-input mb10" :value="otp.encodedKey" disabled>
</div>
<button class="large-btn blue-btn ml0" title="다음" @click="stepGo(3)">다음</button>
</div>
<div v-show="pageStep === 3">
<div class="mt30 mb15">
<input type="text" class="full-input mb10" placeholder="인증코드를 입력해주세요." v-model="otp.onetimePw" @keyup.enter="fnAdminLogin()">
</div>
<button class="large-btn blue-btn ml0" title="인증" @click="fnAdminLogin()" >인증</button>
</div>
<div v-show="pageStep === 4">
<div class="mt30 mb15">
<input type="text" class="full-input mb10" placeholder="인증코드를 입력해주세요." v-model="otp.onetimePw" @keyup.enter="fnAdminLogin()">
</div>
<button class="large-btn blue-btn ml0" title="인증" @click="fnAdminLogin()" >인증</button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { useStore } from "vuex";
import store from "../AppStore";
import { loginProc , findMngrYnByMbr , generateOTP , loginOTP } from '../../../resources/api/login';
import queryParams from "../../../resources/js/queryParams";
import ProgressBar from "../../component/progressbar/ProgressBar.vue";
import VueCookies from "vue-cookies";
export default {
mixins: [queryParams],
data: () => {
return {
pageStep : 0,
member: {
lgnId: null,
mbrEncptPswd: null,
},
steps: ["앱설치", "코드등록", "인증"],
store: useStore(),
isAdminPage: false,
otp: {
lgnId : null,
onetimePw: null,
encodedKey: null,
qrCodeImage: null,
},
redirect: store.state.redirect || null,
};
},
methods: {
loginValidCheck : function () {
if(this.member.lgnId == null || this.member.lgnId.trim() == ''){
alert("아이디를 입력해주세요.")
document.getElementById("id").focus()
return false
}
if(this.member.mbrEncptPswd == null || this.member.mbrEncptPswd.trim() == ''){
alert("비밀번호를 입력해주세요.")
document.getElementById("pw").focus()
return false
}
return true
},
//아이디비밀번호 유효성 & 관리자 여부 확인
async fnValid() {
const vm = this;
if(!this.loginValidCheck()) return
try {
const res = await findMngrYnByMbr(this.member);
if(res.status == 200){
//관리자의 경우
if(res.data.data.mngrYn == "Y") {
//OTP유무 확인
this.$isEmpty(res.data.data.otpUnqNo)? vm.pageStep = 1 : vm.pageStep = 4;
} else {
//일반사용자 로그인 처리
this.fnLogin()
}
}
} catch(error) {
alert(error.response.data.message);
}
},
async fnLogin() {
try {
const res = await loginProc(this.member);
if(res.status == 200) {
store.commit("setAuthorization", res.headers.authorization);
// store.commit("setRefresh", res.headers.refresh);
// this.$cookies.set('refresh',res.headers.refresh)
/** jwt토큰 복호화 **/
const base64String = store.state.authorization.split('.')[1];
const base64 = base64String.replace(/-/g, '+').replace(/_/g, '/');
const mbr = JSON.parse(decodeURIComponent(window.atob(base64).split('').map(function (c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join('')));
store.commit("setMbrId", mbr.mbrId);
store.commit("setMbrNm", mbr.mbrEncptFlnm);
store.commit("setAuthrtNm", mbr.authrtNm);
store.commit("setAuthrtTypeLvl", mbr.authrtTypeLvl);
store.commit('setRoles', mbr.roles);
/** jwt토큰 복호화 **/
// const url = this.restoreRedirect('redirect');
// !this.$isEmpty(url) ? this.$router.push({path: url}) : this.$router.push({path: '/'})
// const isAdmin = mbr.roles.some(role => role.authority === 'ROLE_ADMIN');
// isAdmin? this.$router.push({path:'/kdm/main.page'}) : this.$router.push({path:'/'});
const isAdmin = mbr.roles.some(role => role.authority === 'ROLE_ADMIN');
if(this.redirect){
if (isAdmin && this.redirect.indexOf('/kdm') !== -1) {
store.commit('setRedirect', null)
this.$router.push({ path: '/kdm/main.page' });
return;
}
}
this.$router.push({path: '/'});
}
} catch(error) {
console.log('error',error)
}
},
// 관리자 OTP 발급
async OTPgenerate() {
try {
const res = await generateOTP(this.member)
if(res.status == 200) {
this.otp = res.data.data;
this.stepGo(2)
}
} catch(error) {
alert(error.response.data.message);
}
},
otpLoginValid : function() {
if(this.otp.onetimePw == null || this.otp.onetimePw.trim() == '') {
alert("2차비밀번호를 입력해주세요.")
return false
}
if(!this.otp.onetimePw.match(/^\d{6}$/)) {
alert("2차비밀번호는 6자리 숫자만 입력 가능합니다.");
return false;
}
return true
},
// //관리자 OTP 로그인
async fnAdminLogin() {
if(!this.otpLoginValid()) return
this.otp.lgnId = this.member.lgnId
try {
const res = await loginOTP(this.otp)
if(res.status == 200){
this.fnLogin()
// this.$router.push({path: '/' });
}
} catch(error) {
alert(error.response.data.message);
}
},
goFindInfo: function(type) {
this.$router.push({ path: "/cmmn/findInfo.page", query: { 'type': type }});
},
stepGo: function (num) {
this.pageStep = num
},
},
watch: {
},
computed: {
qrCodeSrc() {
return `data:image/png;base64,${this.otp.qrCodeImage}`;
},
},
components: {
ProgressBar : ProgressBar
},
created() {},
mounted() {
},
};
</script>