티스토리 뷰
Web/Spring
[Spring] 스프링부트 + JPA + thymeleaf + Spring Security로 회원가입 + 게시판(수정, 삭제, 등록, 조회, 댓글, 좋아요) + 로그인 구현하기 #5 로그인
poopooreum 2024. 8. 29. 20:15반응형
✏️ 로그인 로직
- 로그인 창에서 아이디 + 비밀번호를 입력
- 컨트롤러는 LoginDTO로 이 값을 받아옴
- 컨트롤러는 멤버서비스를 통해 아이디가 존재하는지 비밀번호가 일치하는지 검사
- 일치한다면 로그인을 함과 동시에 authentication을 설정해주고, 세션을 만들어준 뒤 메인 화면으로 이동
- 일치하지 않는다면 로그 에러를 찍어주고 다시 로그인 화면을 띄어준다
✏️ LoginDTO 클래스
@Getter
@Setter
public class LoginDTO {
private String id;
private String password;
private Collection<? extends GrantedAuthority> authorities;
}
로그인 시 입력 값을 받아올 클래스이다.
✏️ login.html 생성
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" th:href="@{/css/main.css}">
<title>로그인 창</title>
</head>
<body>
<h1>로그인을 해주세용</h1>
<img th:src="@{/image/html.png}">
<form method="post" action="/member/login" class="login-box">
<table id="login-table">
<tr>
<td>아이디 <input type="text" name="id" required/></td>
</tr>
<tr>
<td>비밀번호 <input type="text" name="password" required autocomplete="off"/></td>
</tr>
<tr>
<td>
<input type="submit" value="로그인">
</td>
</tr>
</table>
</form>
</body>
</html>
✏️ Api Controller 클래스
@PostMapping("/login")
public String login(LoginDTO loginDTO, HttpServletRequest httpServletRequest) {
boolean isMemberExist = memberService.checkMemberExist(loginDTO.getId());
if (!isMemberExist) {
log.error("아이디가 존재하지 않음");
return "redirect:/login";
}
boolean isLoginSamePassword = memberService.checkLoginSamePassword(loginDTO);
if (!isLoginSamePassword) {
log.error("비밀번호가 일치하지 않음");
return "redirect:/login";
}
log.info("login success");
httpServletRequest.getSession().invalidate();
HttpSession session = httpServletRequest.getSession();
session.setAttribute("userId", loginDTO.getId());
session.setMaxInactiveInterval(1800);
log.info("세션 생성");
return "redirect:/member/list";
}
로그인 창에 아이디와 비밀번호를 입력하면 Api 컨트롤러가 LoginDTO를 통해 입력 값을 받아오고 아이디가 db에 존재하는지, 비밀번호가 db랑 일치하는지 검사를 한 후 일치한다면 세션을 만들어서 인증을 해준다.
✏️ WebController 클래스
@GetMapping("/login")
public String login(HttpServletRequest httpServletRequest) {
HttpSession session = httpServletRequest.getSession();
Optional<Object> idOptional =Optional.ofNullable(session.getAttribute("userId"));
if(idOptional.isPresent()){
return "redirect:/member/list";
}
return "login";
}
✏️ MemberService 인터페이스
public interface MemberService {
boolean checkLoginSamePassword(LoginDTO loginDTO);
}
✏️ MemberServiceImpl 클래스
@Override
public boolean checkLoginSamePassword(LoginDTO loginDTO) {
UserDetails member = memberDetailService.loadUserByUsername(loginDTO.getId());
if (!(passwordEncoder.matches(loginDTO.getPassword(), member.getPassword()))) {
log.error("비밀번호가 일치하지 않습니다.");
return false;
}
return true;
}
MemberService에 새롭게 추가된 checkLoginSamePassword 메소드를 구현해준다. 입력한 비밀번호가 db에 있는지 검사해준다
✏️ MemberDetailService 클래스
@Service
@RequiredArgsConstructor
@Slf4j
public class MemberDetailService implements UserDetailsService {
private final MemberRepository memberRepository;
private static final Logger log = LoggerFactory.getLogger(MemberServiceImp.class);
@Override
public UserDetails loadUserByUsername(String id) throws UsernameNotFoundException {
Optional<Member> memberEntity = memberRepository.findById(id);
Member member = memberEntity.get();
return new MemberDetail(member);
}
}
그냥 로그인을 해도 되지만 이렇게 하는 이유는 MemberDetail(member) 를 함으로써 authentication을 설정해 줄 수 있도록 해준다. 우리가 인터넷상에서 메일을 보내고 블로그를 쓰는 등의 행위는 권한이 필요한데 이 권한을 추가해준다
✏️ UserDetailService 인터페이스
public interface UserDetailsService {
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
✏️ MemberDetail 클래스
package hello.hello_spring.service;
import hello.hello_spring.domain.member.Member;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@RequiredArgsConstructor
public class MemberDetail implements UserDetails {
private final Member member;
@Override
public boolean isAccountNonExpired() {
return UserDetails.super.isAccountNonExpired();
}
@Override
public boolean isAccountNonLocked() {
return UserDetails.super.isAccountNonLocked();
}
@Override
public boolean isCredentialsNonExpired() {
return UserDetails.super.isCredentialsNonExpired();
}
@Override
public boolean isEnabled() {
return UserDetails.super.isEnabled();
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority("ROLE_" + member.getRole().name()));
return authorities;
}
@Override
public String getPassword() {
return member.getPassword();
}
@Override
public String getUsername() {
return member.getId();
}
}
UserDetails 인터페이스를 상속받아 구현하는 클래스로 중요한 부분은 밑에서 3번째 함수이다. 로그인을 할 때 ContextHolder → Authentication → 의 authories에 권한을 추가해준다.
반응형
'Web > Spring' 카테고리의 다른 글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- C++
- 스택
- C++ Stack
- html
- 알고리즘
- 백준 풀이
- CSS
- 반복문
- 유니온 파인드
- BFS
- java
- 에라토스테네스의 체
- 알고리즘 공부
- 카운팅 정렬
- 유클리드 호제법
- DP
- js
- 백준
- 우선순위 큐
- 투 포인터
- 자바스크립트
- HTML5
- c++ string
- 세그먼트 트리
- 자바
- 이분 매칭
- 자료구조
- Do it!
- DFS
- 스프링 부트 crud 게시판 구현
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함