login, logout 동작 추가.
parent
701047e22e
commit
c5c3dd3850
|
|
@ -12,8 +12,7 @@ function EgovHeader({ loginUser, onChangeLogin }) {
|
|||
console.log("[Start] EgovHeader ------------------------------");
|
||||
|
||||
const sessionUser = getSessionItem('loginUser');
|
||||
const sessionUserId = sessionUser?.id;
|
||||
const sessionUserName = sessionUser?.name;
|
||||
const sessionUserId = sessionUser?.userId;
|
||||
const sessionUserSe = sessionUser?.userSe;
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
|
@ -85,7 +84,7 @@ function EgovHeader({ loginUser, onChangeLogin }) {
|
|||
{/* 로그아웃 : 로그인 정보 있을때 */}
|
||||
{sessionUserId &&
|
||||
<>
|
||||
<span className="person">{sessionUserName} </span> 님이, 관리자로 로그인하셨습니다.
|
||||
<span className="person">{sessionUserId} </span> 님이, {sessionUserSe==='ADM'?'관리자':'사용자'}로 로그인하셨습니다.
|
||||
<button onClick={logOutHandler} className="btn">로그아웃</button>
|
||||
</>
|
||||
}
|
||||
|
|
@ -161,7 +160,7 @@ function EgovHeader({ loginUser, onChangeLogin }) {
|
|||
{/* 로그아웃 : 로그인 정보 있을때 */}
|
||||
{sessionUserId &&
|
||||
<>
|
||||
<span className="person">{sessionUserName} </span>이 로그인하셨습니다.
|
||||
<span className="person">{sessionUserId} </span>이 로그인하셨습니다.
|
||||
<button onClick={logOutHandler} className="btn logout">로그아웃</button>
|
||||
</>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ function EgovLoginContent(props) {
|
|||
const submitFormHandler = (e) => {
|
||||
console.log("EgovLoginContent submitFormHandler()");
|
||||
|
||||
const loginUrl = "/login"
|
||||
const loginUrl = "/auth/login"
|
||||
const requestOptions = {
|
||||
method: "POST",
|
||||
headers: {
|
||||
|
|
@ -74,7 +74,6 @@ function EgovLoginContent(props) {
|
|||
EgovNet.requestFetch(loginUrl,
|
||||
requestOptions,
|
||||
(resp) => {
|
||||
debugger
|
||||
let resultVO = resp.resultVO;
|
||||
let jToken = resp?.jToken || null;
|
||||
|
||||
|
|
@ -108,28 +107,26 @@ function EgovLoginContent(props) {
|
|||
<p className="txt">전자정부표준프레임워크 경량환경 홈페이지 로그인 페이지입니다.<br />로그인을 하시면 모든 서비스를 제한없이 이용하실 수 있습니다.</p>
|
||||
|
||||
<div className="login_box">
|
||||
<form name="" method="" action="" onSubmit={submitFormHandler}>
|
||||
<fieldset>
|
||||
<legend>로그인</legend>
|
||||
<span className="group">
|
||||
<fieldset>
|
||||
<legend>로그인</legend>
|
||||
<span className="group">
|
||||
<input type="text" name="" title="아이디" placeholder="아이디" value={userInfo?.username}
|
||||
onChange={e => setUserInfo({ ...userInfo, username: e.target.value })} />
|
||||
onChange={e => setUserInfo({ ...userInfo, username: e.target.value })} />
|
||||
<input type="password" name="" title="비밀번호" placeholder="비밀번호"
|
||||
onChange={e => setUserInfo({ ...userInfo, password: e.target.value })} />
|
||||
onChange={e => setUserInfo({ ...userInfo, password: e.target.value })} />
|
||||
</span>
|
||||
<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="submit"><span>LOGIN</span></button>
|
||||
</fieldset>
|
||||
</form>
|
||||
<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>
|
||||
</div>
|
||||
|
||||
<ul className="list">
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ public class LoginVO implements Serializable{
|
|||
@NotBlank(message = "비밀번호확인을 입력해주세요.")
|
||||
private String passwordChk;
|
||||
|
||||
@Schema(description = "사용자 구분", allowableValues = {"GNR", "ENT", "USR"}, defaultValue = "USR")
|
||||
@Schema(description = "사용자 구분", allowableValues = {"ADM", "USR"}, defaultValue = "USR")
|
||||
private String userSe;
|
||||
|
||||
@Schema(description = "이름")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
package com.dbnt.kcscbackend.config.security;
|
||||
|
||||
import com.dbnt.kcscbackend.auth.entity.UserInfo;
|
||||
import com.dbnt.kcscbackend.config.jwt.EgovJwtTokenUtil;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.http.server.ServletServerHttpResponse;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
|
||||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
|
||||
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
|
||||
import org.springframework.security.web.savedrequest.RequestCache;
|
||||
import org.springframework.security.web.savedrequest.SavedRequest;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
@Configuration
|
||||
public class CustomLogoutSuccessHandler implements LogoutSuccessHandler {
|
||||
|
||||
@Override
|
||||
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
|
||||
|
||||
|
||||
MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
|
||||
MediaType jsonMimeType = MediaType.APPLICATION_JSON;
|
||||
|
||||
HashMap<String, Object> resultMap = new HashMap<String, Object>();
|
||||
resultMap.put("resultCode", "200");
|
||||
if (jsonConverter.canWrite(resultMap.getClass(), jsonMimeType)) {
|
||||
jsonConverter.write(resultMap, jsonMimeType, new ServletServerHttpResponse(response));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
package com.dbnt.kcscbackend.config.security;
|
||||
|
||||
import com.dbnt.kcscbackend.auth.entity.UserInfo;
|
||||
import com.dbnt.kcscbackend.config.jwt.EgovJwtTokenUtil;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.http.server.ServletServerHttpResponse;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
|
||||
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
|
||||
import org.springframework.security.web.savedrequest.RequestCache;
|
||||
import org.springframework.security.web.savedrequest.SavedRequest;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
@Configuration
|
||||
public class CustomUrlAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
|
||||
|
||||
private final EgovJwtTokenUtil jwtTokenUtil = new EgovJwtTokenUtil();
|
||||
private RequestCache requestCache = new HttpSessionRequestCache();
|
||||
|
||||
@Override
|
||||
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authentication) throws ServletException, IOException {
|
||||
|
||||
SavedRequest savedRequest = requestCache.getRequest(request, response);
|
||||
|
||||
if (savedRequest != null) {
|
||||
requestCache.removeRequest(request, response);
|
||||
clearAuthenticationAttributes(request);
|
||||
}
|
||||
|
||||
UserInfo securityUser = null;
|
||||
if (SecurityContextHolder.getContext().getAuthentication() != null) {
|
||||
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
if (principal instanceof UserDetails) {
|
||||
securityUser = (UserInfo) principal;
|
||||
}
|
||||
}
|
||||
|
||||
// application/json(ajax) 요청일 경우 아래의 처리!
|
||||
MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
|
||||
MediaType jsonMimeType = MediaType.APPLICATION_JSON;
|
||||
|
||||
String jwtToken = jwtTokenUtil.generateToken(securityUser);
|
||||
securityUser.setPassword(null);
|
||||
securityUser.setUserSeq(null);
|
||||
HashMap<String, Object> resultMap = new HashMap<String, Object>();
|
||||
resultMap.put("resultCode", "200");
|
||||
resultMap.put("resultVO", (UserDetails)securityUser);
|
||||
resultMap.put("jToken", jwtToken);
|
||||
// String userName = jwtTokenUtil.getUserSeFromToken(jwtToken);
|
||||
response.addHeader("Authorization", "BEARER "+jwtToken);
|
||||
if (jsonConverter.canWrite(resultMap.getClass(), jsonMimeType)) {
|
||||
jsonConverter.write(resultMap, jsonMimeType, new ServletServerHttpResponse(response));
|
||||
}
|
||||
}
|
||||
|
||||
public void setRequestCache(RequestCache requestCache) {
|
||||
this.requestCache = requestCache;
|
||||
}
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ import java.nio.charset.StandardCharsets;
|
|||
@Slf4j
|
||||
public class JsonUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
|
||||
|
||||
private static final String DEFAULT_LOGIN_REQUEST_URL = "/login"; // /login/oauth2/ + ????? 로 오는 요청을 처리할 것이다
|
||||
private static final String DEFAULT_LOGIN_REQUEST_URL = "/auth/login"; // /login/oauth2/ + ????? 로 오는 요청을 처리할 것이다
|
||||
private static final String HTTP_METHOD = "POST"; //HTTP 메서드의 방식은 POST 이다.
|
||||
private static final String CONTENT_TYPE = "application/json";//json 타입의 데이터로만 로그인을 진행한다.
|
||||
private static final AntPathRequestMatcher DEFAULT_LOGIN_PATH_REQUEST_MATCHER =
|
||||
|
|
|
|||
|
|
@ -27,9 +27,11 @@ import org.springframework.security.web.SecurityFilterChain;
|
|||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.logout.LogoutHandler;
|
||||
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
|
||||
import org.springframework.security.web.savedrequest.SavedRequest;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
|
|
@ -69,7 +71,7 @@ public class SecurityConfig {
|
|||
// 인증 예외 List
|
||||
private String[] AUTH_WHITELIST = {
|
||||
"/",
|
||||
"/login/**",
|
||||
"/auth/login",
|
||||
"/login",
|
||||
"/auth/join",//회원가입
|
||||
"/cmm/main/**.do", // 메인페이지
|
||||
|
|
@ -128,28 +130,18 @@ public class SecurityConfig {
|
|||
);
|
||||
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
|
||||
|
||||
http.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class)
|
||||
|
||||
http.cors().and().addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class)
|
||||
.exceptionHandling(exceptionHandlingConfigurer ->
|
||||
exceptionHandlingConfigurer
|
||||
.authenticationEntryPoint(new JwtAuthenticationEntryPoint())
|
||||
);
|
||||
|
||||
http.cors().and().addFilterBefore(jsonUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
|
||||
http.addFilterBefore(jsonUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
|
||||
http.logout().logoutRequestMatcher(new AntPathRequestMatcher("/auth/logout")).logoutSuccessHandler(new CustomLogoutSuccessHandler());
|
||||
return http.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticationSuccessHandler loginSuccessHandler() {
|
||||
return (request, response, authentication) -> {
|
||||
UserInfo info = (UserInfo)authentication.getPrincipal();
|
||||
|
||||
String jwtToken = jwtTokenUtil.generateToken(info);
|
||||
// String userName = jwtTokenUtil.getUserSeFromToken(jwtToken);
|
||||
response.addHeader("Authorization", "BEARER "+jwtToken);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticationFailureHandler loginFailureHandler(){
|
||||
return (request, response, exception) -> {
|
||||
|
|
@ -159,7 +151,7 @@ public class SecurityConfig {
|
|||
|
||||
@Bean
|
||||
public JsonUsernamePasswordAuthenticationFilter jsonUsernamePasswordAuthenticationFilter() {
|
||||
JsonUsernamePasswordAuthenticationFilter jsonUsernamePasswordAuthenticationFilter = new JsonUsernamePasswordAuthenticationFilter(objectMapper, loginSuccessHandler(), loginFailureHandler());
|
||||
JsonUsernamePasswordAuthenticationFilter jsonUsernamePasswordAuthenticationFilter = new JsonUsernamePasswordAuthenticationFilter(objectMapper, new CustomUrlAuthenticationSuccessHandler(), loginFailureHandler());
|
||||
jsonUsernamePasswordAuthenticationFilter.setAuthenticationManager(authenticationManager());
|
||||
return jsonUsernamePasswordAuthenticationFilter;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue