Merge branch 'devs/sso' into jenkins_with_weblogic
This commit is contained in:
+2
-1
@@ -244,4 +244,5 @@ gradle-gf63.sh
|
|||||||
eapim-admin-kjb/
|
eapim-admin-kjb/
|
||||||
.claude
|
.claude
|
||||||
*.report.md
|
*.report.md
|
||||||
*.claude.md
|
*.claude.md
|
||||||
|
tmpclaude-*-cwd
|
||||||
|
|||||||
@@ -156,9 +156,16 @@
|
|||||||
$("#changePwd").click(function(){
|
$("#changePwd").click(function(){
|
||||||
changePwd();
|
changePwd();
|
||||||
});
|
});
|
||||||
|
$("#btn_sso_login").click(function(){
|
||||||
|
fncSsoLogin();
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function fncSsoLogin() {
|
||||||
|
sessionStorage["serviceType"] = $("select[name=serviceType]").val();
|
||||||
|
location.href = '<c:url value="/sso/login.do"/>';
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -205,6 +212,11 @@
|
|||||||
<div style="text-align: right !important;" class="form-group">
|
<div style="text-align: right !important;" class="form-group">
|
||||||
<a style="font-size: 12px !important;" href="#pwdChgModal" data-toggle="modal" >Password Change</a>
|
<a style="font-size: 12px !important;" href="#pwdChgModal" data-toggle="modal" >Password Change</a>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- SSO 로그인 버튼 -->
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="button" id="btn_sso_login" class="form-control btn btn-success rounded submit px-3"
|
||||||
|
value="SSO Login">
|
||||||
|
</div>
|
||||||
<p style="color:red;"><%=resultMsg %></p>
|
<p style="color:red;"><%=resultMsg %></p>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|||||||
@@ -120,6 +120,37 @@ public class MainController implements InterceptorSkipController {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SSO 로그인용 세션 설정 (SsoController에서 호출)
|
||||||
|
* 비밀번호 인증 없이 UserInfo만으로 로그인 처리
|
||||||
|
*/
|
||||||
|
public String setupSsoLoginSession(HttpServletRequest request, UserInfo userInfo) {
|
||||||
|
HttpSession session = request.getSession(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
initializeLoginAndSetDashboardImage(session);
|
||||||
|
|
||||||
|
LoginVo dto = new LoginVo();
|
||||||
|
dto.setUserId(userInfo.getUserid());
|
||||||
|
|
||||||
|
session.setAttribute("userId", userInfo.getUserid());
|
||||||
|
session.setAttribute("dualLogin", "N");
|
||||||
|
SessionManager.forceRegisterUserSession(request, dto);
|
||||||
|
session.setAttribute(CommonConstants.LOGIN, dto);
|
||||||
|
|
||||||
|
String result = loadUserInfoAndSetupSession(request, session, dto, userInfo);
|
||||||
|
|
||||||
|
// SSO 로그인 시 기본 serviceType 파라미터 추가 (외부 링크 직접 접근 대응)
|
||||||
|
if ("redirect:/main.do".equals(result)) {
|
||||||
|
DataSourceType defaultType = DataSourceTypeManager.getDynamicDataSourceTypes().get(0);
|
||||||
|
return "redirect:/main.do?serviceType=" + defaultType.getName();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return handleExceptionsAndRedirect(request, session, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 초기 설정 및 대시보드 이미지 설정
|
// 초기 설정 및 대시보드 이미지 설정
|
||||||
private void initializeLoginAndSetDashboardImage(HttpSession session) {
|
private void initializeLoginAndSetDashboardImage(HttpSession session) {
|
||||||
|
|
||||||
|
|||||||
@@ -118,5 +118,20 @@ public class UserInfoService extends
|
|||||||
return repository.findAll(predicate, pageable);
|
return repository.findAll(predicate, pageable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 대소문자 구분 없이 사용자 ID로 검색
|
||||||
|
* @param userId 사용자 ID
|
||||||
|
* @return 사용자 정보 (Optional)
|
||||||
|
*/
|
||||||
|
public Optional<UserInfo> findByUserIdIgnoreCase(String userId) {
|
||||||
|
QUserInfo qUserInfo = QUserInfo.userInfo;
|
||||||
|
|
||||||
|
UserInfo result = getJPAQueryFactory()
|
||||||
|
.selectFrom(qUserInfo)
|
||||||
|
.where(qUserInfo.userid.equalsIgnoreCase(userId))
|
||||||
|
.fetchOne();
|
||||||
|
|
||||||
|
return Optional.ofNullable(result);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,20 @@
|
|||||||
package com.eactive.eai.rms.ext.kjb.sso;
|
package com.eactive.eai.rms.ext.kjb.sso;
|
||||||
|
|
||||||
|
import com.eactive.apim.portal.user.entity.UserInfo;
|
||||||
|
import com.eactive.eai.common.seed.Seed;
|
||||||
|
import com.eactive.eai.rms.common.context.MonitoringContext;
|
||||||
|
import com.eactive.eai.rms.common.datasource.DataSourceType;
|
||||||
|
import com.eactive.eai.rms.common.datasource.DataSourceTypeManager;
|
||||||
import com.eactive.eai.rms.common.interceptor.InterceptorSkipController;
|
import com.eactive.eai.rms.common.interceptor.InterceptorSkipController;
|
||||||
|
import com.eactive.eai.rms.common.login.MainController;
|
||||||
|
import com.eactive.eai.rms.common.util.CommonConstants;
|
||||||
import com.eactive.eai.rms.data.entity.man.monitoringProperty.service.MonitoringPropertyService;
|
import com.eactive.eai.rms.data.entity.man.monitoringProperty.service.MonitoringPropertyService;
|
||||||
|
import com.eactive.eai.rms.data.entity.man.user.UserInfoService;
|
||||||
|
import com.eactive.eai.rms.data.entity.man.user.UserRole;
|
||||||
|
import com.eactive.eai.rms.data.entity.man.user.UserRoleId;
|
||||||
|
import com.eactive.eai.rms.data.entity.man.user.UserRoleService;
|
||||||
|
import com.eactive.eai.rms.data.entity.man.user.UserServiceTypeService;
|
||||||
|
import com.eactive.eai.rms.onl.apim.masking.MaskingUtils;
|
||||||
import com.eactive.ext.kjb.common.KjbProperty;
|
import com.eactive.ext.kjb.common.KjbProperty;
|
||||||
import com.eactive.ext.kjb.sso.KjbSsoModule;
|
import com.eactive.ext.kjb.sso.KjbSsoModule;
|
||||||
import com.eactive.ext.kjb.util.KjbPropertyInjector;
|
import com.eactive.ext.kjb.util.KjbPropertyInjector;
|
||||||
@@ -14,6 +27,8 @@ import org.springframework.web.bind.annotation.RequestParam;
|
|||||||
import javax.servlet.http.Cookie;
|
import javax.servlet.http.Cookie;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@@ -23,36 +38,49 @@ public class SsoController implements InterceptorSkipController {
|
|||||||
|
|
||||||
private final KjbSsoModule ssoModule;
|
private final KjbSsoModule ssoModule;
|
||||||
private final KjbProperty prop;
|
private final KjbProperty prop;
|
||||||
|
private final UserInfoService userInfoService;
|
||||||
|
private final UserRoleService userRoleService;
|
||||||
|
private final UserServiceTypeService userServiceTypeService;
|
||||||
|
private final MonitoringContext monitoringContext;
|
||||||
|
private final MainController mainController;
|
||||||
|
|
||||||
|
public SsoController(MonitoringPropertyService monitoringPropertyService,
|
||||||
public SsoController(MonitoringPropertyService monitoringPropertyService) {
|
UserInfoService userInfoService,
|
||||||
|
UserRoleService userRoleService,
|
||||||
|
UserServiceTypeService userServiceTypeService,
|
||||||
|
MonitoringContext monitoringContext,
|
||||||
|
MainController mainController) {
|
||||||
KjbPropertyInjector kjbPropertyInjector = new KjbPropertyInjector(monitoringPropertyService, PROP_GORUP_ID);
|
KjbPropertyInjector kjbPropertyInjector = new KjbPropertyInjector(monitoringPropertyService, PROP_GORUP_ID);
|
||||||
prop = kjbPropertyInjector.inject(new KjbProperty());
|
prop = kjbPropertyInjector.inject(new KjbProperty());
|
||||||
this.ssoModule = KjbSsoModule.getInstance(prop);
|
this.ssoModule = KjbSsoModule.getInstance(prop);
|
||||||
|
this.userInfoService = userInfoService;
|
||||||
|
this.userRoleService = userRoleService;
|
||||||
|
this.userServiceTypeService = userServiceTypeService;
|
||||||
|
this.monitoringContext = monitoringContext;
|
||||||
|
this.mainController = mainController;
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(value = "/sso/login.do")
|
@RequestMapping(value = "/sso/login.do")
|
||||||
public String login(HttpServletRequest req, HttpServletResponse res,
|
public String login(HttpServletRequest req, HttpServletResponse res,
|
||||||
@RequestParam(name = "UURL", required = false) String uurl) throws Exception {
|
@RequestParam(name = "UURL", required = false) String uurl) throws Exception {
|
||||||
|
HttpSession session = req.getSession();
|
||||||
String ssoId = ssoModule.getSsoId(req);
|
String ssoId = ssoModule.getSsoId(req);
|
||||||
|
|
||||||
log.debug("ssoId : {}", ssoId);
|
log.debug("ssoId : {}", ssoId);
|
||||||
log.debug("uurl : {}", uurl);
|
log.debug("uurl : {}", uurl);
|
||||||
|
|
||||||
log.debug("KjbProperty : \n{}", prop.toJsonString(true));
|
|
||||||
|
|
||||||
|
|
||||||
// 디버깅용 쿠키 목록 출력
|
// 디버깅용 쿠키 목록 출력
|
||||||
Cookie[] cookies = req.getCookies();
|
if (log.isDebugEnabled()) {
|
||||||
if (cookies == null || cookies.length == 0) {
|
Cookie[] cookies = req.getCookies();
|
||||||
log.debug("No cookies");
|
if (cookies == null || cookies.length == 0) {
|
||||||
} else {
|
log.debug("No cookies");
|
||||||
for (Cookie c: cookies) {
|
} else {
|
||||||
log.debug("Cookie[{}] : {}, Domain={}, Path={}, Max-Age={}, Secure={}, Version={}",
|
for (Cookie c : cookies) {
|
||||||
c.getName(), c.getValue(), c.getDomain(), c.getPath(), c.getMaxAge(), c.getSecure(), c.getVersion());
|
log.debug("Cookie[{}] : Domain={}, Path={}",
|
||||||
|
c.getName(), c.getDomain(), c.getPath());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (StringUtils.isEmpty(uurl)) {
|
if (StringUtils.isEmpty(uurl)) {
|
||||||
uurl = ssoModule.getAscpUrl();
|
uurl = ssoModule.getAscpUrl();
|
||||||
@@ -62,45 +90,225 @@ public class SsoController implements InterceptorSkipController {
|
|||||||
ssoModule.goLoginPage(res, uurl);
|
ssoModule.goLoginPage(res, uurl);
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
|
// EAM 세션 검증
|
||||||
String retCode = ssoModule.getEamSessionCheck(req, res);
|
String retCode = ssoModule.getEamSessionCheck(req, res);
|
||||||
log.debug("retCode : {}", retCode);
|
log.debug("retCode : {}", retCode);
|
||||||
|
|
||||||
log.debug("Property - sso.ignore_validation = {}", prop.isSsoIgnoreValidation());
|
log.debug("Property - sso.ignore_validation = {}", prop.isSsoIgnoreValidation());
|
||||||
if (!prop.isSsoIgnoreValidation() && !"0".equalsIgnoreCase(retCode)) {
|
if (!prop.isSsoIgnoreValidation() && !"0".equalsIgnoreCase(retCode)) {
|
||||||
|
// SSO 검증 실패 시 에러 메시지 설정 및 로그인 페이지로 이동
|
||||||
ssoModule.goErrorPage(res, Integer.parseInt(retCode));
|
session.setAttribute("resultMsg", "SSO 로그인을 실패 하였습니다. 다른 로그인 방식을 시도 하세요");
|
||||||
return null;
|
return "redirect:/loginForm.do";
|
||||||
}
|
|
||||||
|
|
||||||
if (StringUtils.isEmpty(ssoId)) {
|
|
||||||
throw new IllegalStateException("KJB-SSO - ssoId 획득 실패");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 기본 정보
|
|
||||||
Properties info = ssoModule.getUserInfos(ssoId);
|
|
||||||
if (info != null) {
|
|
||||||
log.debug("info - {}", info.keySet());
|
|
||||||
info.keySet().forEach( k -> {
|
|
||||||
log.debug("{} : {}", k, info.get(k));
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
log.debug("User info is null");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 확장 정보
|
|
||||||
Properties extendedInfo = ssoModule.getUserExFields(ssoId);
|
|
||||||
if (extendedInfo != null) {
|
|
||||||
log.debug("extendedInfo - {}", info.keySet());
|
|
||||||
extendedInfo.keySet().forEach( k -> {
|
|
||||||
log.debug("{} : {}", k, extendedInfo.get(k));
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
log.debug("User Extended info is null");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "redirect:/main.do";
|
if (StringUtils.isEmpty(ssoId)) {
|
||||||
|
session.setAttribute("resultMsg", "SSO 인증 정보를 획득하지 못했습니다.");
|
||||||
|
return "redirect:/loginForm.do";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 기본 정보
|
||||||
|
Properties info = ssoModule.getUserInfos(ssoId);
|
||||||
|
// 확장 정보
|
||||||
|
Properties extendedInfo = ssoModule.getUserExFields(ssoId);
|
||||||
|
|
||||||
|
// 필수 필드 검증
|
||||||
|
try {
|
||||||
|
validateRequiredFields(info, extendedInfo);
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
log.warn("SSO 필수 필드 검증 실패: {}", e.getMessage());
|
||||||
|
session.setAttribute("resultMsg", e.getMessage());
|
||||||
|
return "redirect:/loginForm.do";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 사용자 정보 로깅 (개인정보 마스킹 처리)
|
||||||
|
String userId = info.getProperty("USERID");
|
||||||
|
String name = info.getProperty("NAME");
|
||||||
|
String email = info.getProperty("EMAIL");
|
||||||
|
String cellPhoneNo = extendedInfo != null ? extendedInfo.getProperty("CELLPHONENO") : null;
|
||||||
|
|
||||||
|
log.info("SSO 로그인 시도 - userId: {}", userId);
|
||||||
|
log.debug("SSO 사용자 정보 - userId: {}, name: {}, phone: {}, email: {}",
|
||||||
|
userId,
|
||||||
|
MaskingUtils.maskName(name),
|
||||||
|
maskPhoneNumber(cellPhoneNo),
|
||||||
|
maskEmail(email));
|
||||||
|
|
||||||
|
// 사용자 생성 또는 업데이트
|
||||||
|
UserInfo userInfo = findOrCreateUser(info, extendedInfo);
|
||||||
|
|
||||||
|
// 로그인 세션 설정 (MainController 위임)
|
||||||
|
log.info("SSO 로그인 성공 - userId: {}", userId);
|
||||||
|
return mainController.setupSsoLoginSession(req, userInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 필수 필드 검증
|
||||||
|
*/
|
||||||
|
private void validateRequiredFields(Properties info, Properties extendedInfo) throws IllegalStateException {
|
||||||
|
validateField(info, "USERID", "사용자ID");
|
||||||
|
validateField(info, "NAME", "사용자명");
|
||||||
|
validateField(extendedInfo, "CELLPHONENO", "휴대폰번호");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateField(Properties props, String key, String fieldName) {
|
||||||
|
String value = props != null ? props.getProperty(key) : null;
|
||||||
|
if (StringUtils.isEmpty(value)) {
|
||||||
|
throw new IllegalStateException(fieldName + " - SSO 서버로 부터 전달 받지 못했습니다.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 사용자 조회 또는 생성
|
||||||
|
*/
|
||||||
|
private UserInfo findOrCreateUser(Properties info, Properties extendedInfo) throws Exception {
|
||||||
|
String userId = info.getProperty("USERID");
|
||||||
|
|
||||||
|
// 대소문자 구분 없이 검색
|
||||||
|
Optional<UserInfo> existingUser = userInfoService.findByUserIdIgnoreCase(userId);
|
||||||
|
|
||||||
|
if (existingUser.isPresent()) {
|
||||||
|
return updateUserIfNeeded(existingUser.get(), info, extendedInfo);
|
||||||
|
} else {
|
||||||
|
return createNewUser(info, extendedInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 신규 사용자 생성
|
||||||
|
*/
|
||||||
|
private UserInfo createNewUser(Properties info, Properties extendedInfo) throws Exception {
|
||||||
|
String userId = info.getProperty("USERID");
|
||||||
|
String name = info.getProperty("NAME");
|
||||||
|
String email = info.getProperty("EMAIL");
|
||||||
|
String cellPhoneNo = extendedInfo != null ? extendedInfo.getProperty("CELLPHONENO") : null;
|
||||||
|
String positionName = extendedInfo != null ? extendedInfo.getProperty("LEGACYPOSITIONNAME") : null;
|
||||||
|
String deptName = extendedInfo != null ? extendedInfo.getProperty("LEGACYDEPTNAME") : null;
|
||||||
|
|
||||||
|
UserInfo userInfo = new UserInfo();
|
||||||
|
userInfo.setUserid(userId);
|
||||||
|
userInfo.setUsername(name);
|
||||||
|
userInfo.setPassword(Seed.encrypt("!" + userId));
|
||||||
|
userInfo.setCphnno(cleanPhoneNumber(cellPhoneNo));
|
||||||
|
userInfo.setRoleidnfiname(CommonConstants.DEPT_DEVELOPER);
|
||||||
|
|
||||||
|
// 부가 필드 설정 (값이 있을 경우만)
|
||||||
|
if (StringUtils.isNotEmpty(email)) {
|
||||||
|
userInfo.setEmad(email);
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(positionName)) {
|
||||||
|
userInfo.setJobtlname(positionName);
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(deptName)) {
|
||||||
|
userInfo.setDvsnname(deptName);
|
||||||
|
}
|
||||||
|
|
||||||
|
userInfoService.save(userInfo);
|
||||||
|
|
||||||
|
// 기본 역할 할당
|
||||||
|
String roleId = monitoringContext.getStringProperty(
|
||||||
|
MonitoringContext.USER_DEFAULT_RULE, "newbie");
|
||||||
|
UserRole userRole = new UserRole();
|
||||||
|
userRole.setId(new UserRoleId(userId, roleId));
|
||||||
|
userRoleService.save(userRole);
|
||||||
|
|
||||||
|
// 서비스 타입 할당
|
||||||
|
DataSourceTypeManager.getDynamicDataSourceTypes().stream()
|
||||||
|
.map(DataSourceType::getName)
|
||||||
|
.forEach(type -> userServiceTypeService.insertUserServiceType(userId, type));
|
||||||
|
|
||||||
|
log.info("SSO 신규 사용자 생성 완료 - userId: {}", userId);
|
||||||
|
return userInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 기존 사용자 정보 업데이트 (변경된 필드만)
|
||||||
|
*/
|
||||||
|
private UserInfo updateUserIfNeeded(UserInfo userInfo, Properties info, Properties extendedInfo) {
|
||||||
|
boolean updated = false;
|
||||||
|
String userId = userInfo.getUserid();
|
||||||
|
|
||||||
|
String name = info.getProperty("NAME");
|
||||||
|
String email = info.getProperty("EMAIL");
|
||||||
|
String cellPhoneNo = extendedInfo != null ? extendedInfo.getProperty("CELLPHONENO") : null;
|
||||||
|
String positionName = extendedInfo != null ? extendedInfo.getProperty("LEGACYPOSITIONNAME") : null;
|
||||||
|
String deptName = extendedInfo != null ? extendedInfo.getProperty("LEGACYDEPTNAME") : null;
|
||||||
|
|
||||||
|
// 사용자명 업데이트
|
||||||
|
if (StringUtils.isNotEmpty(name) && !name.equals(userInfo.getUsername())) {
|
||||||
|
userInfo.setUsername(name);
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 휴대폰번호 업데이트
|
||||||
|
String cleanedPhone = cleanPhoneNumber(cellPhoneNo);
|
||||||
|
if (StringUtils.isNotEmpty(cleanedPhone) && !cleanedPhone.equals(userInfo.getCphnno())) {
|
||||||
|
userInfo.setCphnno(cleanedPhone);
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 이메일 업데이트
|
||||||
|
if (StringUtils.isNotEmpty(email) && !email.equals(userInfo.getEmad())) {
|
||||||
|
userInfo.setEmad(email);
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 직위명 업데이트
|
||||||
|
if (StringUtils.isNotEmpty(positionName) && !positionName.equals(userInfo.getJobtlname())) {
|
||||||
|
userInfo.setJobtlname(positionName);
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 부서명 업데이트
|
||||||
|
if (StringUtils.isNotEmpty(deptName) && !deptName.equals(userInfo.getDvsnname())) {
|
||||||
|
userInfo.setDvsnname(deptName);
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updated) {
|
||||||
|
userInfoService.save(userInfo);
|
||||||
|
log.info("SSO 사용자 정보 업데이트 완료 - userId: {}", userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return userInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 휴대폰번호에서 숫자만 추출
|
||||||
|
*/
|
||||||
|
private String cleanPhoneNumber(String phone) {
|
||||||
|
if (StringUtils.isEmpty(phone)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return phone.replaceAll("[^0-9]", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 휴대폰번호 마스킹 (로그용)
|
||||||
|
*/
|
||||||
|
private String maskPhoneNumber(String phone) {
|
||||||
|
if (StringUtils.isEmpty(phone) || phone.length() < 4) {
|
||||||
|
return "****";
|
||||||
|
}
|
||||||
|
// 010-1234-5678 → 010-****-5678
|
||||||
|
String cleaned = phone.replaceAll("[^0-9]", "");
|
||||||
|
if (cleaned.length() < 7) {
|
||||||
|
return "****";
|
||||||
|
}
|
||||||
|
return cleaned.substring(0, 3) + "****" + cleaned.substring(cleaned.length() - 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 이메일 마스킹 (로그용)
|
||||||
|
*/
|
||||||
|
private String maskEmail(String email) {
|
||||||
|
if (StringUtils.isEmpty(email) || !email.contains("@")) {
|
||||||
|
return "****";
|
||||||
|
}
|
||||||
|
int atIndex = email.indexOf("@");
|
||||||
|
if (atIndex <= 2) {
|
||||||
|
return "**" + email.substring(atIndex);
|
||||||
|
}
|
||||||
|
return email.substring(0, 2) + "**" + email.substring(atIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user