-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#1 회원가입 기능 구현 시큐리티설정 작업 #8
The head ref may contain hidden characters: "#1_\uB85C\uADF8\uC778,\uD68C\uC6D0\uAC00\uC785"
Changes from all commits
a5fcdd3
2fd005c
35e2707
0f32fd7
26ae524
e67b593
674aac6
a6adfc5
8326c73
fdea642
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package com.main.board; | ||
|
||
import com.main.board.member.exception.EmailDuplicatedException; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ProblemDetail; | ||
import org.springframework.validation.FieldError; | ||
import org.springframework.web.bind.MethodArgumentNotValidException; | ||
import org.springframework.web.bind.annotation.ControllerAdvice; | ||
import org.springframework.web.bind.annotation.ExceptionHandler; | ||
|
||
@ControllerAdvice | ||
public class GlobalExceptionHandler { | ||
|
||
//서버 500 에러 | ||
@ExceptionHandler(Exception.class) | ||
public ProblemDetail handleGeneralException() { | ||
return ProblemDetail.forStatusAndDetail(HttpStatus.INTERNAL_SERVER_ERROR, "서버에러입니다 다시시도해주세요."); | ||
} | ||
|
||
// 이메일 중복 에러 | ||
@ExceptionHandler(EmailDuplicatedException.class) | ||
public ProblemDetail handleEmailDuplicatedException() { | ||
return ProblemDetail.forStatusAndDetail(HttpStatus.CONFLICT, "이미 사용중인 이메일입니다."); | ||
} | ||
|
||
//nullpoint 에러 (파라미터 누락) | ||
@ExceptionHandler(NullPointerException.class) | ||
public ProblemDetail handleNullPointerException() { | ||
return ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, "파라미터가 제대로 전달되지 않았습니다."); | ||
} | ||
|
||
// IllegalArgumentException 처리 | ||
@ExceptionHandler(IllegalArgumentException.class) | ||
public ProblemDetail handleIllegalArgumentException(IllegalArgumentException e) { | ||
if(e.getMessage() != null) { | ||
return ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, e.getMessage()); | ||
} | ||
return ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, "파라미터가 제대로 전달되지 않았습니다."); | ||
} | ||
|
||
@ExceptionHandler(MethodArgumentNotValidException.class) | ||
public ProblemDetail handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { | ||
// 첫 번째 오류 메시지 추출 | ||
FieldError fieldError = e.getBindingResult().getFieldErrors().get(0); // 첫 번째 오류만 처리 | ||
String field = fieldError.getField(); | ||
String defaultMessage = fieldError.getDefaultMessage(); | ||
// 이메일 오류 | ||
if ("email".equals(field)) { | ||
return ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, defaultMessage); | ||
} | ||
// 비밀번호 오류 | ||
if ("rawPassword".equals(field)) { | ||
return ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, defaultMessage); | ||
} | ||
return ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, "유효성 검증 실패"); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package com.main.board.config; | ||
|
||
import jakarta.servlet.ServletException; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import org.springframework.beans.factory.annotation.Qualifier; | ||
import org.springframework.security.core.AuthenticationException; | ||
import org.springframework.security.web.AuthenticationEntryPoint; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.web.servlet.HandlerExceptionResolver; | ||
|
||
import java.io.IOException; | ||
|
||
@Component | ||
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint { | ||
|
||
// 인증 실패 시 호출되는 메소드 | ||
@Override | ||
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { | ||
|
||
// 401 Unauthorized 응답 상태 코드 설정 | ||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); | ||
|
||
// 클라이언트에게 반환할 메시지 설정 | ||
response.getWriter().write("로그인 실패: 인증이 필요합니다."); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package com.main.board.config; | ||
|
||
import com.main.board.member.Member; | ||
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; | ||
|
||
public class CustomUserDetails implements UserDetails { | ||
|
||
private final Member member; | ||
|
||
public CustomUserDetails(Member member) { | ||
this.member = member; | ||
} | ||
|
||
@Override | ||
public Collection<? extends GrantedAuthority> getAuthorities() { | ||
ArrayList<GrantedAuthority> auth = new ArrayList<GrantedAuthority>(); //ArrayList객체생성 | ||
auth.add(new SimpleGrantedAuthority("ROLE_USER"));//ROLE_USER권한을 부여 | ||
return auth; //권한리스트반환 | ||
} | ||
|
||
@Override | ||
public String getPassword() { | ||
return member.getEncryptPwd(); | ||
} | ||
|
||
|
||
@Override | ||
public String getUsername() { | ||
return member.getEmail(); | ||
} | ||
|
||
@Override | ||
public boolean isAccountNonExpired() { | ||
return true; | ||
} | ||
|
||
@Override | ||
public boolean isAccountNonLocked() { | ||
return true; | ||
} | ||
|
||
@Override | ||
public boolean isCredentialsNonExpired() { | ||
return true; | ||
} | ||
|
||
@Override | ||
public boolean isEnabled() { | ||
return true; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package com.main.board.config; | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.main.board.login.DTO.LoginRequest; | ||
import jakarta.servlet.FilterChain; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import org.springframework.security.authentication.AuthenticationManager; | ||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.security.core.AuthenticationException; | ||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | ||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository; | ||
import org.springframework.stereotype.Component; | ||
|
||
import java.io.IOException; | ||
|
||
@Component | ||
public class CustomUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter { | ||
|
||
private static final String LOGIN_URL = "/auth/login"; | ||
|
||
private final ObjectMapper objectMapper = new ObjectMapper(); | ||
|
||
public CustomUsernamePasswordAuthenticationFilter(AuthenticationManager authenticationManager) { | ||
super(authenticationManager); | ||
super.setFilterProcessesUrl(LOGIN_URL); | ||
setSecurityContextRepository(new HttpSessionSecurityContextRepository()); | ||
} | ||
|
||
@Override | ||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) { | ||
try { | ||
LoginRequest loginRequest = new LoginRequest(); | ||
loginRequest = objectMapper.readValue(request.getInputStream(), LoginRequest.class); | ||
String email = loginRequest.getEmail(); | ||
String password = loginRequest.getRawPassword(); | ||
|
||
//@valid 어노테이션 사용불가 validation을 직접 구현하기엔좀 단점같음 | ||
//직접구현 | ||
if (email == null || email.isEmpty()) { | ||
throw new IllegalArgumentException("이메일을 입력해주세요."); | ||
} | ||
if (password == null || password.isEmpty()) { | ||
throw new IllegalArgumentException("비밀번호를 입력해주세요."); | ||
} | ||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(email, password); | ||
return this.getAuthenticationManager().authenticate(token); | ||
} catch (IOException e) { | ||
throw new RuntimeException("Failed to parse authentication request body"); | ||
} | ||
} | ||
|
||
@Override | ||
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws IOException { | ||
response.setStatus(HttpServletResponse.SC_OK); | ||
response.getWriter().write("로그인 성공!"); // 로그인 성공 | ||
} | ||
|
||
@Override | ||
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, org.springframework.security.core.AuthenticationException failed) throws java.io.IOException { | ||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); | ||
response.getWriter().write("로그인 실패!" + failed.getMessage()); // 로그인 실패 | ||
} | ||
|
||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
불변선언 좋습니다 👍