본문 바로가기
프로그래밍/SpringBoot

[스프링 부트 게시판] 로그인 기능 / 세션 구현하기

by 소소로드 2020. 10. 15.

로그인 기능 / 세션 구현하기


게시판까지 만들었다면 회원제로 유지되는 게시판을 만들어도 좋을 것 같다.
내가 짜놓은 내용은 첫 화면에 로그인 화면이 있고 아이디, 비밀번호가 맞으면 게시판 리스트로 이동하며
그렇지 않으면 로그인 화면을 유지하도록 하는 방식이다.

즉, 로그인 창 화면이 index 화면이 된다.
물론 게시판 리스트 주소를 알면 로그인은 무용지물이니까 이 부분은 나중에 보완한다.
로그인 실패시 팝업을 뜨게 하는 경우도 있고 그 화면에서 멈춘채 내용만 삭제되는 경우도 있는데
나는 후자를 택해서 사용하였다.

순서
1. 회원에 관한 테이블 작성 / 같은 객체 생성
2. 컨트롤러를 통한 세션만들기 + 나머지 구현



1. 테이블 작성



나는 hello_member라는 이름으로 간단한 회원관리용 테이블을 만들었다.
사실 필드명을 저렇게 써서는 안된다 TT
필드명은 member_id, member_pass 이런식으로 만들어야 맞는데
왜 저렇게 썼는지 모르겠다.(아마 옛날에 이름을 일치시키다가 뭐가 안되어서 저렇게 한듯..)
그대로 써주거나 맞는 필드이름 작성법대로 작성하면 좋을 것 같다.
나중에 mapper.xml에 쓸때만 주의하면 된다.


2. memberVO 객체 만들기

1
2
3
4
5
6
7
8
9
10
@Setter
@Getter
public class MemberVO implements Serializable {
 
    private String memberId;
    private String memberPass;
    private String memberName;
}
cs


3. Controller, service, DAO, mapper 작성


BoardController
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/** Login **/
    @RequestMapping(value="/index", method= {{RequestMethod.GET, RequestMethod.POST})
    public String memberLogin(MemberVO memberVO, HttpServletRequest req, , RedirectAttributes rttrthrows Exception {
        
        HttpSession session = req.getSession();
        MemberVO member = boardService.memberLogin(memberVO);
        
        if(member == null) {
            session.setAttribute("member"null);
rttr.addFlashAttribute("msg", false);
        } else {
            session.setAttribute("member", member);
        }
        
        return "redirect:/";
    }
cs

내용이 많은데 하나하나 정리를 하자면

method= {RequestMethod.POST}
보통 지정하지 않으면 get방식을 사용하는데
로그인을 해서 게시판 목록에 들어갈때는 post방식을 사용하기 때문에 넣어주었다.
RequestMethod.GET을 굳이 넣은 이유는 안써주면
/index라는 주소를 타고 들어갈 때(url) 오류가 뜰까봐 넣어주었다.

만약 로그인 창에서 이름, 비밀번호를 입력하고 넘어갈때 get 방식을 쓰게 되면
URL로 http://localhost:8585/boardList?memberid=nada&pass=1188 이런식으로 나타날 텐데
그러면 보안에 문제가 된다. body에 담아서 사용하는 방법인 post방식을 이용하기 위해 쓴다.


HttpServletRequest req
HttpSession session = req.getSession();

session.setAttribute("member", null);
session.setAttribute("member", member);

: 우리가 url을 입력하고 땅! 치면, WAS는 HttpServletRequest와 HttpServletResponse를 생성한다.
그러면 HttpServletRequest에는 당연히 나의 요청정보들이 들어가있을 것이다.

그 정보들을 가져오기 위해서 HttpServletRequest 를 사용했다고 볼 수 있다.
그 중에서 세션정보 getSession() 메서드는 로그인에 어떤 역할을 할까?
로그인을 하고 난뒤 일정 시간동안 아이디/비밀번호가 유지되는 이유는 세션이 클라이언트의 요청을 지속하게 만들어준다. 

* 세션 : 사용자의 정보가 서버에 저장된다. 서버접속시 세션 ID를 발급받아서 일정 시간동안 유지된다.
<=> 쿠키는 사용자의 정보가 브라우저에 저장된다.

세션은 직접 이름을 지정할 수도 있는데
세션을 생성하기 위해서는 HttpServletRequest 객체의 getSession() 메서드를 이용해서 HttpSession에 담아준다.
getSession() 메서드는 클라이언트가 가지고 있는 세션 ID와 동일한 세션 객체를 찾아 주소값을 반환한다.

member객체가 null이 아니라면 session.setAttribute을 통해 member라는 이름으로 객체를 저장한다.
if구문은 페이지로 넘어갈때 member의 유무에 따라 다음페이지로 갈건지, 로그인창에만 있을건지를 지정한다.


rttr.addFlashAttribute("msg", false);

1회성의 데이터라서 다른 페이지로 넘어가면 사라지는 부분인데
로그인 실패시 1회적으로 아이디, 비밀번호가 일치하는지 알아보기 위해 사용하는 부분이다

return "redirect:/";

스프링부트의 루트 설정은 application.properties에서 하는데
나는 기본루트(localhost:8282/)에 대한 지정을 어디서도 한 적이 없고
컨트롤러에서 /로 매핑한 적이 없음에도 불구하고
자동으로 index.jsp를 인식하는 것을 보고 폭풍 검색을 했더니 이런 문서가 나왔다.

https://qastack.kr/programming/27381781/java-spring-boot-how-to-map-my-app-root-to-index-html
요약하자면 [Spring Boot는 public / static / webapp 폴더에서 index.html을 자동으로 감지한다.] 는 것.

그러므로, 작동 방식은 다음과 같다.

1. localhost:8282/index를 땅 치컨트롤러에서 /index를 타고 서비스 내용을 구현한다.
2. redirect:/로 리턴하는데 기본 루트가 어차피 index.jsp이므로 해당되는 뷰를 보여준다.
3. member가 구현된 적이 없으므로 "로그인 실패"가 바로 뜨는 것은 당연하다.
4. 그러니 localhost:8282(정말 뷰만 보여주는)로 들어가면 해결.
참고로 기본루트로 들어가면 index로 들어가서 해당 내용을 행위하는게 아니라 바로 뷰로 들어간다.

만약 요청 주소를 index가 아닌 login, view 이런 식으로 한다면 매핑을 따로 만들어주면 해결된다.



지금까지 비슷한 내용을 반복하고 있으므로 같은 소스창에 넣었다.

BoardService, BoardMapper(DAO), BoardMapper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
     // BoardService
     public MemberVO memberLogin(MemberVO memberVO) throws Exception {
         return boardMapper.memberLogin(memberVO);
     }
 
     // BoardMapper
     public MemberVO memberLogin(MemberVO memberVO) throws Exception;
 
 
     // BoardMapper.xml
    <select id="memberLogin" resultType="MemberVO">
        SELECT memberId, memberPass
        FROM hello_member
        WHERE memberId = #{memberId}
        AND memberPass = #{memberPass}
    </select>
cs
이 코드들을 통해 로그인을 하기 위해서는 id, pass가 두 개가 조건이 되어
일치하는 id, pass를 가져와서 컨트롤러에서 member로 담아준다는 것을 알 수 있다.



index.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<html>
<head>
</head>
<body>
<c:if test="${member == null}">
        <form action='<c:url value='/index'/>' method="post">
            <div>
                <label>아이디</label>
                <input id="memberId" name="memberId">    
            </div>
            <div>
                <label>비밀번호</label>
                <input id="memberPass" name="memberPass">
            </div>
            <input type="submit" value="로그인">    
            <input type="button" value="회원가입" onclick="location.href='register'">
        </form>
</c:if>
 
<c:if test="${member != null}">
<c:redirect url="/boardList"/>
</c:if>
 
</body>
</html>
cs

회원가입 버튼도 일단 구현해 놓는다.

맨 처음에 http://localhost:8585를 치고 들어갈때는
매핑된 컨트롤러의 내용대로 index에 들어갈 것이다.

그런데 이때의 member는 아무것도 없기 때문에 null인 상태이다.
왜냐하면 BoardMapper.xml의 쿼리에서도 보듯
memberId, memeberPass은 아무것도 입력되지 않았다.

그러므로 jsp의 ${member == null}로 들어가고 아이디, 비밀번호를 입력하는 창이 등장한다.
여기에서 존재하는 아이디, 비밀번호를 입력하고 로그인을 누를 경우
submit에 의해 post방식으로 다시 컨트롤러의 로그인창으로 이동한다.
index.jsp에서의 ${memberId}는 인수 memberVO에서 일치하는지 알아서 확인 후 setter, getter로 바인딩된다.
이번에는 member에 값이 있으니 else로 들어가서 session에 member라는 이름이 지정된다.
${member != null}에 성립하므로 boardList에 진입한다.



전체적인 완성작은 해당 소스를 참고
github.com/yulfsong/spring-boot-hello-project

yulfsong/spring-boot-hello-project

Contribute to yulfsong/spring-boot-hello-project development by creating an account on GitHub.

github.com