LUMI_dev
사용자 관리하기 - #2. 로그인 구현 JWT 본문
스파르타 코딩 클럽 | 자바 심화 과정/Spring Master (숙련 주차)
사용자 관리하기 - #2. 로그인 구현 JWT
luminous_dev 2025. 2. 5. 11:06로그인을 하고 완료되면 JWT 토큰을 만들어서 클라이언트에 반환하도록 하겠음
반환 방법 중 쿠키를 직접 생성해서 JWT 토큰을 담고, Response 객체에 담는 식으로 구현 예정
.orElseThrow()
비어있으면 예외 던짐
UserController.java
@PostMapping ("/user/signup")
public String signup(SignupRequestDto requestDto) { //객체로 받고 있음
userService.signup(requestDto);
return "redirect:/api/user/login-page";
}
//로그인
@PostMapping("/user/login")
public String login(LoginRequestDto requestDto, HttpServletResponse res) {
try {
userService.login(requestDto,res);
//res = 끝나면 JwtTokenCookie에 넣고, cookie 담으로 Response 객체 넣어주기
} catch (Exception e) {
return "redirect:/api/user/login-page?error";
}
return "redirect:/";
}
UserService.java
package com.sparta.springauth.service;
import com.sparta.springauth.dto.LoginRequestDto;
import com.sparta.springauth.dto.SignupRequestDto;
import com.sparta.springauth.entity.User;
import com.sparta.springauth.entity.UserRoleEnum;
import com.sparta.springauth.jwt.JwtUtil;
import com.sparta.springauth.repository.UserRepository;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.Optional;
@Service
public class UserService {
private final UserRepository userRepository; //interface
private final PasswordEncoder passwordEncoder;
//로그인에서 Jwt 쓰기 위해 호출
private final JwtUtil jwtUtil;
public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder, JwtUtil jwtUtil) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
this.jwtUtil = jwtUtil;
}
.
.
.
public void login(LoginRequestDto requestDto, HttpServletResponse res) {
String username = requestDto.getUsername();
String password = requestDto.getPassword();
//사용자 확인
User user = userRepository.findByUsername(username).orElseThrow(
() -> new IllegalArgumentException("등록된 사용자가 없습니다.")
); //중복과 달리 사용자 확인해서 없으면 error 처리를 해줘야 함 - optional의 기능 중 하나인 orElseThrow
//() -> 람다식 : 인자가 없는 메서드 정의 /Supplier 인터페이스의 get()메서드 구현- 인자를 받지 않고 값을 반환하는 메서드
//비밀번호 확인
if(!passwordEncoder.matches(password, user.getPassword())) {
//평문(입력 받은 데이터), 암호화된 비밀번호
//서로 일치하지 않으면
throw new IllegalArgumentException("비밀번호가 일치하지 않습니다.");
}
//JWT 생성 및 쿠키에 저장 후 Response 객체에 추가
//(JWT 사용하려면 Jwtutil을 호출해야함)
String token = jwtUtil.createToken(user.getUsername(), user.getRole());
//JWT를 쿠키에 넣고 Response객체에 넣기
jwtUtil.addJwtToCookie(token,res); //res에 담는 과정까지
}
}
전체 코드
UserController.java
package com.sparta.springauth.controller;
import com.sparta.springauth.dto.LoginRequestDto;
import com.sparta.springauth.dto.SignupRequestDto;
import com.sparta.springauth.service.UserService;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/api")
public class UserController {
//주입
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
//로그인 페이지
@GetMapping("/user/login-page")
public String loginPage() {
return "login";
}
//회원 가입 페이지
@GetMapping("/user/signup")
public String signupPage() {
return "signup";
}
@PostMapping ("/user/signup")
public String signup(SignupRequestDto requestDto) { //객체로 받고 있음
userService.signup(requestDto);
return "redirect:/api/user/login-page";
}
//로그인
@PostMapping("/user/login")
public String login(LoginRequestDto requestDto, HttpServletResponse res) {
try {
userService.login(requestDto,res);
} catch (Exception e) {
return "redirect:/api/user/login-page?error";
}
return "redirect:/";
}
}
UserService.java
package com.sparta.springauth.service;
import com.sparta.springauth.dto.LoginRequestDto;
import com.sparta.springauth.dto.SignupRequestDto;
import com.sparta.springauth.entity.User;
import com.sparta.springauth.entity.UserRoleEnum;
import com.sparta.springauth.jwt.JwtUtil;
import com.sparta.springauth.repository.UserRepository;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.Optional;
@Service
public class UserService {
private final UserRepository userRepository; //interface
private final PasswordEncoder passwordEncoder;
//로그인에서 Jwt 쓰기 위해 호출
private final JwtUtil jwtUtil;
public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder, JwtUtil jwtUtil) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
this.jwtUtil = jwtUtil;
}
// ADMIN_TOKEN
private final String ADMIN_TOKEN = "AAABnvxRVklrnYxKZ0aHgTBcXukeZygoC";
//회원 가입
public void signup(SignupRequestDto requestDto) {
String username = requestDto.getUsername();
//암호화된 패스워드
String password = passwordEncoder.encode(requestDto.getPassword());
// 회원 중복 확인
Optional<User> checkUsername = userRepository.findByUsername(username);
//Optional은 값이 존재하거나 존재하지 않을 수 있음을 명시적으로 나타내는 컨테이너
//Optional<User>는 User 객체를 감싸고 있으며, User가 존재할 수도 있고, 존재하지 않을 수도 있음
if (checkUsername.isPresent()) {
throw new IllegalArgumentException("중복된 사용자가 존재합니다.");
}
// email 중복확인
String email = requestDto.getEmail();
Optional<User> checkEmail = userRepository.findByEmail(email);
if (checkEmail.isPresent()) { //.isPresent() : 값이 존재하는지 아닌지
throw new IllegalArgumentException("중복된 Email 입니다.");
}
// 사용자 ROLE 확인
UserRoleEnum role = UserRoleEnum.USER;//사용자 권한을 일단 설정해둠
if (requestDto.isAdmin()) { //.isAdmin하면 Dto의 boolean admin값 가져옴
if (!ADMIN_TOKEN.equals(requestDto.getAdminToken())) {
throw new IllegalArgumentException("관리자 암호가 틀려 등록이 불가능합니다.");
}
role = UserRoleEnum.ADMIN; //어드민 권한으로 덮어씀
}
// 사용자 등록
//테이블의 한 행에 해당하는 데이터를 만들어야 함
User user = new User(username, password, email, role);
userRepository.save(user); //repository에 의해 저장
}
public void login(LoginRequestDto requestDto, HttpServletResponse res) {
String username = requestDto.getUsername();
String password = requestDto.getPassword();
//사용자 확인
User user = userRepository.findByUsername(username).orElseThrow(
() -> new IllegalArgumentException("등록된 사용자가 없습니다.")
); //중복과 달리 사용자 확인해서 없으면 error 처리를 해줘야 함 - optional의 기능 중 하나인 orElseThrow
//() -> 람다식 : 인자가 없는 메서드 정의 /Supplier 인터페이스의 get()메서드 구현- 인자를 받지 않고 값을 반환하는 메서드
//비밀번호 확인
if(!passwordEncoder.matches(password, user.getPassword())) {
//평문(입력 받은 데이터), 암호화된 비밀번호
//서로 일치하지 않으면
throw new IllegalArgumentException("비밀번호가 일치하지 않습니다.");
}
//JWT 생성 및 쿠키에 저장 후 Response 객체에 추가
//(JWT 사용하려면 Jwtutil을 호출해야함)
String token = jwtUtil.createToken(user.getUsername(), user.getRole());
//JWT를 쿠키에 넣고 Response객체에 넣기
jwtUtil.addJwtToCookie(token,res); //res에 담는 과정까지
}
}
'스파르타 코딩 클럽 | 자바 심화 과정 > Spring Master (숙련 주차)' 카테고리의 다른 글
Filter 필터 (1) | 2025.02.06 |
---|---|
JWT 다루기 (1) | 2025.02.06 |
사용자 관리하기 - #1. 회원가입 구현 (구현 편) / 양방향, 단방향 암호 알고리즘 (0) | 2025.02.05 |
사용자 관리하기 - #1. 회원가입 구현 (설정 편) (0) | 2025.02.05 |
인증과 인가란? (1) | 2025.02.04 |