Merge branch 'master' of http://118.219.150.34:50501/DBNT/kcscDev
commit
eb12c300f5
|
|
@ -4,7 +4,8 @@ const URL = {
|
|||
MAIN : "/", //메인페이지
|
||||
|
||||
LOGIN : "/login", //로그인
|
||||
ERROR : "/error", //로그인
|
||||
JOIN : "/join", //회원가입
|
||||
ERROR : "/error", //에러
|
||||
|
||||
//ABOUT
|
||||
ABOUT : "/about", //사이트소개
|
||||
|
|
|
|||
|
|
@ -84,4 +84,4 @@ button {cursor: pointer;}
|
|||
|
||||
|
||||
.detailInfoDiv > div > p { display: inline; }
|
||||
.detailInfoDiv > div > input {margin-right: 5px;}
|
||||
.detailInfoDiv > div > input {margin-right: 5px;}
|
||||
|
|
|
|||
|
|
@ -12,13 +12,26 @@
|
|||
.Plogin .login_box input[type=password]:-ms-input-placeholder {color: #aaa; opacity: 1;}
|
||||
.Plogin .login_box button {display: block; position: absolute; left: 435px; top: 70px; width: 160px; height: 110px; border-radius: 8px; color: #fff; font-size: 20px; font-weight: 500; text-align: center; line-height: 110px; background: #169bd5;}
|
||||
.Plogin .login_box button span {display: block; position: relative; height: 100%;}
|
||||
.Plogin .login_box .chk {margin-top: 20px; font-size: 0;}
|
||||
.Plogin .login_box .chk {margin-top: 20px;}
|
||||
.Plogin .login_box .chk em {display: inline-block; height: 30px; margin-left: 40px; color: #666; font-size: 16px;}
|
||||
.Plogin .list {margin-top: 44px; padding: 0 360px;}
|
||||
.Plogin .list li {position: relative; padding-left: 15px; color: #666; font-size: 16px; line-height: 26px;}
|
||||
.Plogin .list li::before {content: ""; display: block; position: absolute; left: 0; top: 12px; width: 4px; height: 4px; background: #666;}
|
||||
.Plogin .list li + li {margin-top: 5px;}
|
||||
|
||||
.Pjoin h1 {color: #222; font-size: 48px; font-weight: 500; letter-spacing: -2px; line-height: 48px; text-align: center;}
|
||||
.Pjoin .join_box {position: relative; width: 690px; margin: 54px auto 0; padding: 70px 95px 120px 95px ; border: 1px solid #dde2e5; border-radius: 25px; box-shadow: 3px 4px 5px #ccc;}
|
||||
.Pjoin .join_box input[type=text],
|
||||
.Pjoin .join_box input[type=password] {width: 100%; height: 46px; padding: 0 20px; border: 0; border-radius: 8px; color: #666; font-size: 16px; background: #f5f5f5;}
|
||||
.Pjoin .join_box .group input + input {margin-top: 18px;}
|
||||
.Pjoin .join_box input[type=text]:-ms-input-placeholder,
|
||||
.Pjoin .join_box input[type=password]:-ms-input-placeholder {color: #aaa; opacity: 1;}
|
||||
.Pjoin .join_box .chk {margin-top: 20px;}
|
||||
.Pjoin .join_box .chk em {display: inline-block; height: 30px; margin-left: 40px; color: #666; font-size: 16px;}
|
||||
.Pjoin .join_box button {width: 500px;height: 50px;border-radius: 8px;color: #fff;font-size: 20px;font-weight: 500;text-align: center;line-height: 50px;background: #169bd5;}
|
||||
.Pjoin .join_box button span {display: block; position: relative; height: 100%;}
|
||||
.Pjoin .join_box .list li {position: relative; padding-left: 15px; color: #666; font-size: 16px; line-height: 26px;}
|
||||
.Pjoin .join_box .list li + li {margin-top: 5px;}
|
||||
|
||||
|
||||
/* Board */
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
import {Link, useLocation, useNavigate} from 'react-router-dom';
|
||||
import * as EgovNet from 'api/egovFetch';
|
||||
|
||||
import URL from 'constants/url';
|
||||
import CODE from 'constants/code';
|
||||
import Row from 'react-bootstrap/Row';
|
||||
import Col from 'react-bootstrap/Col';
|
||||
|
||||
import { getLocalItem, setLocalItem, setSessionItem } from 'utils/storage';
|
||||
|
||||
function EgovLoginContent(props) {
|
||||
|
|
@ -113,11 +116,16 @@ function EgovLoginContent(props) {
|
|||
<input type="password" name="" title="비밀번호" placeholder="비밀번호"
|
||||
onChange={e => setUserInfo({ ...userInfo, password: e.target.value })} />
|
||||
</span>
|
||||
<div className="chk">
|
||||
<label className="f_chk" htmlFor="saveid" ref={checkRef}>
|
||||
<input type="checkbox" name="" id="saveid" onChange={handleSaveIDFlag} checked={saveIDFlag}/> <em>ID저장</em>
|
||||
</label>
|
||||
</div>
|
||||
<Row className="chk justify-content-between">
|
||||
<Col xs={3}>
|
||||
<label className="f_chk" htmlFor="saveid" ref={checkRef}>
|
||||
<input type="checkbox" name="" id="saveid" onChange={handleSaveIDFlag} checked={saveIDFlag}/> <em>ID저장</em>
|
||||
</label>
|
||||
</Col>
|
||||
<Col xs={3}>
|
||||
<Link to={URL.JOIN}><em>회원가입</em></Link>
|
||||
</Col>
|
||||
</Row>
|
||||
<button type="button" onClick={submitFormHandler}><span>LOGIN</span></button>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
import React from 'react'
|
||||
|
||||
function InfoShareChk() {
|
||||
return (
|
||||
<ul className="list">
|
||||
<li>건설기준 포털시스템(KCSC)은 회원님께 원활한 서비스 제공을 위해 최소한의 개인정보를 수집하고 있으며, 각 목적 별로 수집하는 개인정보를 다음과 같이 정하고 있습니다.</li>
|
||||
<li className="no_dot"> </li>
|
||||
<li className="no_dot">◌ 수집하는 개인정보의 항목</li>
|
||||
<li className="no_dot"> 수집항목: 아이디(ID), 비밀번호, 이메일(e-mail)</li>
|
||||
<li className="no_dot">◌ 개인정보의 수집 및 이용 목적</li>
|
||||
<li className="no_dot"> 이용목적 : 건설기준 포털시스템(KCSC) 회원가입 및 Q&A 작성</li>
|
||||
<li className="no_dot">◌ 개인정보의 보류 및 이용기간</li>
|
||||
<li className="no_dot"> 회원가입정보 : 탈퇴시까지</li>
|
||||
<li className="no_dot">◌ 정보주체의 동의 거부 권리 및 그에 따른 불이익 사항</li>
|
||||
<li className="no_dot"> </li>
|
||||
<li>귀하는 건설기준 포털시스템(KCSC) 이용을 위한 개인정보의 수집·이용 동의를 거부할 권리가 있습니다. 다만, 개인정보의 수집·이용 동의를 거부할 경우 건설기준 포털시스템(KCSC) 일부 기능에 대한 서비스 이용에 제한을 받으실 수 있습니다.</li>
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
export default InfoShareChk;
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import {Link, useLocation, useNavigate} from 'react-router-dom';
|
||||
import * as EgovNet from 'api/egovFetch';
|
||||
|
||||
import URL from 'constants/url';
|
||||
import CODE from 'constants/code';
|
||||
import Row from 'react-bootstrap/Row';
|
||||
import Col from 'react-bootstrap/Col';
|
||||
|
||||
import { getLocalItem, setLocalItem, setSessionItem } from 'utils/storage';
|
||||
import EgovLoginContent from "../EgovLoginContent";
|
||||
import InfoShareChk from "./InfoShareChk";
|
||||
|
||||
function Join(props) {
|
||||
console.group("JoinContent");
|
||||
console.log("[Start] JoinContent ------------------------------");
|
||||
console.log("JoinContent [props] : ", props);
|
||||
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
console.log("JoinContent [location] : ", location);
|
||||
|
||||
const [userInfo, setUserInfo] = useState({ id: '', email: '', password: '' });
|
||||
const [infoShareChk, setInfoShareChk] = useState(false);
|
||||
|
||||
const submitFormHandler = (e) => {
|
||||
console.log("JoinContent submitFormHandler()");
|
||||
|
||||
const loginUrl = "/auth/join"
|
||||
const requestOptions = {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(userInfo)
|
||||
}
|
||||
|
||||
EgovNet.requestFetch(loginUrl,
|
||||
requestOptions,
|
||||
(resp) => {
|
||||
let resultVO = resp.resultVO;
|
||||
let jToken = resp?.jToken || null;
|
||||
|
||||
setSessionItem('jToken', jToken);
|
||||
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
console.log("------------------------------JoinContent [End]");
|
||||
console.groupEnd("JoinContent");
|
||||
|
||||
const infoShareBtn = () =>{
|
||||
setInfoShareChk(true)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container">
|
||||
<div className="c_wrap">
|
||||
{/* <!-- Location --> */}
|
||||
<div className="location">
|
||||
<ul>
|
||||
<li><Link to={URL.MAIN} className="home" >Home</Link></li>
|
||||
<li><Link to={URL.LOGIN}>로그인</Link></li>
|
||||
<li>회원가입</li>
|
||||
</ul>
|
||||
</div>
|
||||
{/* <!--// Location --> */}
|
||||
|
||||
<div className="layout">
|
||||
<div className="contents" id="contents">
|
||||
{/* <!-- 본문 --> */}
|
||||
<div className="Pjoin">
|
||||
<h1>회원가입</h1>
|
||||
<div className="join_box">
|
||||
{infoShareChk?(
|
||||
<form name="" method="" action="" >
|
||||
<span className="group">
|
||||
<input type="text" name="" title="아이디" placeholder="아이디" value={userInfo?.id}
|
||||
onChange={e => setUserInfo({ ...userInfo, id: e.target.value })} />
|
||||
<input type="text" name="" title="이메일" placeholder="이메일" value={userInfo?.email}
|
||||
onChange={e => setUserInfo({ ...userInfo, email: e.target.value })} />
|
||||
<input type="password" name="" title="비밀번호" placeholder="비밀번호"
|
||||
onChange={e => setUserInfo({ ...userInfo, password: e.target.value })} />
|
||||
<input type="password" name="" title="비밀번호 확인" placeholder="비밀번호 확인"
|
||||
onChange={e => setUserInfo({ ...userInfo, passwordConfirm: e.target.value })} />
|
||||
</span>
|
||||
<ul className="list">
|
||||
<li>비밀번호는 6~12자의 영문 대/소문자, 숫자, 특수문자를 혼합해서 사용하실 수 있습니다.</li>
|
||||
<li>쉬운 비밀번호나 자주 쓰는 사이트의 비밀번호가 같을 경우, 도용되기 쉬우므로 주기적으로
|
||||
변경하셔서 사용하는 것이 좋습니다.</li>
|
||||
</ul>
|
||||
<button type="button" onClick={submitFormHandler}><span>회원가입</span></button>
|
||||
</form>
|
||||
):(
|
||||
<Row className="justify-content-end">
|
||||
<Col xs={12}>
|
||||
<InfoShareChk/>
|
||||
</Col>
|
||||
<Col xs={"auto"}>
|
||||
<button onClick={infoShareBtn}>동의하기</button>
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{/* <!--// 본문 --> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Join;
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
import * as EgovNet from "../../api/egovFetch";
|
||||
import React, {useEffect, useState} from "react";
|
||||
import SbItem from "./SbItem";
|
||||
import {Col, Row} from "react-bootstrap";
|
||||
import {VwDiv, VwPtag} from "./Sb.style";
|
||||
|
||||
/*최상위 컴포넌트*/
|
||||
export function Maincontent({docCode}) {
|
||||
const [doccode, setdoccode] = useState('');
|
||||
const [docname, setdocname] = useState('');
|
||||
//TODO 맨처음 목차코드 및 목차제목 안나오는 문제 수정
|
||||
function setdoccodandname(doccode, docname) {
|
||||
setdoccode(doccode);
|
||||
setdocname(docname);
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Col>{doccode+' '+docname}</Col>
|
||||
<Row>
|
||||
<CodeTree docCode={docCode} setdoccodandname={setdoccodandname}/>
|
||||
<CodeCotentData docCode={docCode}/>
|
||||
</Row>
|
||||
</div>)
|
||||
}
|
||||
|
||||
/*글 트리 컴포넌트*/
|
||||
export function CodeTree({docCode, setdoccodandname}) {
|
||||
const [codeTree, setcodeTree] = useState([]);
|
||||
const [doccode, setdoccode] = useState(docCode);
|
||||
let data = [];
|
||||
const getCodeTree = () => {
|
||||
EgovNet.requestFetch(
|
||||
'/standardCode/getCodeTree.do',
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({})
|
||||
}, (item) => {
|
||||
data = item.result.codeTree;
|
||||
const nest = (menuData, parent_seq = null, link = 'parent_seq') =>
|
||||
menuData.filter(item => item[link] === parent_seq)
|
||||
.map(item => ({...item, childrens: nest(menuData, item.seq)}));
|
||||
setcodeTree(nest(data));
|
||||
}, () => {
|
||||
})
|
||||
}
|
||||
useEffect(() => {
|
||||
getCodeTree()
|
||||
}, [])
|
||||
|
||||
return (<Col>
|
||||
{codeTree.map(resp => {
|
||||
return (
|
||||
<SbItem item={resp} openDocCode={doccode} updateDocCode={setdoccodandname}/>
|
||||
)
|
||||
}
|
||||
)}
|
||||
</Col>)
|
||||
}
|
||||
|
||||
|
||||
/*글 내용+목차 분리 컴포넌트*/
|
||||
//TODO 추가 분리 작업 필요
|
||||
export function CodeCotentData({docCode}) {
|
||||
const [codeChapter, setcodeChapter] = useState([]);
|
||||
const [codeContent, setcodeContetn] = useState([]);
|
||||
let result =[];
|
||||
const getCodeDetail = (docCode) => {
|
||||
EgovNet.requestFetch(
|
||||
'/standardCode/getCodeDetailInfo.do',
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
docCode: docCode
|
||||
})
|
||||
}, (item) => {
|
||||
result = item.result.document;
|
||||
}, () => {
|
||||
})
|
||||
}
|
||||
useEffect(() => {
|
||||
getCodeDetail(docCode)
|
||||
setcodeChapter(result.map(item =>{
|
||||
const isTitle = item.full_content.includes(item.group_title);
|
||||
return(
|
||||
<VwDiv depth={item.cont_level} isTitle={isTitle}>
|
||||
<VwPtag href="#" isTitle={isTitle} onClick={() => {
|
||||
document.location.hash="#"+item.cont_type_cd;
|
||||
}} dangerouslySetInnerHTML={ {__html: item.group_title} }>
|
||||
</VwPtag>
|
||||
</VwDiv>
|
||||
)
|
||||
}))
|
||||
setcodeContetn(result.map(item =>{
|
||||
const isTitle = item.full_content.includes(item.group_title);
|
||||
const docLinkReg = /([A-Z]{3,5}(\s[0-9]{2}){3,4})/g
|
||||
const docPartReg = /\((?:표|그림|부록)?\s*([A-Z]\.)?(?!\d\))\d+(\.\d+)*(\s?\(\d\))?(-\d+)?(?:\s*[A-Z])?\)/g
|
||||
if(docLinkReg.test(item.full_content)){
|
||||
const docCodeAry = item.full_content.match(docLinkReg);
|
||||
const docCodeMap = new Map();
|
||||
for(let i=0; i<docCodeAry.length; i++) {
|
||||
const docCode = docCodeAry[i];
|
||||
docCodeMap.set(docCode, '<a class="docLink" href="/standardCode/viewer/' + docCode + '" target="_blank">' + docCode + '</a>')
|
||||
}
|
||||
docCodeMap.forEach((docCodeLink, docCode)=>{
|
||||
item.full_content = item.full_content.replaceAll(docCode, docCodeLink);
|
||||
})
|
||||
if(docPartReg.test(item.full_content)){
|
||||
|
||||
const docPartAry = item.full_content.match(docPartReg);
|
||||
const docPartMap = new Map();
|
||||
for(let i=0; i<docPartAry.length; i++) {
|
||||
const docPart = docPartAry[i];
|
||||
const docCodeMatch = item.full_content.substring(item.full_content.indexOf(docPart)-30).match(docLinkReg);
|
||||
let docCode = null;
|
||||
if (docCodeMatch){
|
||||
docCode = docCodeMatch[0];
|
||||
}
|
||||
//const docCode = item.full_content.substring(item.full_content.indexOf(docPart)-30).match(docLinkReg)[0];
|
||||
docPartMap.set(docPart, docPart +
|
||||
'<key class="bookmark" data-doccode="'+docCode+'" data-docpart="'+docPart.replace('(', '').replace(')', '')+'">'+
|
||||
'<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 16 16" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M2 4a2 2 0 0 1 2-2h6a2 2 0 0 1 2 2v11.5a.5.5 0 0 1-.777.416L7 13.101l-4.223 2.815A.5.5 0 0 1 2 15.5V4z"></path><path d="M4.268 1A2 2 0 0 1 6 0h6a2 2 0 0 1 2 2v11.5a.5.5 0 0 1-.777.416L13 13.768V2a1 1 0 0 0-1-1H4.268z"></path></svg>'+
|
||||
'</key>');
|
||||
}
|
||||
docPartMap.forEach((docPartLink, docPart)=>{
|
||||
item.full_content = item.full_content.replaceAll(docPart, docPartLink);
|
||||
})
|
||||
}
|
||||
if(item.full_content.includes("<table")){
|
||||
item.full_content = item.full_content.replace('<table ', '<table class="table table-bordered "')
|
||||
}
|
||||
if(item.error_cd !== null){
|
||||
item.full_content = "<div class='errorText'>"+item.error_cd+"</div>"+item.full_content;
|
||||
}
|
||||
item.full_content = item.full_content+"<hr>"
|
||||
return(
|
||||
<VwDiv depth={item.cont_level} isTitle={isTitle} id={item.cont_type_cd} dangerouslySetInnerHTML={ {__html: item.full_content} }></VwDiv>
|
||||
)
|
||||
}
|
||||
}))
|
||||
}, [docCode])
|
||||
|
||||
return (<>
|
||||
<CodeChapter codeChapter={codeChapter}/>
|
||||
<CodeContent codeContent={codeContent}/>
|
||||
</>)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*글 목차 컴포넌트*/
|
||||
export function CodeChapter({codeChapter}) {
|
||||
return (<>{codeChapter}</>)
|
||||
}
|
||||
|
||||
/*글 내용 컴포넌트*/
|
||||
export function CodeContent({codeContent}) {
|
||||
return (<>{codeContent}</>)
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ import EgovError from 'components/EgovError';
|
|||
|
||||
import EgovMain from 'pages/main/EgovMain';
|
||||
import EgovLogin from 'pages/login/EgovLogin';
|
||||
import Join from 'pages/login/join/Join';
|
||||
|
||||
//ABOUT
|
||||
import EgovAboutSite from 'pages/about/EgovAboutSite';
|
||||
|
|
@ -146,9 +147,9 @@ const SecondRoutes = () => {
|
|||
<Route path={URL.MAIN} element={<EgovMain />} />
|
||||
|
||||
{/* LOGIN */}
|
||||
<Route path={URL.LOGIN} element={<EgovLogin
|
||||
onChangeLogin={(user) => setLoginVO(user)}
|
||||
/>}/>
|
||||
<Route path={URL.LOGIN} element={<EgovLogin onChangeLogin={(user) => setLoginVO(user)}/>}/>
|
||||
{/*{JOIN}*/}
|
||||
<Route path={URL.JOIN} element={<Join />} />
|
||||
|
||||
{/* ERROR */}
|
||||
<Route path={URL.ERROR} element={<EgovError />} />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,190 @@
|
|||
package com.dbnt.kcscbackend.auth;
|
||||
|
||||
import com.dbnt.kcscbackend.auth.service.EgovLoginService;
|
||||
import com.dbnt.kcscbackend.config.common.BaseController;
|
||||
import com.dbnt.kcscbackend.auth.entity.LoginVO;
|
||||
import com.dbnt.kcscbackend.config.common.ResponseCode;
|
||||
import com.dbnt.kcscbackend.config.common.ResultVO;
|
||||
import com.dbnt.kcscbackend.config.egov.EgovMessageSource;
|
||||
import com.dbnt.kcscbackend.config.jwt.EgovJwtTokenUtil;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* 일반 로그인을 처리하는 컨트롤러 클래스
|
||||
* @author 공통서비스 개발팀 박지욱
|
||||
* @since 2009.03.06
|
||||
* @version 1.0
|
||||
* @see
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ------- -------- ---------------------------
|
||||
* 2009.03.06 박지욱 최초 생성
|
||||
* 2011.08.31 JJY 경량환경 템플릿 커스터마이징버전 생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/auth")
|
||||
@Tag(name="EgovLoginApiController",description = "로그인 관련")
|
||||
public class EgovLoginApiController extends BaseController {
|
||||
|
||||
/** EgovLoginService */
|
||||
private EgovLoginService loginService;
|
||||
|
||||
/** EgovMessageSource */
|
||||
@Resource(name = "egovMessageSource")
|
||||
EgovMessageSource egovMessageSource;
|
||||
|
||||
/** JWT */
|
||||
@Autowired
|
||||
private EgovJwtTokenUtil jwtTokenUtil;
|
||||
|
||||
|
||||
@Operation(
|
||||
summary = "JWT 로그인",
|
||||
description = "JWT 로그인 처리",
|
||||
tags = {"EgovLoginApiController"}
|
||||
)
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(responseCode = "200", description = "로그인 성공"),
|
||||
@ApiResponse(responseCode = "300", description = "로그인 실패")
|
||||
})
|
||||
@PostMapping(value = "/join")
|
||||
public HashMap<String, Object> actionJoin(@RequestBody LoginVO loginVO, HttpServletRequest request) throws Exception {
|
||||
HashMap<String, Object> resultMap = new HashMap<String, Object>();
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 일반 로그인을 처리한다
|
||||
* @param loginVO - 아이디, 비밀번호가 담긴 LoginVO
|
||||
* @param request - 세션처리를 위한 HttpServletRequest
|
||||
* @return result - 로그인결과(세션정보)
|
||||
* @exception Exception
|
||||
*/
|
||||
|
||||
@Operation(
|
||||
summary = "일반 로그인",
|
||||
description = "일반 로그인 처리",
|
||||
tags = {"EgovLoginApiController"}
|
||||
)
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(responseCode = "200", description = "로그인 성공"),
|
||||
@ApiResponse(responseCode = "300", description = "로그인 실패")
|
||||
})
|
||||
@PostMapping(value = "/login", consumes = {MediaType.APPLICATION_JSON_VALUE , MediaType.TEXT_HTML_VALUE})
|
||||
public HashMap<String, Object> actionLogin(@RequestBody LoginVO loginVO, HttpServletRequest request) throws Exception {
|
||||
HashMap<String,Object> resultMap = new HashMap<String,Object>();
|
||||
|
||||
// 1. 일반 로그인 처리
|
||||
LoginVO loginResultVO = loginService.actionLogin(loginVO);
|
||||
|
||||
if (loginResultVO != null && loginResultVO.getId() != null && !loginResultVO.getId().equals("")) {
|
||||
|
||||
request.getSession().setAttribute("LoginVO", loginResultVO);
|
||||
resultMap.put("resultVO", loginResultVO);
|
||||
resultMap.put("resultCode", "200");
|
||||
resultMap.put("resultMessage", "성공 !!!");
|
||||
} else {
|
||||
resultMap.put("resultVO", loginResultVO);
|
||||
resultMap.put("resultCode", "300");
|
||||
resultMap.put("resultMessage", egovMessageSource.getMessage("fail.common.login"));
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
|
||||
}
|
||||
|
||||
@Operation(
|
||||
summary = "JWT 로그인",
|
||||
description = "JWT 로그인 처리",
|
||||
tags = {"EgovLoginApiController"}
|
||||
)
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(responseCode = "200", description = "로그인 성공"),
|
||||
@ApiResponse(responseCode = "300", description = "로그인 실패")
|
||||
})
|
||||
@PostMapping(value = "/login-jwt")
|
||||
public HashMap<String, Object> actionLoginJWT(@RequestBody LoginVO loginVO, HttpServletRequest request, ModelMap model) throws Exception {
|
||||
HashMap<String, Object> resultMap = new HashMap<String, Object>();
|
||||
|
||||
// 1. 일반 로그인 처리
|
||||
LoginVO loginResultVO = loginService.actionLogin(loginVO);
|
||||
|
||||
if (loginResultVO != null && loginResultVO.getId() != null && !loginResultVO.getId().equals("")) {
|
||||
|
||||
log.debug("===>>> loginVO.getUserSe() = "+loginVO.getUserSe());
|
||||
log.debug("===>>> loginVO.getId() = "+loginVO.getId());
|
||||
log.debug("===>>> loginVO.getPassword() = "+loginVO.getPassword());
|
||||
|
||||
String jwtToken = jwtTokenUtil.generateToken(loginResultVO);
|
||||
|
||||
String username = jwtTokenUtil.getUserSeFromToken(jwtToken);
|
||||
log.debug("Dec jwtToken username = "+username);
|
||||
|
||||
//서버사이드 권한 체크 통과를 위해 삽입
|
||||
//EgovUserDetailsHelper.isAuthenticated() 가 그 역할 수행. DB에 정보가 없으면 403을 돌려 줌. 로그인으로 튕기는 건 프론트 쪽에서 처리
|
||||
request.getSession().setAttribute("LoginVO", loginResultVO);
|
||||
|
||||
resultMap.put("resultVO", loginResultVO);
|
||||
resultMap.put("jToken", jwtToken);
|
||||
resultMap.put("resultCode", "200");
|
||||
resultMap.put("resultMessage", "성공 !!!");
|
||||
|
||||
} else {
|
||||
resultMap.put("resultVO", loginResultVO);
|
||||
resultMap.put("resultCode", "300");
|
||||
resultMap.put("resultMessage", egovMessageSource.getMessage("fail.common.login"));
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 로그아웃한다.
|
||||
* @return resultVO
|
||||
* @exception Exception
|
||||
*/
|
||||
@Operation(
|
||||
summary = "로그아웃",
|
||||
description = "로그아웃 처리(JWT,일반 관계 없이)",
|
||||
tags = {"EgovLoginApiController"}
|
||||
)
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(responseCode = "200", description = "로그아웃 성공"),
|
||||
})
|
||||
@GetMapping(value = "/logout")
|
||||
public ResultVO actionLogoutJSON(HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||
|
||||
ResultVO resultVO = new ResultVO();
|
||||
|
||||
new SecurityContextLogoutHandler().logout(request, response, null);
|
||||
|
||||
resultVO.setResultCode(ResponseCode.SUCCESS.getCode());
|
||||
resultVO.setResultMessage(ResponseCode.SUCCESS.getMessage());
|
||||
|
||||
return resultVO;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.dbnt.kcscbackend.config.common;
|
||||
package com.dbnt.kcscbackend.auth.entity;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ public class LoginVO implements Serializable{
|
|||
|
||||
@Schema(description = "이름")
|
||||
private String name;
|
||||
|
||||
|
||||
@Schema(description = "주민등록번호")
|
||||
private String ihidNum;
|
||||
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
package com.dbnt.kcscbackend.auth.mapper;
|
||||
|
||||
import com.dbnt.kcscbackend.auth.entity.LoginVO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 일반 로그인을 처리하는 비즈니스 구현 클래스
|
||||
* @author 공통서비스 개발팀 박지욱
|
||||
* @since 2009.03.06
|
||||
* @version 1.0
|
||||
* @see
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ------- -------- ---------------------------
|
||||
* 2009.03.06 박지욱 최초 생성
|
||||
* 2011.08.31 JJY 경량환경 템플릿 커스터마이징버전 생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@Mapper
|
||||
public interface LoginUserMapper {
|
||||
|
||||
/**
|
||||
* 일반 로그인을 처리한다
|
||||
* @param vo LoginVO
|
||||
* @return LoginVO
|
||||
* @exception Exception
|
||||
*/
|
||||
LoginVO actionLogin(LoginVO vo);
|
||||
|
||||
/**
|
||||
* 아이디를 찾는다.
|
||||
* @param vo LoginVO
|
||||
* @return LoginVO
|
||||
* @exception Exception
|
||||
*/
|
||||
LoginVO searchId(LoginVO vo);
|
||||
|
||||
/**
|
||||
* 비밀번호를 찾는다.
|
||||
* @param vo LoginVO
|
||||
* @return LoginVO
|
||||
* @exception Exception
|
||||
*/
|
||||
LoginVO searchPassword(LoginVO vo);
|
||||
|
||||
/**
|
||||
* 변경된 비밀번호를 저장한다.
|
||||
* @param vo LoginVO
|
||||
* @exception Exception
|
||||
*/
|
||||
void updatePassword(LoginVO vo);
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package com.dbnt.kcscbackend.auth.service;
|
||||
|
||||
|
||||
import com.dbnt.kcscbackend.auth.entity.LoginVO;
|
||||
|
||||
/**
|
||||
* 일반 로그인을 처리하는 비즈니스 구현 클래스
|
||||
* @author 공통서비스 개발팀 박지욱
|
||||
* @since 2009.03.06
|
||||
* @version 1.0
|
||||
* @see
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ------- -------- ---------------------------
|
||||
* 2009.03.06 박지욱 최초 생성
|
||||
* 2011.08.31 JJY 경량환경 템플릿 커스터마이징버전 생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
public interface EgovLoginService {
|
||||
|
||||
/**
|
||||
* 일반 로그인을 처리한다
|
||||
* @return LoginVO
|
||||
*
|
||||
* @param vo LoginVO
|
||||
* @exception Exception Exception
|
||||
*/
|
||||
public LoginVO actionLogin(LoginVO vo) throws Exception;
|
||||
|
||||
/**
|
||||
* 아이디를 찾는다.
|
||||
* @return LoginVO
|
||||
*
|
||||
* @param vo LoginVO
|
||||
* @exception Exception Exception
|
||||
*/
|
||||
public LoginVO searchId(LoginVO vo) throws Exception;
|
||||
|
||||
/**
|
||||
* 비밀번호를 찾는다.
|
||||
* @return boolean
|
||||
*
|
||||
* @param vo LoginVO
|
||||
* @exception Exception Exception
|
||||
*/
|
||||
public boolean searchPassword(LoginVO vo) throws Exception;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
package com.dbnt.kcscbackend.auth.service.impl;
|
||||
|
||||
import com.dbnt.kcscbackend.auth.mapper.LoginUserMapper;
|
||||
import com.dbnt.kcscbackend.auth.service.EgovLoginService;
|
||||
import com.dbnt.kcscbackend.auth.entity.LoginVO;
|
||||
import com.dbnt.kcscbackend.config.egov.EgovFileScrty;
|
||||
import com.dbnt.kcscbackend.config.util.EgovNumberUtil;
|
||||
import com.dbnt.kcscbackend.config.util.EgovStringUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* 일반 로그인을 처리하는 비즈니스 구현 클래스
|
||||
* @author 공통서비스 개발팀 박지욱
|
||||
* @since 2009.03.06
|
||||
* @version 1.0
|
||||
* @see
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ------- -------- ---------------------------
|
||||
* 2009.03.06 박지욱 최초 생성
|
||||
* 2011.08.31 JJY 경량환경 템플릿 커스터마이징버전 생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@Service
|
||||
@Transactional
|
||||
@RequiredArgsConstructor
|
||||
public class EgovLoginServiceImpl extends EgovAbstractServiceImpl implements EgovLoginService {
|
||||
|
||||
private final LoginUserMapper loginMapper;
|
||||
|
||||
/**
|
||||
* 일반 로그인을 처리한다
|
||||
* @param vo LoginVO
|
||||
* @return LoginVO
|
||||
* @exception Exception
|
||||
*/
|
||||
@Override
|
||||
public LoginVO actionLogin(LoginVO vo) throws Exception {
|
||||
|
||||
// 1. 입력한 비밀번호를 암호화한다.
|
||||
String enpassword = EgovFileScrty.encryptPassword(vo.getPassword(), vo.getId());
|
||||
vo.setPassword(enpassword);
|
||||
|
||||
// 2. 아이디와 암호화된 비밀번호가 DB와 일치하는지 확인한다.
|
||||
LoginVO loginVO = loginMapper.actionLogin(vo);
|
||||
|
||||
// 3. 결과를 리턴한다.
|
||||
if (loginVO != null && !loginVO.getId().equals("") && !loginVO.getPassword().equals("")) {
|
||||
return loginVO;
|
||||
} else {
|
||||
loginVO = new LoginVO();
|
||||
}
|
||||
|
||||
return loginVO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 아이디를 찾는다.
|
||||
* @param vo LoginVO
|
||||
* @return LoginVO
|
||||
* @exception Exception
|
||||
*/
|
||||
@Override
|
||||
public LoginVO searchId(LoginVO vo) throws Exception {
|
||||
|
||||
// 1. 이름, 이메일주소가 DB와 일치하는 사용자 ID를 조회한다.
|
||||
LoginVO loginVO = loginMapper.searchId(vo);
|
||||
|
||||
// 2. 결과를 리턴한다.
|
||||
if (loginVO != null && !loginVO.getId().equals("")) {
|
||||
return loginVO;
|
||||
} else {
|
||||
loginVO = new LoginVO();
|
||||
}
|
||||
|
||||
return loginVO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 비밀번호를 찾는다.
|
||||
* @param vo LoginVO
|
||||
* @return boolean
|
||||
* @exception Exception
|
||||
*/
|
||||
@Override
|
||||
public boolean searchPassword(LoginVO vo) throws Exception {
|
||||
|
||||
boolean result = true;
|
||||
|
||||
// 1. 아이디, 이름, 이메일주소, 비밀번호 힌트, 비밀번호 정답이 DB와 일치하는 사용자 Password를 조회한다.
|
||||
LoginVO loginVO = loginMapper.searchPassword(vo);
|
||||
if (loginVO == null || loginVO.getPassword() == null || loginVO.getPassword().equals("")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 임시 비밀번호를 생성한다.(영+영+숫+영+영+숫=6자리)
|
||||
String newpassword = "";
|
||||
for (int i = 1; i <= 6; i++) {
|
||||
// 영자
|
||||
if (i % 3 != 0) {
|
||||
newpassword += EgovStringUtil.getRandomStr('a', 'z');
|
||||
// 숫자
|
||||
} else {
|
||||
newpassword += EgovNumberUtil.getRandomNum(0, 9);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 임시 비밀번호를 암호화하여 DB에 저장한다.
|
||||
LoginVO pwVO = new LoginVO();
|
||||
String enpassword = EgovFileScrty.encryptPassword(newpassword, vo.getId());
|
||||
pwVO.setId(vo.getId());
|
||||
pwVO.setPassword(enpassword);
|
||||
pwVO.setUserSe(vo.getUserSe());
|
||||
loginMapper.updatePassword(pwVO);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,305 @@
|
|||
package com.dbnt.kcscbackend.config.egov;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.tomcat.util.codec.binary.Base64;
|
||||
|
||||
import java.io.*;
|
||||
import java.security.MessageDigest;
|
||||
|
||||
/**
|
||||
* Base64인코딩/디코딩 방식을 이용한 데이터를 암호화/복호화하는 Business Interface class
|
||||
* @author 공통서비스개발팀 박지욱
|
||||
* @since 2009.01.19
|
||||
* @version 1.0
|
||||
* @see
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ------- -------- ---------------------------
|
||||
* 2009.01.19 박지욱 최초 생성
|
||||
* 2011.08.31 JJY 경량환경 템플릿 커스터마이징버전 생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@Slf4j
|
||||
public class EgovFileScrty {
|
||||
// 파일구분자
|
||||
static final String FILE_SEPARATOR = System.getProperty("file.separator");
|
||||
// 버퍼사이즈
|
||||
static final int BUFFER_SIZE = 1024;
|
||||
|
||||
/**
|
||||
* 파일을 암호화하는 기능
|
||||
*
|
||||
* @param source 암호화할 파일
|
||||
* @param target 암호화된 파일
|
||||
* @return boolean result 암호화여부 True/False
|
||||
* @exception Exception
|
||||
*/
|
||||
public static boolean encryptFile(String source, String target) throws Exception {
|
||||
|
||||
// 암호화 여부
|
||||
boolean result = false;
|
||||
|
||||
String sourceFile = EgovWebUtil.filePathBlackList(source.replace("\\", FILE_SEPARATOR).replace("/", FILE_SEPARATOR));
|
||||
String targetFile = EgovWebUtil.filePathBlackList(target.replace("\\", FILE_SEPARATOR).replace("/", FILE_SEPARATOR));
|
||||
File srcFile = new File(sourceFile);
|
||||
|
||||
BufferedInputStream input = null;
|
||||
BufferedOutputStream output = null;
|
||||
|
||||
byte[] buffer = new byte[BUFFER_SIZE];
|
||||
|
||||
try {
|
||||
if (srcFile.exists() && srcFile.isFile()) {
|
||||
|
||||
input = new BufferedInputStream(new FileInputStream(srcFile));
|
||||
output = new BufferedOutputStream(new FileOutputStream(targetFile));
|
||||
|
||||
int length = 0;
|
||||
while ((length = input.read(buffer)) >= 0) {
|
||||
byte[] data = new byte[length];
|
||||
System.arraycopy(buffer, 0, data, 0, length);
|
||||
output.write(encodeBinary(data).getBytes());
|
||||
output.write(System.getProperty("line.separator").getBytes());
|
||||
}
|
||||
|
||||
result = true;
|
||||
}
|
||||
} finally {
|
||||
if (input != null) {
|
||||
try {
|
||||
input.close();
|
||||
} catch (IOException ignore) {
|
||||
log.debug("IGNORE: {}", ignore);
|
||||
}
|
||||
}
|
||||
if (output != null) {
|
||||
try {
|
||||
output.close();
|
||||
} catch (IOException ignore) {
|
||||
log.debug("IGNORE: {}", ignore);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 파일을 복호화하는 기능
|
||||
*
|
||||
* @param source 복호화할 파일
|
||||
* @param target 복호화된 파일
|
||||
* @return boolean result 복호화여부 True/False
|
||||
* @exception Exception
|
||||
*/
|
||||
public static boolean decryptFile(String source, String target) throws Exception {
|
||||
|
||||
// 복호화 여부
|
||||
boolean result = false;
|
||||
|
||||
String sourceFile = source.replace("\\", FILE_SEPARATOR).replace("/", FILE_SEPARATOR);
|
||||
String targetFile = target.replace("\\", FILE_SEPARATOR).replace("/", FILE_SEPARATOR);
|
||||
File srcFile = new File(sourceFile);
|
||||
|
||||
BufferedReader input = null;
|
||||
BufferedOutputStream output = null;
|
||||
|
||||
//byte[] buffer = new byte[BUFFER_SIZE];
|
||||
String line = null;
|
||||
|
||||
try {
|
||||
if (srcFile.exists() && srcFile.isFile()) {
|
||||
|
||||
input = new BufferedReader(new InputStreamReader(new FileInputStream(srcFile)));
|
||||
output = new BufferedOutputStream(new FileOutputStream(targetFile));
|
||||
|
||||
while ((line = input.readLine()) != null) {
|
||||
byte[] data = line.getBytes();
|
||||
output.write(decodeBinary(new String(data)));
|
||||
}
|
||||
|
||||
result = true;
|
||||
}
|
||||
} finally {
|
||||
if (input != null) {
|
||||
try {
|
||||
input.close();
|
||||
} catch (IOException ignore) {
|
||||
log.debug("IGNORE: {}", ignore);
|
||||
}
|
||||
}
|
||||
if (output != null) {
|
||||
try {
|
||||
output.close();
|
||||
} catch (IOException ignore) {
|
||||
log.debug("IGNORE: {}", ignore);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 데이터를 암호화하는 기능
|
||||
*
|
||||
* @param data 암호화할 데이터
|
||||
* @return String result 암호화된 데이터
|
||||
* @exception Exception
|
||||
*/
|
||||
public static String encodeBinary(byte[] data) throws Exception {
|
||||
if (data == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return new String(Base64.encodeBase64(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* 데이터를 암호화하는 기능
|
||||
*
|
||||
* @param data 암호화할 데이터
|
||||
* @return String result 암호화된 데이터
|
||||
* @exception Exception
|
||||
*/
|
||||
public static String encode(String data) throws Exception {
|
||||
return encodeBinary(data.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* 데이터를 복호화하는 기능
|
||||
*
|
||||
* @param data 복호화할 데이터
|
||||
* @return String result 복호화된 데이터
|
||||
* @exception Exception
|
||||
*/
|
||||
public static byte[] decodeBinary(String data) throws Exception {
|
||||
return Base64.decodeBase64(data.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* 데이터를 복호화하는 기능
|
||||
*
|
||||
* @param String data 복호화할 데이터
|
||||
* @return String result 복호화된 데이터
|
||||
* @exception Exception
|
||||
*/
|
||||
public static String decode(String data) throws Exception {
|
||||
return new String(decodeBinary(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* 비밀번호를 암호화하는 기능(복호화가 되면 안되므로 SHA-256 인코딩 방식 적용).
|
||||
*
|
||||
* deprecated : 보안 강화를 위하여 salt로 ID를 지정하는 encryptPassword(password, id) 사용
|
||||
*
|
||||
* @param data 암호화할 비밀번호
|
||||
* @return String result 암호화된 비밀번호
|
||||
* @exception Exception
|
||||
*/
|
||||
@Deprecated
|
||||
public static String encryptPassword(String data) throws Exception {
|
||||
|
||||
if (data == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
byte[] plainText = null; // 평문
|
||||
byte[] hashValue = null; // 해쉬값
|
||||
plainText = data.getBytes();
|
||||
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||
|
||||
// 변경 시 기존 hash 값에 검증 불가.. => deprecated 시키고 유지
|
||||
/*
|
||||
// Random 방식의 salt 추가
|
||||
SecureRandom ng = new SecureRandom();
|
||||
byte[] randomBytes = new byte[16];
|
||||
ng.nextBytes(randomBytes);
|
||||
|
||||
md.reset();
|
||||
md.update(randomBytes);
|
||||
|
||||
*/
|
||||
hashValue = md.digest(plainText);
|
||||
|
||||
/*
|
||||
BASE64Encoder encoder = new BASE64Encoder();
|
||||
return encoder.encode(hashValue);
|
||||
*/
|
||||
return new String(Base64.encodeBase64(hashValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* 비밀번호를 암호화하는 기능(복호화가 되면 안되므로 SHA-256 인코딩 방식 적용)
|
||||
*
|
||||
* @param password 암호화될 패스워드
|
||||
* @param id salt로 사용될 사용자 ID 지정
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String encryptPassword(String password, String id) throws Exception {
|
||||
|
||||
if (password == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
byte[] hashValue = null; // 해쉬값
|
||||
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||
|
||||
md.reset();
|
||||
md.update(id.getBytes());
|
||||
|
||||
hashValue = md.digest(password.getBytes());
|
||||
|
||||
return new String(Base64.encodeBase64(hashValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* 비밀번호를 암호화하는 기능(복호화가 되면 안되므로 SHA-256 인코딩 방식 적용)
|
||||
* @param data 암호화할 비밀번호
|
||||
* @param salt Salt
|
||||
* @return 암호화된 비밀번호
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String encryptPassword(String data, byte[] salt) throws Exception {
|
||||
|
||||
if (data == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
byte[] hashValue = null; // 해쉬값
|
||||
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||
|
||||
md.reset();
|
||||
md.update(salt);
|
||||
|
||||
hashValue = md.digest(data.getBytes());
|
||||
|
||||
return new String(Base64.encodeBase64(hashValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* 비밀번호를 암호화된 패스워드 검증(salt가 사용된 경우만 적용).
|
||||
*
|
||||
* @param data 원 패스워드
|
||||
* @param encoded 해쉬처리된 패스워드(Base64 인코딩)
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static boolean checkPassword(String data, String encoded, byte[] salt) throws Exception {
|
||||
byte[] hashValue = null; // 해쉬값
|
||||
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||
|
||||
md.reset();
|
||||
md.update(salt);
|
||||
hashValue = md.digest(data.getBytes());
|
||||
|
||||
return MessageDigest.isEqual(hashValue, Base64.decodeBase64(encoded.getBytes()));
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ package com.dbnt.kcscbackend.config.jwt;
|
|||
|
||||
|
||||
import com.dbnt.kcscbackend.config.egov.EgovProperties;
|
||||
import com.dbnt.kcscbackend.config.common.LoginVO;
|
||||
import com.dbnt.kcscbackend.auth.entity.LoginVO;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package com.dbnt.kcscbackend.config.jwt;
|
||||
|
||||
import com.dbnt.kcscbackend.config.common.LoginVO;
|
||||
import com.dbnt.kcscbackend.auth.entity.LoginVO;
|
||||
import com.dbnt.kcscbackend.config.util.EgovStringUtil;
|
||||
import io.jsonwebtoken.ExpiredJwtException;
|
||||
import io.jsonwebtoken.MalformedJwtException;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package com.dbnt.kcscbackend.config.security;
|
||||
|
||||
import com.dbnt.kcscbackend.config.common.LoginVO;
|
||||
import com.dbnt.kcscbackend.auth.entity.LoginVO;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ public class SecurityConfig {
|
|||
"/login/**",
|
||||
"/auth/login-jwt",//JWT 로그인
|
||||
"/auth/login",//일반 로그인
|
||||
"/auth/join",//회원가입
|
||||
"/cmm/main/**.do", // 메인페이지
|
||||
"/cmm/fms/FileDown.do", //파일 다운로드
|
||||
"/cmm/fms/getImage.do", //갤러리 이미지보기
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.dbnt.kcscbackend.standardCode;
|
||||
|
||||
import com.dbnt.kcscbackend.config.common.BaseController;
|
||||
import com.dbnt.kcscbackend.config.common.LoginVO;
|
||||
import com.dbnt.kcscbackend.auth.entity.LoginVO;
|
||||
import com.dbnt.kcscbackend.config.common.ResponseCode;
|
||||
import com.dbnt.kcscbackend.config.common.ResultVO;
|
||||
import com.dbnt.kcscbackend.standardCode.entity.TnDocumentCodeList;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,182 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.dbnt.kcscbackend.auth.mapper.LoginUserMapper">
|
||||
|
||||
<!-- 일반 로그인 -->
|
||||
<select id="actionLogin" resultType="LoginVO" parameterType="LoginVO">
|
||||
<!-- 일반회원 -->
|
||||
<if test="userSe == "USR"">
|
||||
|
||||
SELECT EMPLYR_ID AS id
|
||||
, USER_NM AS name
|
||||
, PASSWORD AS password
|
||||
, IHIDNUM AS ihidNum
|
||||
, EMAIL_ADRES AS email
|
||||
, 'USR' AS userSe
|
||||
, ORGNZT_ID AS orgnztId
|
||||
, ESNTL_ID AS uniqId
|
||||
FROM LETTNEMPLYRINFO
|
||||
WHERE EMPLYR_ID = #{id}
|
||||
AND PASSWORD = #{password}
|
||||
AND EMPLYR_STTUS_CODE = 'P'
|
||||
|
||||
</if>
|
||||
<!-- 기업회원 -->
|
||||
<if test="userSe == "ENT"">
|
||||
|
||||
SELECT entrprsmber_id AS id
|
||||
, cmpny_nm AS name
|
||||
, entrprs_mber_password AS password
|
||||
, bizrno AS ihidNum
|
||||
, applcnt_email_adres AS email
|
||||
, 'ENT' AS userSe
|
||||
, '-' AS orgnztId
|
||||
, esntl_id AS uniqId
|
||||
FROM LETTNENTRPRSMBER
|
||||
WHERE entrprsmber_id = #{id}
|
||||
AND entrprs_mber_password = #{password}
|
||||
AND entrprs_mber_sttus = 'P'
|
||||
|
||||
</if>
|
||||
<!-- 업무사용자 -->
|
||||
<if test="userSe == "USR"">
|
||||
|
||||
SELECT emplyr_id AS id
|
||||
, user_nm AS name
|
||||
, password AS password
|
||||
, ihidnum AS ihidNum
|
||||
, email_adres AS email
|
||||
, 'USR' AS userSe
|
||||
, orgnzt_id AS orgnztId
|
||||
, esntl_id AS uniqId
|
||||
FROM LETTNEMPLYRINFO
|
||||
WHERE emplyr_id = #{id}
|
||||
AND password = #{password}
|
||||
AND emplyr_sttus_code = 'P'
|
||||
|
||||
</if>
|
||||
</select>
|
||||
|
||||
|
||||
<!-- 인증서 로그인 -->
|
||||
<select id="actionCrtfctLogin" resultType="LoginVO" parameterType="LoginVO">
|
||||
|
||||
SELECT emplyr_id AS id
|
||||
, user_nm AS name
|
||||
, password AS password
|
||||
, ihidnum AS ihidNum
|
||||
, email_adres AS email
|
||||
, 'USR' AS userSe
|
||||
, orgnzt_id AS orgnztId
|
||||
, esntl_id AS uniqId
|
||||
FROM LETTNEMPLYRINFO
|
||||
WHERE sub_dn = #{dn}
|
||||
|
||||
</select>
|
||||
|
||||
<!-- 아이디 찾기 -->
|
||||
<select id="searchId" resultType="LoginVO" parameterType="LoginVO">
|
||||
<!-- 일반회원 -->
|
||||
<if test="userSe == "GNR"">
|
||||
|
||||
SELECT mber_id AS id
|
||||
FROM LETTNGNRLMBER
|
||||
WHERE mber_nm = #{name}
|
||||
AND mber_email_adres = #{email}
|
||||
AND mber_sttus = 'P'
|
||||
|
||||
</if>
|
||||
<!-- 기업회원 -->
|
||||
<if test="userSe == "ENT"">
|
||||
|
||||
SELECT entrprsmber_id AS id
|
||||
FROM LETTNENTRPRSMBER
|
||||
WHERE cmpny_nm = #{name}
|
||||
AND applcnt_email_adres = #{email}
|
||||
AND entrprs_mber_sttus = 'P'
|
||||
|
||||
</if>
|
||||
<!-- 업무사용자 -->
|
||||
<if test="userSe == "USR"">
|
||||
|
||||
SELECT emplyr_id AS id
|
||||
FROM LETTNEMPLYRINFO
|
||||
WHERE user_nm = #{name}
|
||||
AND email_adres = #{email}
|
||||
AND emplyr_sttus_code = 'P'
|
||||
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<!-- 비밀번호 찾기 -->
|
||||
<select id="searchPassword" resultType="LoginVO" parameterType="LoginVO">
|
||||
<!-- 일반회원 -->
|
||||
<if test="userSe == "GNR"">
|
||||
|
||||
SELECT password AS password
|
||||
FROM LETTNGNRLMBER
|
||||
WHERE mber_id = #{id}
|
||||
AND mber_nm = #{name}
|
||||
AND mber_email_adres = #{email}
|
||||
AND password_hint = #{passwordHint}
|
||||
AND password_cnsr = #{passwordCnsr}
|
||||
AND mber_sttus = 'P'
|
||||
|
||||
</if>
|
||||
<!-- 기업회원 -->
|
||||
<if test="userSe == "ENT"">
|
||||
|
||||
SELECT entrprs_mber_password AS password
|
||||
FROM LETTNENTRPRSMBER
|
||||
WHERE entrprsmber_id = #{id}
|
||||
AND cmpny_nm = #{name}
|
||||
AND applcnt_email_adres = #{email}
|
||||
AND entrprs_mber_password_hint = #{passwordHint}
|
||||
AND entrprs_mber_password_cnsr = #{passwordCnsr}
|
||||
AND entrprs_mber_sttus = 'P'
|
||||
|
||||
</if>
|
||||
<!-- 업무사용자 -->
|
||||
<if test="userSe == "USR"">
|
||||
|
||||
SELECT password AS password
|
||||
FROM LETTNEMPLYRINFO
|
||||
WHERE emplyr_id = #{id}
|
||||
AND user_nm = #{name}
|
||||
AND email_adres = #{email}
|
||||
AND password_hint = #{passwordHint}
|
||||
AND password_cnsr = #{passwordCnsr}
|
||||
AND emplyr_sttus_code = 'P'
|
||||
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<!-- 변경된 비밀번호를 저장 -->
|
||||
<update id="updatePassword" parameterType="LoginVO">
|
||||
<!-- 일반회원 -->
|
||||
<if test="userSe == "GNR"">
|
||||
|
||||
UPDATE LETTNGNRLMBER
|
||||
SET password = #{password}
|
||||
WHERE mber_id = #{id}
|
||||
|
||||
</if>
|
||||
<!-- 기업회원 -->
|
||||
<if test="userSe == "ENT"">
|
||||
|
||||
UPDATE LETTNENTRPRSMBER
|
||||
SET entrprs_mber_password = #{password}
|
||||
WHERE entrprsmber_id = #{id}
|
||||
|
||||
</if>
|
||||
<!-- 업무사용자 -->
|
||||
<if test="userSe == "USR"">
|
||||
|
||||
UPDATE LETTNEMPLYRINFO
|
||||
SET password = #{password}
|
||||
WHERE emplyr_id = #{id}
|
||||
|
||||
</if>
|
||||
</update>
|
||||
</mapper>
|
||||
Loading…
Reference in New Issue