소스 검색

user menu auth api add

shjung 3 년 전
부모
커밋
1332e5fb73

+ 82 - 14
src/main/java/com/its/op/controller/its/LoginController.java

@@ -2,16 +2,21 @@ package com.its.op.controller.its;
 
 import com.its.op.dto.its.LoginDto;
 import com.its.op.service.its.LoginService;
+import com.its.op.webapp.config.WebConfig;
+import com.its.utils.CookieUtils;
 import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.servlet.ModelAndView;
 
-import javax.validation.Valid;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 
 @Slf4j
 @RequiredArgsConstructor
@@ -31,16 +36,79 @@ public class LoginController {
     }
 */
 
-    @ApiOperation(value = "로그인", response = LoginDto.class)
-    @PostMapping(value = "/login", produces = {"application/json; charset=utf8"})
-    public LoginDto login(@RequestBody @Valid final LoginDto.LoginReqDto req) {
-        return this.service.login(req);
+//    @ApiOperation(value = "로그인", response = LoginDto.class)
+//    @PostMapping(value = "/login", produces = {"application/json; charset=utf8"})
+//    public LoginDto login(@RequestBody @Valid final LoginDto.LoginReqDto req) {
+//        return this.service.login(req);
+//    }
+
+    /**
+     * 로그인
+     * @param login
+     * @param model
+     * @return
+     */
+    @PostMapping("/login.do")
+    public String postLogin(@ModelAttribute LoginDto.LoginReqDto login, Model model) {
+        log.error("{}", login.toString());
+        log.error("{}", model.toString());
+        model.addAttribute("login", login);
+        return "success";
+    }
+
+//    @ApiOperation(value = "로그아웃")
+//    @PostMapping(value = "/logout", produces = {"application/json; charset=utf8"})
+//    public void logout(@RequestBody @Valid final LoginDto.LogoutReqDto req) {
+//        this.service.logout(req);
+//    }
+
+    /**
+     * 로그아웃
+     * @param request
+     * @param response
+     * @return
+     */
+    @GetMapping({"/logout.do"})
+    public ModelAndView getLogout(HttpServletRequest request, HttpServletResponse response) {
+        Cookie[] cookies = request.getCookies();
+        log.error("{}", cookies.length);
+        for (int ii = 0; ii < cookies.length; ii++) {
+            log.error("{}, {}", cookies[ii].getName(), cookies[ii].getValue());
+        }
+        String encUserId = "";
+        String loginHms = "";
+        if (cookies!= null && cookies.length > 0) {
+            try {
+                encUserId = CookieUtils.getCookie(request, WebConfig.USER_UUID);
+                loginHms = CookieUtils.getCookie(request, WebConfig.USER_TIME);
+            } catch (Exception e) {
+                log.error("{}", e.getMessage());
+            }
+        }
+
+        if (!"".equals(encUserId)) {
+            String userId = WebConfig.decUserId(encUserId);
+            LoginDto.LogoutReqDto req = LoginDto.LogoutReqDto.builder()
+                    .user_id(WebConfig.decUserId(userId))
+                    .login_hms(loginHms)
+                    .build();
+            log.info("logout: {}", req.toString());
+            this.service.logout(req);
+        }
+
+        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
+        if(auth != null) {
+            expiredCookie(response, WebConfig.USER_UUID);
+            expiredCookie(response, WebConfig.USER_TIME);
+            new SecurityContextLogoutHandler().logout(request, response, auth);
+        }
+        return new ModelAndView("forward:/application/login/login.html");
     }
 
-    @ApiOperation(value = "로그아웃")
-    @PostMapping(value = "/logout", produces = {"application/json; charset=utf8"})
-    public void logout(@RequestBody @Valid final LoginDto.LogoutReqDto req) {
-        this.service.logout(req);
+    private void expiredCookie(HttpServletResponse response, String cookieName) {
+        Cookie cookie = new Cookie(cookieName, null);
+        cookie.setMaxAge(0);
+        response.addCookie(cookie);
     }
 
 }

+ 14 - 13
src/main/java/com/its/op/dto/its/LoginDto.java

@@ -47,32 +47,32 @@ public class LoginDto implements Serializable {
     @NoArgsConstructor(access = AccessLevel.PROTECTED)
     public static class LoginReqDto {
 
-        @ApiModelProperty("사용자ID, Nullable = N, VARCHAR(20)")  // N VARCHAR(20)
-        @JsonProperty("user_id")
+        @ApiModelProperty("사용자 ID")
+        @JsonProperty("username")
         @Size(min=1, max=20)
-        private String userId;
+        private String username;
 
-        @ApiModelProperty("암호, Nullable = Y, VARCHAR(64)")  // Y VARCHAR(64)
-        @JsonProperty("pwd")
+        @ApiModelProperty("비밀번호")
+        @JsonProperty("password")
         @Size(min=1, max=64)
-        private String pwd;
+        private String password;
 
         @Builder
-        public LoginReqDto(String user_id, String pwd) {
-            this.userId = user_id;
-            this.pwd = pwd;
+        public LoginReqDto(String user_id, String password) {
+            this.username = user_id;
+            this.password = password;
         }
 
         public TbUserInfr toEntity() {
             return TbUserInfr.builder()
-                    .userId(this.userId)
-                    .pwd(this.pwd)
+                    .userId(this.username)
+                    .pwd(this.password)
                     .build();
         }
 
         public TbUserCnncHs toCnnsHsEntity() {
             return TbUserCnncHs.builder()
-                    .userId(this.userId)
+                    .userId(this.username)
                     .loginHms(ItsUtils.getSysTime())
                     .logoutHms("")
                     .build();
@@ -98,9 +98,10 @@ public class LoginDto implements Serializable {
         @Builder
         public LogoutReqDto(String user_id, String login_hms) {
             this.userId = user_id;
+            this.loginHms = login_hms;
         }
 
-        public TbUserCnncHs toCnnsHsEntity() {
+        public TbUserCnncHs toCnncHsEntity() {
             return TbUserCnncHs.builder()
                     .userId(this.userId)
                     .loginHms(this.loginHms)

+ 16 - 11
src/main/java/com/its/op/interceptor/ApiHandlerInterceptor.java

@@ -1,6 +1,7 @@
 package com.its.op.interceptor;
 
 import com.its.op.webapp.config.WebConfig;
+import com.its.utils.CookieUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang.StringUtils;
 import org.springframework.lang.Nullable;
@@ -8,6 +9,7 @@ import org.springframework.stereotype.Component;
 import org.springframework.web.servlet.HandlerInterceptor;
 import org.springframework.web.servlet.ModelAndView;
 
+import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
@@ -18,29 +20,32 @@ public class ApiHandlerInterceptor implements HandlerInterceptor {
 
     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        Cookie[] cookies = request.getCookies();
+        String userId = "";
+        String loginHms = "";
+        if (cookies != null && cookies.length > 0) {
+            userId = CookieUtils.getCookie(request, WebConfig.USER_UUID);
+            loginHms = CookieUtils.getCookie(request, WebConfig.USER_TIME);
+        }
+        if (userId == null || "".equals(userId)) {
+        }
+        else {
+            userId = WebConfig.decUserId(userId);
+        }
+
         if (StringUtils.equalsIgnoreCase("GET", request.getMethod())) {
             log.error("{}", request.getRequestURI());
         }
         else {
-            HttpSession session = request.getSession();
+            HttpSession session = request.getSession(false);
             log.error("{}: session: {}", request.getMethod(), session);
             if (session == null) {
                 log.error("권한이 없음. 로그인 되어 있지 않음.");
                 //response.sendRedirect("/error.html");
                 return false;
             }
-            String userId = WebConfig.decUserId(session.getAttribute(WebConfig.USER_UUID));
-            String loginHms = (String)session.getAttribute(WebConfig.USER_TIME);
             log.error("preHandle: {}, {}", userId, loginHms);
         }
-        //else {
-        log.error("preHandle1: {}", request.getContextPath());
-        log.error("preHandle2: {}", request.getPathInfo());
-        log.error("preHandle3: {}", request.getMethod());
-        log.error("preHandle4: {}", request.getAuthType());
-
-        //}
-//        log.error("preHandle: {}, {}, {}", request.getRequestURI(), request.getMethod(), handler);
         return true;
     }
 

+ 7 - 6
src/main/java/com/its/op/service/its/LoginService.java

@@ -1,10 +1,10 @@
 package com.its.op.service.its;
 
+import com.its.op.dao.repository.its.oper.TbUserCnncHsRepository;
+import com.its.op.dao.repository.its.oper.TbUserInfrRepository;
 import com.its.op.dto.its.LoginDto;
 import com.its.op.entity.its.oper.TbUserCnncHs;
 import com.its.op.entity.its.oper.TbUserInfr;
-import com.its.op.dao.repository.its.oper.TbUserCnncHsRepository;
-import com.its.op.dao.repository.its.oper.TbUserInfrRepository;
 import com.its.utils.ItsUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -28,11 +28,11 @@ public class LoginService {
     public LoginDto login(LoginDto.LoginReqDto req) {
 
         LoginDto result = LoginDto.builder()
-                .userId(req.getUserId())
+                .userId(req.getUsername())
                 .loginHms(ItsUtils.getSysTime())
                 .build();
 
-        Optional<TbUserInfr> userInfr = this.userRepo.findById(req.getUserId());
+        Optional<TbUserInfr> userInfr = this.userRepo.findById(req.getUsername());
         if (userInfr.isPresent()) {
             // found
             result.setLoginResult("success");
@@ -54,8 +54,9 @@ public class LoginService {
      */
     public void logout(LoginDto.LogoutReqDto req) {
 
-        TbUserCnncHs cnncHs = req.toCnnsHsEntity();
-        this.cnncHsRepo.save(cnncHs);
+        TbUserCnncHs cnncHs = req.toCnncHsEntity();
+        cnncHsRepo.updateData(cnncHs.getLoginHms(), cnncHs.getUserId(), cnncHs.getLogoutHms());
+        //this.cnncHsRepo.save(cnncHs);
     }
 
     /**

+ 34 - 16
src/main/java/com/its/op/webapp/config/WebSecurityConfig.java

@@ -5,6 +5,7 @@ import com.its.op.webapp.handler.LoginSuccessHandler;
 import com.its.op.webapp.security.WebPasswordEncoder;
 import com.its.op.webapp.service.WebLoginService;
 import lombok.RequiredArgsConstructor;
+import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.http.HttpMethod;
@@ -14,9 +15,11 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.builders.WebSecurity;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
 import org.springframework.security.core.session.SessionRegistry;
 import org.springframework.security.core.session.SessionRegistryImpl;
 import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.session.HttpSessionEventPublisher;
 
 @Configuration
 @EnableWebSecurity
@@ -56,11 +59,12 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
                 .antMatchers("/application/facility/**", "/facility/**").permitAll()
                 .antMatchers("/application/wall/**", "/wall/**").permitAll()
                 .antMatchers("/application/login/**").permitAll()
+                .antMatchers("/api/auth/**").permitAll()
                 .anyRequest().authenticated()
                 .and()
             .formLogin()
                 .loginPage("/application/login/login.html")
-                .loginProcessingUrl("/login.do")
+                .loginProcessingUrl("/api/auth/login.do")
                 .defaultSuccessUrl("/application/op/00.main/main.html", true)
                 .usernameParameter("username")
                 .passwordParameter("password")
@@ -68,11 +72,26 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
                 .failureHandler(this.loginFailureHandler)
                 .permitAll()
                 .and()
-//            .logout()
-//                .invalidateHttpSession(true)
-//                .deleteCookies("JSESSIONID")
-//                .logoutSuccessUrl("/login.do")
-//                .permitAll()
+            .logout()
+                .invalidateHttpSession(true)
+                .deleteCookies("JSESSIONID")
+                .deleteCookies(WebConfig.USER_UUID)
+                .deleteCookies(WebConfig.USER_TIME)
+                .logoutSuccessUrl("/api/auth/login.do").permitAll()
+                .and()
+            .sessionManagement()
+                .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)   // 스프링 시큐리티가 필요 시 생성 (default)
+                // 인증에 성공할 때 마다 세션 ID나 세션을 변경해서 발급해줌으로써
+                // 세션을 중간에서 가로채더라도 해당 세션이 유효하지 않게 하는 기능
+                .invalidSessionUrl("/api/auth/login.do")    // 세션이 유효하지 않을 경우 이동 할 페이지
+                .sessionFixation().changeSessionId()        // changeSessionId : 새로운 세션 ID를 발급해서 전달(default)
+                                                            // none            : 아무 동작 안함
+                                                            // migrateSession  : 새로운 세션을 생성해서 전달 (속성값 유지)
+                                                            // newSession      : 새로운 세션 전달 (속성값 유지 안됨)
+                .maximumSessions(20)                        // 최대 허용 가능 세션 수, -1인 경우 무제한 세션 허용
+                .maxSessionsPreventsLogin(true)             // 동시 로그인 차단, false 인 경우 기존 세션 만료(default)
+                .expiredUrl("/api/auth/logout.do")          // 세션이 만료된 경우 이동 할 페이지
+                .sessionRegistry(sessionRegistry())
 //                .and()
 //            .exceptionHandling()
 //                .accessDeniedPage("/login.do")
@@ -94,16 +113,6 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 //                .exceptionHandling().accessDeniedPage("/login");
         ;
 
-//        http.sessionManagement()
-//                .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
-//                .invalidSessionUrl("/login")
-//                .sessionFixation()
-//                .migrateSession()
-//                .maximumSessions(5)
-//                .maxSessionsPreventsLogin(true)
-//                .expiredUrl("/login")
-//                .sessionRegistry(sessionRegistry())
-//        ;
     }
 
     public DaoAuthenticationProvider daoAuthenticationProvider() {
@@ -134,4 +143,13 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
         return new SessionRegistryImpl();
     }
 
+    /**
+     * 로그아웃을 했기 때문에 세션의 개수가 0이라 생각했는데 로그인이 안되었다.
+     * 이에 대한 해결책으로 SessionRegistry 빈을 생성 후 sessionManagement 에 DI 시킨다.
+     * @return
+     */
+    @Bean
+    public static ServletListenerRegistrationBean httpSessionEventPublisher() {
+        return new ServletListenerRegistrationBean(new HttpSessionEventPublisher());
+    }
 }

+ 0 - 33
src/main/java/com/its/op/webapp/controller/WebController.java

@@ -1,20 +1,13 @@
 package com.its.op.webapp.controller;
 
-import com.its.op.webapp.config.WebConfig;
-import com.its.op.webapp.domain.Login;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
 import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
 import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.ModelAttribute;
-import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.servlet.ModelAndView;
 
-import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
@@ -50,32 +43,6 @@ public class WebController {
         return new ModelAndView("forward:/application/login/login.html");
     }
 
-    @PostMapping("/login.do")
-    public String postLogin(@ModelAttribute Login login, Model model) {
-        log.error("{}", login.toString());
-        log.error("{}", model.toString());
-        model.addAttribute("login", login);
-        return "success";
-    }
-
-    @GetMapping({"/logout.do"})
-    public ModelAndView getLogout(HttpServletRequest request, HttpServletResponse response) {
-        log.error("getLogout: {}", request);
-        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
-        if(auth != null) {
-            expiredCookie(response, WebConfig.USER_UUID);
-            expiredCookie(response, WebConfig.USER_TIME);
-            new SecurityContextLogoutHandler().logout(request, response, auth);
-        }
-        return new ModelAndView("forward:/application/login/login.html");
-    }
-
-    private void expiredCookie(HttpServletResponse response, String cookieName) {
-        Cookie cookie = new Cookie(cookieName, null);
-        cookie.setMaxAge(0);
-        response.addCookie(cookie);
-    }
-
     /**
      * 시설물 관리 리다이렉션
      * @param request

+ 0 - 15
src/main/java/com/its/op/webapp/domain/Login.java

@@ -1,15 +0,0 @@
-package com.its.op.webapp.domain;
-
-import lombok.Builder;
-import lombok.Data;
-
-import java.io.Serializable;
-
-@Data
-@Builder
-public class Login  implements Serializable {
-    private static final long serialVersionUID = 1L;
-
-    private String username;
-    private String password;
-}

+ 2 - 0
src/main/java/com/its/op/webapp/domain/UserInfrVo.java

@@ -23,6 +23,7 @@ import java.util.Set;
 @NoArgsConstructor(access = AccessLevel.PROTECTED)
 @Builder
 @AllArgsConstructor
+@EqualsAndHashCode(of = "userId")
 public class UserInfrVo implements UserDetails {
     private static final long serialVersionUID = 1L;
 
@@ -157,4 +158,5 @@ public class UserInfrVo implements UserDetails {
         log.error("isEnabled: {}", StringUtils.equalsIgnoreCase("N", this.delYn));
         return StringUtils.equalsIgnoreCase("N", this.delYn);
     }
+
 }

+ 10 - 6
src/main/java/com/its/op/webapp/handler/LoginSuccessHandler.java

@@ -1,9 +1,10 @@
 package com.its.op.webapp.handler;
 
-import com.its.op.entity.its.oper.TbUserCnncHs;
 import com.its.op.dao.repository.its.oper.TbUserCnncHsRepository;
+import com.its.op.entity.its.oper.TbUserCnncHs;
 import com.its.op.webapp.config.WebConfig;
 import com.its.op.webapp.domain.UserInfrVo;
+import com.its.utils.CookieUtils;
 import com.its.utils.ItsUtils;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -15,7 +16,6 @@ import org.springframework.security.web.authentication.WebAuthenticationDetails;
 import org.springframework.stereotype.Service;
 
 import javax.servlet.ServletException;
-import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
@@ -64,12 +64,16 @@ public class LoginSuccessHandler implements AuthenticationSuccessHandler {
                 .build();
         this.cnncHsRepo.insertData(cnncHs.getLoginHms(), cnncHs.getUserId(), cnncHs.getLogoutHms());
 
+        log.info("cnncHs: {}, {}", cnncHs.getUserId(), cnncHs.getLoginHms());
+
         request.getSession().setAttribute(WebConfig.USER_UUID, WebConfig.encUserId(cnncHs.getUserId()));
         request.getSession().setAttribute(WebConfig.USER_TIME, cnncHs.getLoginHms());
-        Cookie userIdCookie   = new Cookie(WebConfig.USER_UUID, WebConfig.encUserId(cnncHs.getUserId()));
-        Cookie loginHmsCookie = new Cookie(WebConfig.USER_TIME, cnncHs.getLoginHms());
-        response.addCookie(userIdCookie);
-        response.addCookie(loginHmsCookie);
+        try {
+            CookieUtils.setCookie(response, WebConfig.USER_UUID, WebConfig.encUserId(cnncHs.getUserId()), 60*60);
+            CookieUtils.setCookie(response, WebConfig.USER_TIME, cnncHs.getLoginHms(), 60*60);
+        } catch (Exception e) {
+            log.error("{}", e.getMessage());
+        }
 
         String defaultSuccessUrl = "/application/op/00.main/main.html";
         String uri = defaultSuccessUrl;

+ 43 - 0
src/main/java/com/its/utils/CookieUtils.java

@@ -0,0 +1,43 @@
+package com.its.utils;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class CookieUtils {
+
+    public static void setCookie(HttpServletResponse response, String key, String value, int maxAge) throws Exception {
+        Cookie cookie = new Cookie(key, value);
+        //cookie.setMaxAge(maxAge);
+        response.addCookie(cookie);
+    }
+
+    public static Cookie createCookie(String name, String value, int expiry, boolean isSecure, boolean httpOnly, String path, String domain ) {
+        Cookie cookie = new Cookie(name, value);
+        cookie.setMaxAge(expiry);
+        cookie.setSecure(true);
+        cookie.setHttpOnly(httpOnly);
+        cookie.setPath(path);
+        cookie.setDomain(domain);
+        return cookie;
+    }
+
+    public static void delCookie(HttpServletResponse response, String key) throws Exception {
+        Cookie cookie = new Cookie(key, null);
+        cookie.setMaxAge(0);
+        response.addCookie(cookie);
+    }
+
+    public static String getCookie(HttpServletRequest request, String key) throws Exception {
+        Cookie[] cookies = request.getCookies();
+        if (cookies != null) {
+            for(int ii = 0; ii < cookies.length; ii++) {
+                if (key.equals(cookies[ii].getName())) {
+                    return cookies[ii].getValue();
+                }
+            }
+        }
+        return "";
+    }
+
+}

+ 1 - 1
src/main/resources/static/application/login/login.html

@@ -11,7 +11,7 @@
     </head>
     <body>
         <div class="flex-container">
-            <form method="POST" action="/login.do">
+            <form method="POST" action="/api/auth/login.do">
                 <span class="logoImage"></span>
                 <div class="title-line">용인시 ITS 통합운영단말 로그인</div>
                 <div class="under-line"></div>