AJAX를 이용한 로그인 방법

 

네브바에서 로그인 누를때

  • <li class="nav-item"><a class="nav-link" href="/loginForm">로그인</a></li>

 

 

[loginForm]

 

<form action="/api/user/login"> form태그 방식 안쓰고 button 태그를 form밖으로 꺼낸다

<button id="btn-login" class="btn btn-primary">로그인 완료</button>

 

<script src="/js/user.js"></script> 붙여주기

경로설정 

 

 

 

[user.js]

 

로그인 완료 버튼을 눌렀을때 login 함수 실행

$("#btn-login").on("click", () => {  //function(){}, ()=>{} this를 바인딩하기 위해서
     this.login();
});

//로그인 함수 실행
login: function() {
    let data = {
        username: $("#username").val(),
        password: $("#password").val(),
    }

    $.ajax({
        type:"POST",
        url:"/api/user/login",
        data:JSON.stringify(data), // http body데이터 (마임데이터가 필요)
        contentType:"application/json; charset=utf-8", // body데이터가 어떤 타입인지(MIME)
        dataType: "json" 
    }).done(function(resp){
        alert("로그인이 완료되었습니다.");
        location.href="/";   // 로그인되면 메인페이지 이동
    }).fail(function(error){
        alert(JSON.stringify(error));
    });
}
  • 로그인할때는 username, password 값만 필요하여 data에 넣는다.
  • 로그인은 DB안의 나의 정보와 일치하는지 확인이 필요하기때문에 select 를 하고
  • 주소에 아이디와 비번이 보여지면 안되니까 POST 방식

 

 

이제  url:"/api/user/login", 주소 컨트롤러 만들기

 

 

 

[UserApiController]

@PostMapping("/api/user/login")
public ResponseDto<Integer> login(@RequestBody User user, HttpSession session){
    System.out.println("UserApiController : login 호출됨");
    User principal = userService.로그인(user); //principal(접근주체)

    if(principal != null) {
        session.setAttribute("principal", principal);
    }
    return new ResponseDto<Integer>(HttpStatus.OK.value(), 1);  // 1이면 로그인 정상적 요청됨
}

응답은 ResponseDto<Integer> 로 한다.

@RequestBody User user  user 객체를 받아

 User principal = userService.로그인(user); : userService.로그인(user) 을 통해서 로그인 정보를 얻어 principal 에 담는다.

 

 

UserService에서 로그인() 함수 만들기

 

 

[UserService]

@Transactional
public User 로그인(User user) {
    userRepository.save()
}

 

userRepository.save 를 쓰는것 보다

UserRepository 에서 로그인을 위한 함수를 만들자 

username, password만 저장하는 로그인을 위한 함수는 리파지토리에 없기 때문에 직접 함수를 만든다!

= findByUsernameAndPassword

 

 

UserRepository에서 로그인을 위한 함수를 만드는데는 2가지 방법이 있다.

 

 

1번째 방법.  JPA Naming 쿼리 ( 함수이름으로 자동 쿼리문 실행)
public interface UserRepository extends JpaRepository<User, Integer>{
   User findByUsernameAndPassword(String username, String password);   //User 객체로 리턴
}

findBy 뒤부터 함수 이름에 따라 자동 쿼리문이 만들어고 대문자가 물음표가 된다 UsernameAndPassword

SELECT * FROM user WHERE username = ? AND password = ?

 

 String username 은 username = ? 에 들어가고  String password 는 password =? 에 들어간다.

 

 

 

 

2번째방법. nativeQuery (@Query 어노테이션 value값에 쿼리문을 직접 넣기 )
public interface UserRepository extends JpaRepository<User, Integer>{
   @Query(value = "SELECT * FROM user WHERE username = ? AND password = ?", nativeQuery = true)
   User login(String username, String password);
}

 

 

 

다시 [UserService] 로 돌아가서

간단하게 로그인 함수(findByUsernameAndPassword)를 이용해 User을 리턴한다.

@Transactional(readOnly = true) 
public User 로그인(User user) {
     return userRepository.findByUsernameAndPassword(user.getUsername(), user.getPassword());
}

select만 할거면 트랜잭션이 필요없으나

@Transactional(readOnly = true) 를 붙여서 select 할때 트랜잭션 시작 ~ 서비스 종료시 트랜잭션 종료할때 정합성 유지해준다.

 

정합성이란 select를 여러번해도 같은 데이터가 찾아지도록 하는것

 

 

 

 

[UserApiController]

@PostMapping("/api/user/login")
public ResponseDto<Integer> login(@RequestBody User user, HttpSession session){
    System.out.println("UserApiController : login 호출됨");
    User principal = userService.로그인(user); 

    if(principal != null) {
        session.setAttribute("principal", principal);   // session.setAttribute(String key, object value)
    }
    return new ResponseDto<Integer>(HttpStatus.OK.value(), 1);  // 1이면 로그인 정상적 요청됨
}
  • User principal = userService.로그인(user) : 로그인 정보를 principal 에 담아 
  • session.setAttribute("principal", principal); : 로그인 정보를 value 에 담고 "principal" 을 키 값으로 한다.

 

 

 

 

세션 객체는 스프링 컨테이너가 빈으로 등록해서 가지고 있으면 우리가 필요할때 가져다 쓸 수 있다. (DI)

 

세션을 쓰는 방법은 두가지가 있다

  1. 위처럼 매개변수에 담아서 쓰는 방법  HttpSession session
  2. @Autowired private HttpSession session;

 

 

이제 로그인이 완료되면 메인화면에 보여지는 로그인, 회원가입 버튼만 보여지던 네브바를 수정한다. (jstl 사용함)

 


jstl 사용법

1. 라이브러리 다운받아 네브바 [header.jsp] 맨 위에 복붙하기  (jstl tutorial 검색후 태그복사)

<%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>

 

2. pom.xml 에서 JSTL 라이브러리가 다운돼있는지 확인

<!-- JSTL -->
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>jstl</artifactId>
  <version>1.2</version>
</dependency>

 


 

[header.jsp] 

 

세션이 있을때, 없을때 네브바 다르게 설정

<c:choose> 태그는 if else 와 비슷하다  <c:when> 이 아니면 <c:otherwise> 를 해라

<c:choose>
    <c:when test="${empty sessionScope.principal}">
        <ul class="navbar-nav">
            <li class="nav-item"><a class="nav-link" href="/auth/loginForm">로그인</a></li>
            <li class="nav-item"><a class="nav-link" href="/auth/joinForm">회원가입</a></li>
        </ul>
    </c:when>

    <c:otherwise>
        <ul class="navbar-nav">
            <li class="nav-item"><a class="nav-link" href="/board/saveForm">글쓰기</a></li>
            <li class="nav-item"><a class="nav-link" href="/user/updateForm">회원정보</a></li>
            <li class="nav-item"><a class="nav-link" href="/logout">로그아웃</a></li>
        </ul>
    </c:otherwise>
</c:choose>
  • <c:when test="${empty sessionScope.principal}"> 세션이 비어있다면 로그인, 회원가입 네브바 나타나고
  • <c:otherwise> 세션이 있으면 글쓰기, 회원정보, 로그아웃 네브바 나타나기

 

☆ 주의할점 "$ 가 붙어져 있어야 잘 실행이 된다.

 

 

 

- 원래 로그인 화면 

로그인 화면

 

- 로그인 완료 후 네브바 변경 된 화면

로그인 후 네브바 변경 확인

 

반응형
LIST

+ Recent posts