Initial commit
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
= 로그인
|
||||
|
||||
SDL은 Knox EpTray, ID/PW, ADFS 로그인을 지원한다.
|
||||
|
||||
== EpTray
|
||||
Knox EpTray 로그인은 Chrome, Edge 등 멀티 브라우저에서 가능하다.
|
||||
사용자가 Knox에 로그인을 한 후 시스템에 접속을 하게 되면 EpTray값을 이용해 시스템 로그인을 한다.
|
||||
|
||||
NOTE: Knox EpTray SSO 를 위한 연계 신청이 필요하다. (스테이지/운영) +
|
||||
자세한 내용 안내 및 문의는 Knox Support (매뉴얼 > KnoxPortal NewEpTray 연계 가이드) 를 참조한다.
|
||||
|
||||
=== EpTray 적용
|
||||
연계신청 과정에서 생성되는 *rsaprivkey8.pem* 파일을 +
|
||||
config.properties의 login.sso.knox-tray-private-key-path 경로에 넣어준다.
|
||||
|
||||
CAUTION: *rsaprivkey8.pem* 파일이 없는 경우 아래와 같은 에러가 발생하므로 주의한다.
|
||||
|
||||
image::newEpTrayUtil.png[Can not load new EpTray Private Key.png]
|
||||
|
||||
=== LoginPage.vue
|
||||
|
||||
UI 에서 사용자 정보가 없을 경우 LoginPage.vue 페이지로 이동하게 되고 인증 절차를 시작한다.
|
||||
|
||||
EpTray 연계를 위한 메서드
|
||||
|
||||
[source,javascript]
|
||||
----
|
||||
async loginByNewEpTray() {
|
||||
let loginResult = false;
|
||||
SDLUtil.showLoadingBar(true);
|
||||
await this.socConnect().then((data) => {
|
||||
this.newEpTrayKey = data;
|
||||
this.websocket.close();
|
||||
}).catch((err) => {
|
||||
SDLUtil.alert(err);
|
||||
});
|
||||
SDLUtil.showLoadingBar(false);
|
||||
|
||||
if (this.newEpTrayKey) {
|
||||
if (this.newEpTrayKey.result === 'success') {
|
||||
const { userInfo, key } = this.newEpTrayKey;
|
||||
loginResult = await this.loginNewEpTray({ userInfo, key });
|
||||
} else {
|
||||
SDLUtil.alert(`sdl.epTray.error.${this.newEpTrayKey.errorCode}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (!loginResult) {
|
||||
if (this.$route.query.token) {
|
||||
loginService.setToken(this.$route.query.token);
|
||||
document.location = `${SDLUtil.WEB_CONTEXT_PATH}/`;
|
||||
}
|
||||
}
|
||||
this.afterLoginProcess(loginResult);
|
||||
},
|
||||
----
|
||||
|
||||
[source,javascript]
|
||||
----
|
||||
socConnect() {
|
||||
return new Promise(((resolve, reject) => {
|
||||
const server = new WebSocket('wss://localhost:29283'); // <1>
|
||||
this.websocket = server;
|
||||
server.onopen = () => {
|
||||
server.send('{"rqtype":"getknoxsso","token":"","data":"KCC60TRAY0072"}'); // <2>
|
||||
server.onmessage = (event) => {
|
||||
const socketData = JSON.parse(event.data);
|
||||
if (socketData.rpcode === 'RETURN_SUCCESS') {
|
||||
resolve(JSON.parse(socketData.data));
|
||||
} else {
|
||||
this.websocket.close();
|
||||
let err;
|
||||
if (socketData.rpcode === 'EMPTY_BOX') err = 'sdl.epTray.rpCode.EMPTY_BOX';
|
||||
else err = `sdl.epTray.rpCode.${socketData.detail}`;
|
||||
reject(err);
|
||||
}
|
||||
};
|
||||
};
|
||||
server.onerror = () => {
|
||||
const err = 'sdl.epTray.rpCode.CONNECTION_FAILED';
|
||||
reject(err);
|
||||
};
|
||||
}));
|
||||
},
|
||||
----
|
||||
<1> WebSocket HOST 정보
|
||||
<2> 발급받은 연계용 system ID
|
||||
|
||||
=== LoginController.java
|
||||
|
||||
LoginController 에서는 EpTray값의 정보를 이용해 사용자를 로그인 한다.
|
||||
이때 시스템 사용자가 아닐 경우, 등록 화면으로 이동하고, 정상적인 시스템 사용자일 경우
|
||||
Token을 발급한다.
|
||||
|
||||
GET /noauth/login/new-eptray
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@PostMapping("/noauth/login/new-eptray")
|
||||
@Operation(value = "", description = "knox new eptray 로그인")
|
||||
public JwtResponse loginByNewEptray(HttpServletRequest request, HttpServletResponse response, @RequestParam String encodeUserInfo, @RequestParam String encodeAesKey ) throws AccountException {
|
||||
loginInterceptorExecutor.applyPreLogin(request, response);
|
||||
User user = authenticationService.loginByNewEpTray(encodeUserInfo, encodeAesKey);
|
||||
user.setRecentLoginIp(webUtil.getClientIp(request));
|
||||
JwtResponse jwtResponse = new JwtResponse(jwtUtil.generateToken(user), user.getUserId());
|
||||
user.setJwt(jwtResponse.getJwtToken().split("\\.")[2]);
|
||||
loginInterceptorExecutor.applyPostLogin(request, response, user);
|
||||
return jwtResponse;
|
||||
}
|
||||
----
|
||||
|
||||
== ADFS 로그인
|
||||
|
||||
NOTE: ADFS 통합인증 사이트 (https://adsso.sec.samsung.net) 에서 신청 후 사용해야 한다. +
|
||||
자세한 내용은 해당 사이트를 참조하거나 전자통합인증3 (nextsso3@samsung.com) 으로 문의 한다.
|
||||
|
||||
SDL에서는 ADFS 통합인증 사이트의 가이드를 참조하여 AD 로그인 샘플을 제공하고 있으며, 각 프로젝트 환경에 맞게 수정하여 사용한다.
|
||||
|
||||
=== 참고할 샘플 파일
|
||||
* LoginPage.vue
|
||||
* AdLoginController.java
|
||||
* onelogin.saml.properties
|
||||
|
||||
== 로그인/아웃 전,후 처리
|
||||
|
||||
로그인 전과 후, 로그아웃 전과 후 비즈니스 로직이 필요한 경우 LoginInterceptor를 상속받아 구현한다.
|
||||
|
||||
LoginInterceptor 클래스는 아래와 같은 Interface를 제공한다.
|
||||
[source, java]
|
||||
----
|
||||
/**
|
||||
* 로그인 전
|
||||
*/
|
||||
default void preLogin(HttpServletRequest request, HttpServletResponse response) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 로그인 후
|
||||
*/
|
||||
default void postLogin(HttpServletRequest request, HttpServletResponse response, User user) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 로그아웃 전
|
||||
*/
|
||||
default void preLogout(HttpServletRequest request, HttpServletResponse response, User user) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 로그아웃 후
|
||||
*/
|
||||
default void postLogout(HttpServletRequest request, HttpServletResponse response, User user) {
|
||||
}
|
||||
----
|
||||
|
||||
LoginInterceptor를 구현한 클래스는 LoginInterceptorExecutor에 의해 실행되며 Spring Bean으로 등록하고 SpringWebCofig에 아래와 같이 LoginInterceptorExecutor에 등록한다.
|
||||
|
||||
[source, java]
|
||||
----
|
||||
@Bean
|
||||
public LoginInterceptorExecutor loginInterceptorExecutor() {
|
||||
List<LoginInterceptor> loginInterceptorList = new ArrayList<>();
|
||||
loginInterceptorList.add(userUpdateInterceptor());
|
||||
loginInterceptorList.add(loginOutLogInterceptor());
|
||||
return new LoginInterceptorExecutor(loginInterceptorList);
|
||||
}
|
||||
----
|
||||
|
||||
아래는 로그인 후 사용자 정보를 update 하는 UserUpdateInterceptor의 일부분이다.
|
||||
|
||||
[source, java]
|
||||
----
|
||||
@Override
|
||||
public void postLogin(HttpServletRequest request, HttpServletResponse response, User user) {
|
||||
|
||||
String recentLoginIp = user.getRecentLoginIp();
|
||||
Date recentLoginDatetime = user.getRecentLoginDatetime();
|
||||
user.setLastLoginDate(recentLoginDatetime);
|
||||
user.setLastLoginIp(recentLoginIp);
|
||||
user.setRecentLoginDatetime(new Date());
|
||||
user.setRecentLoginIp(webUtil.getClientIp(request));
|
||||
user.setLastActivityTime(System.currentTimeMillis());
|
||||
userService.updateUser(user);
|
||||
}
|
||||
----
|
||||
Reference in New Issue
Block a user