Spring Framework-9

유호준·2021년 3월 26일
0

Spring Framework

목록 보기
10/21

🔐이번엔 로그인을 만들어보자!!


login.jsp 수정

login.jspform을 다음과 같이 수정하고 스크립트를 추가합니다. 이 스크립트는 login버튼이 눌리면 userVO에 정보를 담아 POST요청을 /에 보내는 스크립트입니다. 요청이 성공하고 반환받은 datasuccesstrue라면 /board로 이동하고 아니라면 email 혹은 비밀번호를 확인해주세요라는 메시지를 띄웁니다.

<form class="user">
	<div class="form-group">
		<input type="email" class="form-control form-control-user" name="email" aria-describedby="emailHelp" placeholder="Enter Email Address...">  
        </div>
	<div class="form-group">
		<input type="password" class="form-control form-control-user" name="password" placeholder="Password">
	</div>
	<div class="form-group">
		<div class="custom-control custom-checkbox small">
			<input type="checkbox" class="custom-control-input" id="customCheck">
			<label class="custom-control-label" for="customCheck">Remember Me</label>
		</div>
	</div>
	<a id="login" class="btn btn-primary btn-user btn-block">
		Login
	</a>
	<hr>
	<a href="index.html" class="btn btn-google btn-user btn-block">
		<i class="fab fa-google fa-fw"></i> Login with Google
	</a>
	<a href="index.html" class="btn btn-facebook btn-user btn-block">
		<i class="fab fa-facebook-f fa-fw"></i> Login with Facebook
	</a>
</form>
<script>
        $("#login").click(function (){
            var userVO = new Object()
            userVO.email = $("[name='email']").val()
            userVO.password = $("[name='password']").val()

            $.ajax({
                type:'POST',
                url:'/',
                data:JSON.stringify(userVO),
                contentType:'application/json; charset=UTF-8',
                success:function (data){
                    if(data.success)
                        location.href='/board'
                    else
                        alert('email 혹은 비밀번호를 확인해주세요!')
                }
            })
        })

    </script>

UserMapper 인터페이스와 xml 수정

email로 유저의 정보를 가져올 수 있도록 수정합니다.

<mapper namespace="ac.kr.smu.mapper.UserMapper">
    <insert id="save">
        INSERT INTO user(name,email,password)
        VALUES (#{name},#{email},#{password})
    </insert>

    <select id="checkEmailDuplication" resultType="int">
        SELECT COUNT(*) FROM user where email=#{email}
    </select>

    <select id="findByEmail" resultType="UserVO">
        SELECT * FROM user where email=#{email}
    </select>
</mapper>
public interface UserMapper {
    public void save(UserVO userVO);
    public int checkEmailDuplication(String email);
    public UserVO findByEmail(String email);
}

UserService 수정

비밀번호를 확인해서 맞다면 true틀리면 false를 반환하도록 수정합니다.

public interface UserService {
    public void save(UserVO userVO);
    public boolean checkEmailDuplication(String email);
    public boolean checkPassword(String email, String password);
}
@RequiredArgsConstructor
@Service
public class UserServiceImpl implements UserService {
    private final UserMapper userMapper;

    @Override
    public void save(UserVO userVO) {
        userMapper.save(userVO);
    }

    @Override
    public boolean checkEmailDuplication(String email) {
        return userMapper.checkEmailDuplication(email)==0;
    }

    @Override
    public boolean checkPassword(String email, String password) {
 	return password.equals(userMapper.findByEmail(email).getPassword());

    }
}

LoginController 수정

로그인 처리를 할 수 있도록 수정합니다. 비밀번호를 확인해서 맞다면 Mapsuccesstrue를 담아서 반환하고 아니라면 false를 담아서 반환합니다. 그리고 비밀번호가 맞다면 세션의 만료시간을 30분으로 설정하고 userSession이라는 이름으로 email을 저장합니다. 그리고 반환할 때 상태코드 200번을 반환합니다.

@RestController
@RequiredArgsConstructor
@RequestMapping("/")
public class LoginController {
    private final UserService userService;

    @GetMapping
    public ModelAndView getLogin(){
        return new ModelAndView("login");
    }
    @PostMapping
    public ResponseEntity<?> postLogin(@RequestBody UserVO userVO, HttpSession session){
        Map<String,Boolean> body = new HashMap<>();
        boolean result = userService.checkPassword(userVO.getEmail(), userVO.getPassword());

        body.put("success",result);
        if(result) {
            session.setMaxInactiveInterval(60*30);//초 단위로 세션의 만료시간 설정
            session.setAttribute("userSession",userVO.getEmail());
        }

        return ResponseEntity.ok(body);

    }
}

세션이란??

브라우저가 종료되기 전까지 클라이언트의 요청을 유지하는 기술

ResponseEntity는 객체와 HttpStatus 등등을 함께 반환할 수 있는 클래스입니다.


Interceptor 추가

우리는 이제 로그인을 만들었으므로, 로그인이 되지 않은 사람들은 로그인, 회원가입 페이지 이외에는 접근을 하지 못하도록 해야합니다. 따라서 우리는 Interceptor로 이 처리를 할 것입니다.

LoginInterceptor 추가

LoginInterceptor 클래스를 추가합니다. 이 클래스는 request에서 세션을 받아와서, userSession이 없다면 로그인 페이지로 이동시키고 있다면 그대로 진행시키는 클래스입니다.

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session  = request.getSession();
        boolean chk=session.getAttribute("userSession") != null;

        if(!chk)
            response.sendRedirect("/");

        return chk;
    }
}

Interceptor란?

말 그대로 요청을 가로채는 클래스입니다. Controller로 요청이 가기 전에 혹은 요청이 끝나고 나서 조작을 가할 수 있는 AOP의 일종입니다.

ServletConfig 수정

다음 메소드를 Override해줍니다. interceptor를 추가하는 메소드입니다. 경로는 /board/post로 들어오는 모든 요청을 interceptor가 처리하도록 합니다.

@Override
public void addInterceptors(InterceptorRegistry registry) {
        WebMvcConfigurer.super.addInterceptors(registry);
        registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/board").addPathPatterns("/post/**");
    }

테스트

로그인을 제대로 할 때



로그인 안하고 접근 시도

로그를 남겨서 접근을 했는지 확인해보겠습니다. LoginInterceptor를 다음과같이 수정합니다.

@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session  = request.getSession();
        log.info(request.getRequestURI());
        log.info("userSession is null? : "+(session.getAttribute("userSession")==null));
        boolean chk=session.getAttribute("userSession") != null;

        if(!chk)
            response.sendRedirect("/");

        return chk;
    }
}


다음과 같이 로그인을 하지 않은 상태입니다.

로그인을 하지 않은 상태에서 접근을 하게 되면

interceptor가 요청을 가로채서 세션이 null인지 확인합니다. 이번 요청은 null이므로 다시 로그인 페이지로 이동시킵니다.

0개의 댓글