ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 세션 로그인 구현 복습
    프로젝트 2022. 11. 22. 19:32

    저번 프로젝트 때는 세션을 활용해 로그인을 구현했었다.

    당시에는 서비스를 배포까지 계획이 없었기 때문에 세션으로도 충분했다.

    하지만 굉장히 대충 만든 로그인이었고 이번 프로젝트에서는 JWT 방법을 이용하고자 한다.

    또한 가능하다면 카카오/구글 등으로도 로그인을 가능하게 구현하는 것이 목표이다.

     

    JWT 로그인 구현 방식에 대해 간략하게 찾아보니... 대충 봐도 어려웠다.

    이왕 공부하는거 세션 로그인부터 시작해서 총체적으로 정리해야겠다.

     

     

     


     

    저번 프로젝트 때 로그인은 아래와 같은 코드로 구현했다.

     

    1. controller

    @Controller
    public class LoginController {
    	
    	private LoginService service;
    	
    	@Autowired
    	public LoginController(LoginService service) {
    		this.service = service;
    	}
    	
    	@GetMapping(value="/login")
    	public String login(HttpServletRequest request) {
    		return "login";
    	}
    	
    	@PostMapping(value="/loginok")
    	public void loginok(HttpSession session, HttpServletResponse resp, HttpServletRequest req, LoginDTO dto, Model model) {
    		
    		LoginDTO result = service.login(dto);
    		
    		try {
    			
    			if (result != null) {
    				session.setAttribute("result", result);
    				resp.sendRedirect("/web/dashboardall");
    			} else {
    				session.removeAttribute("result");
    				resp.setCharacterEncoding("UTF-8");
    				resp.setContentType("text/html; charset=UTF-8");
    				PrintWriter out = resp.getWriter();
    				out.println("<script>alert('아이디 또는 비밀번호가 틀렸습니다.'); location.href='/web/login';</script>");
    				out.flush();	
    			}
    			
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    	
    	@GetMapping(value="/logout")
    	public String logout(HttpSession session, HttpServletRequest req) {
    		session.removeAttribute("result");
    		return "redirect:/login";
    	}
    	
    }

     

    2. DAO

    public interface LoginDAO {
    
    	LoginDTO login(LoginDTO dto);
    
    }

     

    3. DAOImpl

    @Repository
    public class LoginDAOImpl implements LoginDAO {
    
    	private SqlSessionTemplate template;
    	
    	@Autowired
    	public LoginDAOImpl(SqlSessionTemplate template) {
    		this.template = template;
    	}
    
    	@Override
    	public LoginDTO login(LoginDTO dto) {
    		return this.template.selectOne("login.login", dto);
    	}
    
    }

     

    4. DTO

    import lombok.Data;
    
    @Data
    public class LoginDTO {
    	
    	private String employeeseq;
    	private String ename;
    	private String role;
    	private String email;
    	private String pw;
    	private String position;
    	private String tname;
    	private String pname;
    	private String pjsdate;
    	private String pjfdate;
    	private String pstate;
    	private String levelseq;
    
    }

     

    5. Service

    public interface LoginService {
    
    	LoginDTO login(LoginDTO dto);
    
    }

     

    6. ServiceImpl

    @Service
    public class LoginServiceImpl implements LoginService {
    
    	private LoginDAO dao;
    	
    	@Autowired
    	public LoginServiceImpl(LoginDAO dao) {
    		this.dao = dao;
    	}
    
    	@Override
    	public LoginDTO login(LoginDTO dto) {
    		return dao.login(dto);
    	}
    
    }

     

    HttpSession을 이용해 로그인을 구현했고 장점은 HttpSession을 필요할 때만 생성하는 것이 가능하다는 점이다.

    로그아웃하면 해당 세션을 제거하고 다시 로그인 페이지로 이동하도록 코드를 작성했다.

     

    이 세션 정보를 이용해서 로그인한 사람의 직책에 따라 다른 메뉴가 보이도록 jsp 코드를 작성했다.

    이런 부분을 구현하기 위해 처음 로그인 시 세션에 최대한 많은 정보를 저장했다.

    구현하다가 필요한 정보가 있으면 DB 조합으로 만드는 게 아니라 세션에 정보를 추가했다.

    보안 등 여러 요소를 고려하지 않았고 일단 로그인이 되는기 위한 코드였다.

    그러다 보니 이 과정에서 공부하고 배운 것이 없는 것 같다.

     

    <!-- 관리자 -->
    <li class="nav-item admin">
        <a class="nav-link collapsed admin" data-toggle="collapse" data-target="#collapseAdmin" aria-expanded="true" aria-controls="collapseAdmin"> 
            <i class="fas fa-fw fa-cog admin"></i> <span class="admin">관리자</span>
        </a>
    	<div id="collapseAdmin" class="collapse" aria-labelledby="headingOne" data-parent="#accordionSidebar">
    		<div class="bg-white py-2 collapse-inner rounded">
    			<a class="collapse-item " href="/web/adminuser">사용자 관리</a>
    			<a class="collapse-item " href="/web/adminproject">프로젝트 관리</a>
    		</div>
    	</div>
    </li>
    <script>
    $(function() {
    		
    	var role = "${sessionScope.result.role}";
    	var levelseq = "${sessionScope.result.levelseq}";
    		
    	if (levelseq == 1) {
    		$(".admin").show();
    	} else {
    		$(".admin").hide();
    	}
    		
    	if (role == "PL") {
    		 $(".adminProject").show();
    	} else {
    		 $(".adminProject").hide();
    	}
    		
    });
    </script>

     

     

    로그인 상태 유지하는 2가지 방법

    1. 요청할 때 사용자 정보를 쿼리 파라미터로 전달하기

    > 번거롭고 식별 가능한 사용자 정보를 쿼리 파라미터에 노출하는 것은 보안상 위험하다.

    2. 쿠키에 사용자 정보 담아서 사용하기

    > 서버에서 로그인 성공 시 HTTP 응답에 쿠키를 담아 브라우저에 전달, 브라우저는 쿠키를 지속적으로 서버에 보내서 서버는 사용자를 식별할 수 있다.

    3. 쿠키에 세션 정보 담아서 사용하기

     

     

    쿠키 종류

    1. 영속 쿠키 : 만료 날짜까지 유지

    2. 세션 쿠키 : 브라우저 종료 시까지만 유지

     

     

    쿠키의 보안 문제

    1. 쿠키 값은 임의로 변경 가능하다

    > 클라이언트가 쿠키를 강제로 변경하면 다른 사용자가 됨

    > 웹브라우저 개발자 모드 Application Cookie 변경으로 확인 가능

    2. 쿠키에 보관된 정보를 훔쳐갈 수 있다.

    > 쿠키에 개인 정보 등이 있다면 이 정보가 웹 브라우저에 보관되고 네트워크 요청마다 계속 클라이언트 서버로 전달됨

    > 쿠키의 정보가 나의 로컬 PC 혹은 네트워크 전송 구간에서 해킹당할 수 있다.

    3. 해커가 쿠키를 훔쳐가면 평생 사용할 수 있다.

     

     

     


    * 지금까지 내가 말하는 session과 쿠키는 같은 것? 세션 쿠키 / 영속 쿠키였던 것 같다

    > 네트워크에 대한 지식이 없어 모르는 것 같다. 적어도 이 부분은 찾아서 정리 하기

    * 보통은 세션 정보를 쿠키에 저장해 로그인을 구현하는 것 같다

    > 이 방법으로 다시 구현해 보기

    * 스프링 시큐리티를 이용해 로그인을 구현하는 것도 좋은 방법인 것 같다


     

    참고

    https://develop-writing.tistory.com/m/87

    https://catsbi.oopy.io/0c27061c-204c-4fbf-acfd-418bdc855fd8

    https://jaehoney.tistory.com/67

     

    728x90

    '프로젝트' 카테고리의 다른 글

    웹 API를 위한 JSON vs XML  (0) 2023.04.25
    프로젝트 기본 환경설정 - 1  (0) 2023.01.18
    REST와 REST API  (0) 2022.12.26
    스프링 프레임워크(Framework)에 대하여, 스프링부트?  (0) 2022.12.04
    API 와 오픈 API  (0) 2022.11.22
Designed by Tistory.