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)
세션을 쓰는 방법은 두가지가 있다
- 위처럼 매개변수에 담아서 쓰는 방법 HttpSession session
- @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> 세션이 있으면 글쓰기, 회원정보, 로그아웃 네브바 나타나기
☆ 주의할점 "$ 가 붙어져 있어야 잘 실행이 된다.
- 원래 로그인 화면
- 로그인 완료 후 네브바 변경 된 화면
'Spring boot | 블로그 만들기' 카테고리의 다른 글
스프링 시큐리티 로그인 | SecurityConfig 설정 (0) | 2022.11.09 |
---|---|
스프링 시큐리티 로그인 | 사용자 정보 가져오기 principal (0) | 2022.11.09 |
회원가입 | Ajax를 사용하는 이유 , Service, Dto (0) | 2022.11.06 |
메인화면, 회원가입 화면, 로그인 화면 (0) | 2022.11.06 |
회원삭제 테스트 | Exception 처리 (0) | 2022.11.05 |