Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
package com.gltkorea.icebang.auth.dto;

public class LoginDto {}
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class LoginDto {
private String email; // 로그인용 이메일
private String password; // 비밀번호
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
package com.gltkorea.icebang.auth.dto;

public class SignUpDto {}
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SignUpDto {
private String email; // 회원가입용 이메일
private String password; // 비밀번호
private String nickname; // 닉네임
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,98 @@
package com.gltkorea.icebang.auth.provider;

/*
@RequiredArgsConstructor 추가
AuthService 의존성 주입
supports() 메서드 로직 구현
authenticate() 메서드 로직 구현
createAuthentication() 헬퍼 메서드 추가
supports(): SignUpDto나 LoginDto 존재 여부로 처리 가능성 판단
authenticate(): 회원가입 후 자동 로그인 또는 단순 로그인 처리
createAuthentication(): Spring Security의 Authentication 객체 생성
ROLE_USER 기본 권한 부여
*/

import java.util.Collections;
import java.util.List;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;

import com.gltkorea.icebang.auth.dto.DefaultRequestWrapper;
import com.gltkorea.icebang.auth.service.AuthService;
import com.gltkorea.icebang.dto.UserAuthDto;

import lombok.RequiredArgsConstructor;

@Component("default")
@RequiredArgsConstructor
public class DefaultProvider implements AuthProvider<DefaultRequestWrapper> {

private final AuthService authService;

/**
* 요청이 Default Provider로 처리 가능한지 검증
*
* @param request 요청 래퍼
* @return 처리 가능 여부
*/
@Override
public boolean supports(DefaultRequestWrapper request) {
return false;
// SignUpDto나 LoginDto 중 하나라도 있으면 처리 가능
if (request.getLoginDto() == null && request.getSignUpDto() == null) {
return false;
}
return true;
}

/**
* 인증 처리 (회원가입 + 로그인 또는 로그인만)
*
* @param request 요청 래퍼
* @return Authentication 객체
*/
@Override
public Authentication authenticate(DefaultRequestWrapper request) {
return null;
UserAuthDto user;

// 1. 회원가입 요청 처리
if (request.getSignUpDto() != null) {
// 회원가입 후 자동 로그인
user = authService.signUp(request.getSignUpDto());
}
// 2. 로그인 요청 처리
else if (request.getLoginDto() != null) {
user = authService.login(request.getLoginDto());
}
// 3. 잘못된 요청
else {
throw new IllegalArgumentException("SignUpDto 또는 LoginDto가 필요합니다");
}

// 4. Authentication 객체 생성
return createAuthentication(user);
}

/**
* UserAuthDto를 Authentication 객체로 변환
*
* @param user 사용자 정보
* @return Authentication 객체
*/
private Authentication createAuthentication(UserAuthDto user) {
// @TODO
// 이미 auth dto는 데이터 베이스에서 읽어온 상태
// 그럼 여기서 ROLE_USER가 아닌 실제 role을 넣어야함.
List<GrantedAuthority> authorities =
Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"));

return new UsernamePasswordAuthenticationToken(
user.getEmail(), // principal (사용자 식별자)
null, // credentials (비밀번호는 null로 - 이미 인증 완료)
authorities // authorities (권한)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

import com.gltkorea.icebang.auth.dto.LoginDto;
import com.gltkorea.icebang.auth.dto.SignUpDto;
import com.gltkorea.icebang.domain.user.model.Users;
import com.gltkorea.icebang.dto.UserAuthDto;

public interface AuthService {
Users signUp(SignUpDto signUpDto);
UserAuthDto signUp(SignUpDto signUpDto); // 변경!

Users login(LoginDto loginDto);
UserAuthDto login(LoginDto loginDto); // 변경!

Users loadUser(String identifier);
UserAuthDto loadUser(String identifier); // 변경!
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,118 @@
package com.gltkorea.icebang.auth.service;

/*
비밀번호 암호화: PasswordEncoder 사용
중복 검증: 회원가입 시 이메일 중복 체크
UUID 생성: 고유한 userId 자동 생성
예외 처리: 명확한 에러 메시지
상태 관리: ACTIVE 상태 체크
*/

import java.util.Optional;
import java.util.UUID;

import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.gltkorea.icebang.auth.dto.LoginDto;
import com.gltkorea.icebang.auth.dto.SignUpDto;
import com.gltkorea.icebang.domain.user.model.Users;
import com.gltkorea.icebang.domain.user.UserStatus;
import com.gltkorea.icebang.dto.UserAuthDto;
import com.gltkorea.icebang.mapper.UserMapper;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class AuthServiceImpl implements AuthService {

private final UserMapper userMapper;
private final PasswordEncoder passwordEncoder; // 비밀번호 암호화용

/**
* 회원가입 처리
*
* @param signUpDto 회원가입 정보
* @return 생성된 사용자 정보
*/
@Override
public Users signUp(SignUpDto signUpDto) {
return null;
@Transactional
public UserAuthDto signUp(SignUpDto signUpDto) {
// 1. 이메일 중복 체크
Optional<UserAuthDto> existingUser = userMapper.findByEmail(signUpDto.getEmail());
if (existingUser.isPresent()) {
throw new IllegalArgumentException("이미 존재하는 이메일입니다: " + signUpDto.getEmail());
}

// 2. 새 사용자 객체 생성
UserAuthDto newUser =
UserAuthDto.builder()
.userId(UUID.randomUUID().toString())
.email(signUpDto.getEmail())
.password(passwordEncoder.encode(signUpDto.getPassword()))
.provider("default")
.providerId(null)
.status(UserStatus.ONBOARDING.name())
.name(signUpDto.getEmail().split("@")[0]) // 이메일 앞부분을 임시 이름으로 @TODO:: fix to name
.build();

// 3. DB에 저장
int result = userMapper.insertUser(newUser);
if (result != 1) {
throw new RuntimeException("회원가입 실패");
}

// 4. 생성된 사용자 정보 반환
return newUser;
}

/**
* 로그인 처리
*
* @param loginDto 로그인 정보
* @return 인증된 사용자 정보
*/
@Override
public Users login(LoginDto loginDto) {
return null;
public UserAuthDto login(LoginDto loginDto) {
// 1. 이메일로 사용자 조회
Optional<UserAuthDto> userOpt = userMapper.findByEmail(loginDto.getEmail());
if (userOpt.isEmpty()) {
throw new IllegalArgumentException("존재하지 않는 이메일입니다: " + loginDto.getEmail());
}

UserAuthDto user = userOpt.get();

// 2. 비밀번호 검증
if (!passwordEncoder.matches(loginDto.getPassword(), user.getPassword())) {
throw new IllegalArgumentException("비밀번호가 일치하지 않습니다");
}

// 3. 계정 상태 체크
if (!"ACTIVE".equals(user.getStatus())) {
throw new IllegalStateException("비활성화된 계정입니다");
}

return user;
}

/**
* 사용자 조회 (이메일 또는 userId로)
*
* @param identifier 이메일 또는 userId
* @return 사용자 정보
*/
@Override
public Users loadUser(String identifier) {
return null;
public UserAuthDto loadUser(String identifier) {
// 1. 이메일 형식인지 확인 (@ 포함 여부)
if (identifier.contains("@")) {
return userMapper
.findByEmail(identifier)
.orElseThrow(() -> new IllegalArgumentException("사용자를 찾을 수 없습니다: " + identifier));
} else {
return userMapper
.findByUserId(identifier)
.orElseThrow(() -> new IllegalArgumentException("사용자를 찾을 수 없습니다: " + identifier));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ public SecureRandom secureRandom() {

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http.authorizeHttpRequests(
return http.csrf(csrf -> csrf.disable()) // 이 줄을 추가하세요
.authorizeHttpRequests(
auth ->
auth.requestMatchers(SecurityEndpoints.PUBLIC.getMatchers())
.permitAll()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,15 @@

public enum SecurityEndpoints {
PUBLIC(
"/", "/login", "/register", "/api/public/**", "/health", "/css/**", "/js/**", "/images/**"),
"/",
"/login",
"/register",
"/api/public/**",
"/health",
"/css/**",
"/js/**",
"/images/**",
"/v0/auth/**"), // 이 줄 추가!

ADMIN("/admin/**", "/api/admin/**", "/management/**", "/actuator/**"),

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
package com.gltkorea.icebang.domain.user.model;

import java.time.LocalDateTime;

import com.gltkorea.icebang.domain.user.UserStatus;

public class Users {
private Long id;
private String email;
private String password; // Default 로그인시에만 사용 (OAuth는 null)
private String provider; // "default", "kakao", "naver", "google"
private String providerId; // Default: null, OAuth: 소셜 ID
private UserStatus status;
private LocalDateTime createdAt;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@

import com.gltkorea.icebang.auth.service.AuthService;
import com.gltkorea.icebang.domain.user.model.UserAccountPrincipal;
import com.gltkorea.icebang.domain.user.model.Users;
import com.gltkorea.icebang.dto.UserAuthDto;

public class SecurityAuthenticateAdapter implements UserAuthService {
private AuthService authService;

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Users user = authService.loadUser(username);
UserAuthDto user = authService.loadUser(username);
return UserAccountPrincipal.builder().build(); // @TODO users -> userdetail로
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.gltkorea.icebang.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;

@Data
@Builder
@AllArgsConstructor
public class UserAuthDto {
private String userId; // 기존 필드 (String ID)
private String name; // 기존 필드
private String email; // 기존 필드
private String password; // 추가: Default 로그인용
private String provider; // 추가: "default", "kakao", "naver"
private String providerId; // 추가: OAuth ID
private String status; // 추가: 사용자 상태
// ... 필요한 다른 필드들
}

This file was deleted.

Loading
Loading