Security Chain antMatchers ๊ด๋ จ Exception Handling
Table of contents
Security Chain ์ค์ ์์,
ํน์ Role๋ง Url ์์ฒญ์ ์ ๊ทผํ ์ ์๋๋ก ์ค์ ํ ๋ (.hasRole()
๋์ด์๋) ํน์ .authenticated()
๋์ด์๋ url์ AUTHORIZATION
๋ด์ฉ์ด ์์ ์๋ ๊ฒฝ์ฐ
Chain์์ ๋ฐ์ํ๋ ์์ธ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด์๋ AccessDeniedHandler
์ AuthenticationEntryPoint
๋ฅผ ์์๋ฐ์ ๊ตฌํํด์ผํ๋ค.
์์๋ก ์๋์ ๊ฐ์ด ๊ตฌํํ ์ ์๋ค.
Error Response ๊ตฌ์ฑ
@RestControllerAdvice
@Slf4j
public class ExceptionManager {
public static void setErrorResponse(HttpServletResponse response, ErrorCode errorCode) throws IOException {
// ์๋ฌ ์๋ต์ฝ๋ ์ค์
response.setStatus(errorCode.getHttpStatus().value());
// ์๋ต body type JSON ํ์
์ผ๋ก ์ค์
response.setContentType("application/json;charset=UTF-8");
Response<ErrorDto> error = Response.error(new ErrorDto(errorCode.toString(), errorCode.getMessage()));
//์์ธ ๋ฐ์ ์ Error ๋ด์ฉ์ JSONํ ํ ํ ์๋ต body์ ๋ด์์ ๋ณด๋ธ๋ค.
Gson gson = new Gson();
String responseBody = gson.toJson(error);
response.getWriter().write(responseBody);
}
}
@AllArgsConstructor
@Getter
public enum ErrorCode {
TOKEN_NOT_FOUND(HttpStatus.UNAUTHORIZED, "ํ ํฐ์ด ์กด์ฌํ์ง ์์ต๋๋ค."),
FORBIDDEN_REQUEST(HttpStatus.FORBIDDEN, "ADMIN ํ์๋ง ์ ๊ทผํ ์ ์์ต๋๋ค.");
private HttpStatus httpStatus;
private String message;
}
๋จผ์ ์์ ๊ฐ์ ๋ฉ์๋๋ฅผ ๊ตฌํํ๋ค. ์ฌ๋ฌ๊ณณ์์ ์ฐ์ผ ์ ์๊ธฐ ๋๋ฌธ์, static ๋ฉ์๋๋ก ๋ง๋ค์๋ค.
HttpServletResponse
์ status
์ contentType
๋ฅผ ์ค์ ํ๊ณ
.getWriter.write()
๋ฉ์๋๋ก ์๋ตํ body๋ฅผ JSONํ ํด์ ์๋ตํ ๋ด์ฉ์ ์ค์ ํ๋ฉด ๋๋ค.
AccessDeniedHandler ๊ตฌํํ๊ธฐ
import likelion.sns.Exception.ErrorCode;
import likelion.sns.Exception.ExceptionManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
@Slf4j
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException {
log.info("{}", accessDeniedException.getMessage());
ErrorCode errorCode = ErrorCode.FORBIDDEN_REQUEST;
ExceptionManager.setErrorResponse(response, errorCode);
}
}
handle
์ ์ค๋ฒ๋ผ์ด๋ฉํ ํ, ์๋ฌ ๋ฐ์์ ์๋ตํ ์ฝ๋๋ฅผ ์ค์ ํ๋ฉด ๋๋ค.
๊ทธ๋ฌ๋ฉด .hasRole
๊ด๋ จ ์์ธ๋ฅผ ํธ๋ค๋งํ ์ ์๋ค.
AuthenticationEntryPoint ๊ตฌํํ๊ธฐ
import likelion.sns.Exception.ErrorCode;
import likelion.sns.Exception.ExceptionManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
@Slf4j
public class CustomAuthenticationEntryPointHandler implements AuthenticationEntryPoint {
/**
* ํ ํฐ ์์ด Security Chain ์์ autenticated๋ url ์ ๊ทผ ์, ์๋ฌ ํธ๋ค๋ง
*/
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
final String authorization = request.getHeader(HttpHeaders.AUTHORIZATION);
if (authorization == null) {
log.error("ํ ํฐ์ด ์กด์ฌํ์ง ์์ต๋๋ค.");
ErrorCode errorCode = ErrorCode.TOKEN_NOT_FOUND;
ExceptionManager.setErrorResponse(response, errorCode);
}
}
}
commence
๋ฅผ ์ค๋ฒ๋ผ์ด๋ฉํ๋ฉด ๋๊ณ , authorization์ด null ์ธ ์กฐ๊ฑด๋ฌธ์ ์ฌ์ฉํ์ฌ, ์์ธ ์ฒ๋ฆฌ๋ฅผ ํ๋ฉด ๋๋ค.
ํ์ธ
ํ ํฐ ์์ด ์์ฒญํ ๊ฒฝ์ฐ
๊ถํ ์๋ ์ฌ์ฉ์๊ฐ ์์ฒญํ ๊ฒฝ์ฐ