SpringBoot/보안과 인증
로그인 & 회원가입 구현
DEVLIB
2025. 4. 15. 10:24
728x90
로그인 & 회원가입 구현 개요
기술 스택
- Spring Boot
- Spring Security
- H2 / MySQL
- JPA
- BCryptPasswordEncoder (비밀번호 암호화)
1. 의존성 설정 (build.gradle)
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
runtimeOnly 'com.h2database:h2' // 또는 mysql
}
2. 회원 Entity
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
private String username;
private String password;
private String role; // ex: ROLE_USER
}
3. 회원가입 DTO
public class MemberDto {
private String username;
private String password;
}
4. MemberRepository
public interface MemberRepository extends JpaRepository<Member, Long> {
Optional<Member> findByUsername(String username);
}
5. 비밀번호 암호화 (Config)
@Configuration
public class SecurityConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
// 기타 Security 설정 생략...
}
6. 사용자 인증용 UserDetailsService 구현
@Service
public class CustomUserDetailsService implements UserDetailsService {
private final MemberRepository memberRepository;
public CustomUserDetailsService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Member member = memberRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("사용자 없음"));
return User.builder()
.username(member.getUsername())
.password(member.getPassword())
.roles("USER")
.build();
}
}
7. 회원가입 서비스
@Service
public class MemberService {
private final MemberRepository memberRepository;
private final PasswordEncoder passwordEncoder;
public MemberService(MemberRepository memberRepository, PasswordEncoder passwordEncoder) {
this.memberRepository = memberRepository;
this.passwordEncoder = passwordEncoder;
}
public void register(MemberDto dto) {
if (memberRepository.findByUsername(dto.getUsername()).isPresent()) {
throw new IllegalArgumentException("이미 존재하는 사용자입니다.");
}
Member member = new Member();
member.setUsername(dto.getUsername());
member.setPassword(passwordEncoder.encode(dto.getPassword()));
member.setRole("ROLE_USER");
memberRepository.save(member);
}
}
8. 컨트롤러
@Controller
@RequiredArgsConstructor
public class AuthController {
private final MemberService memberService;
@GetMapping("/login")
public String login() {
return "login";
}
@GetMapping("/signup")
public String signupForm(Model model) {
model.addAttribute("memberDto", new MemberDto());
return "signup";
}
@PostMapping("/signup")
public String signup(@ModelAttribute MemberDto memberDto) {
memberService.register(memberDto);
return "redirect:/login";
}
}
9. Thymeleaf 템플릿 예시
login.html
<form method="post" action="/login">
<input type="text" name="username" placeholder="아이디" />
<input type="password" name="password" placeholder="비밀번호" />
<button type="submit">로그인</button>
</form>
signup.html
<form method="post" th:action="@{/signup}" th:object="${memberDto}">
<input type="text" th:field="*{username}" placeholder="아이디" />
<input type="password" th:field="*{password}" placeholder="비밀번호" />
<button type="submit">회원가입</button>
</form>
마무리 요약
기능 | 구현 요소 |
회원가입 | DTO → Service → 암호화 → Repository 저장 |
로그인 | 스프링 시큐리티 기본 폼 → DB 사용자 인증 |
비밀번호 암호화 | BCryptPasswordEncoder |
사용자 인증 | UserDetailsService 구현 |
보안 적용 | 모든 경로에 인증 적용, /login, /signup만 허용 |
LIST