티스토리 뷰
반응형
Spring 4 에서 새로 소개된 @Order 어노테이션은 같은 타입의 Bean이 Collection에 Autowired 될 때 순서를 지정하기 위해 사용합니다. 아무래도 인증이나 보안과 관련되어 가장 우선적으로 필터링할 클래스에 주로 사용합니다.
먼저 사용하기 위한 샘플 소스를 작성해보도록 하겠습니다.
Work.java
public interface Work {
public void work();
}
Programmer.java
@Service
@Order(value=1)
public class Programmer implements Work {
public void work() {
System.out.println("Programmer Working...");
}
}
Designer.java
@Service
@Order(value=2)
public class Designer implements Work {
public void work() {
System.out.println("Designer Working...");
}
}
위와 같이 work 메소드를 먼저 정의하였을 경우 출력은 Order가 오름차순으로 Autowired 됩니다. 그래서 결과 또한 아래와 같이 출력될 것입니다.
## 결과
Programmer Working... (Order=1)
Designer Working... (Order=2)
이번에는 각 클래스의 Order 내 값만 변경해서 출력해보겠습니다.
Programmer.java
@Service
@Order(value=2)
public class Programmer implements Work {
public void work() {
System.out.println("Programmer Working...");
}
}
Designer.java
@Service
@Order(value=1)
public class Designer implements Work {
public void work() {
System.out.println("Designer Working...");
}
}
## 결과
Designer Working... (Order=1)
Programmer Working... (Order=2)
이런 Order를 적용해 인증과 관련된 클래스, 즉 Filter 클래스를 적용해보면 어떨까요?
JsonToUrlEncodedAuthenticationFilter.java
package com.example.auth.core.filter;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.apache.catalina.connector.RequestFacade;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;
import java.util.Objects;
import static org.springframework.util.StringUtils.hasText;
@Component
@Order(value = Integer.MIN_VALUE)
@RequiredArgsConstructor
public class JsonToUrlEncodedAuthenticationFilter implements Filter {
private final ObjectMapper objectMapper;
@Override
public void init(final FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
try {
RequestFacade castRequest = (RequestFacade) request;
} catch (ClassCastException e) {
chain.doFilter(request, response);
return;
}
if (Objects.equals(request.getContentType(), "application/json") && Objects.equals(((RequestFacade) request).getServletPath(), "/oauth/token")) {
InputStream is = request.getInputStream();
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
byte[] json = buffer.toByteArray();
HashMap<String, String> result = objectMapper.readValue(json, HashMap.class);
HashMap<String, String[]> r = new HashMap<>();
for (String key : result.keySet()) {
String[] val = new String[1];
val[0] = result.get(key);
r.put(key, val);
}
String[] val = new String[1];
val[0] = ((RequestFacade) request).getMethod();
r.put("_method", val);
String authorization = ((RequestFacade) request).getHeader("Authorization");
if (hasText(authorization) && authorization.toLowerCase().startsWith("basic")) {
final String[] values = decodeHttpBasicAuthorization(authorization);
String[] client_id = new String[1];
client_id[0] = values[0];
String[] client_secret = new String[1];
client_secret[0] = values[1];
r.put("client_id", client_id);
r.put("client_secret", client_secret);
}
HttpServletRequest s = new MyServletRequestWrapper(((HttpServletRequest) request), r);
chain.doFilter(s, response);
} else {
chain.doFilter(request, response);
}
}
private String[] decodeHttpBasicAuthorization(final String authorization) {
String base64Credentials = authorization.substring("Basic".length()).trim();
byte[] credDecoded = Base64.getDecoder().decode(base64Credentials);
String credentials = new String(credDecoded, StandardCharsets.UTF_8);
final String[] values = credentials.split(":", 2);
return values;
}
@Override
public void destroy() {
}
}
위에서는 @Order(value = Integer.MIN_VALUE) 로 적용하여 가장 우선적으로 필터링을 진행하기 위한 어노테이션을 적용했습니다.
여기서 잘 보아야할 메소드는 doFilter 입니다. 가장 먼저 try-catch 문을 이용하여 ServletRequest 가 RequestFacade로 강제형변환이 되는지 체크 후 하위 소스에서 RequestFacade에서 제공하는 getMethod() 와 getHeader("Authorization") 를 활용하여 인증 절차를 거치게 됩니다.
반응형
'Server' 카테고리의 다른 글
Ubuntu 20.04 Redis 설치하고 구성하기 (0) | 2021.08.18 |
---|---|
Ubuntu 20.04 Java 설치 (0) | 2021.08.18 |
MVC Redirect 에서 OOM 방지하기 (0) | 2021.07.01 |
[Java] 날짜와 관련된 클래스들 (0) | 2021.06.30 |
Nginx를 활용한 에러 페이지 출력하기 (0) | 2021.06.26 |
Nginx Error Log 설정과 보는 방법 (0) | 2021.06.26 |
댓글
공지사항