LoginAccountIdArgumentResolver
LoginAccountIdArgumentResolver
ArgumentResolver가 현재 로그인한 Account의 Id를 컨트롤러의 파라미터로 받을 수 있도록 한다.
이를 구현하기 위해 다음과 같은 어노테이션와 클래스를 생성한다.
● @LoginAccountId : LoginAccountIdArgumentResolver 사용시, 파라미터에 적용될 어노테이션
● LoginAccountIdArgumentResolver : 컨트롤러의 파라미터에 현재 로그인한 Account의 Id를 반환하는 클래스
1. LoginAccountIdArgumentResolver
■ LoginAccountId
어노테이션 기반으로 파라미터를 지정해주기 때문에 어노테이션을 생성한다.
[LoginAccountId]
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.PARAMETER) //[1]
@Retention(RetentionPolicy.RUNTIME) //[2]
public @interface LoginAccountId {
}
● [1] : 어노테이션의 적용 대상(ElemetType.PARAMTER = 파라미터).
● [2] : 어노테이션 적용 범위(RetentionPolicy.RUNTIME = 런타임).
■ LoginAccountIdArgumentResolver
[LoginAccountIdArgumentResolver]
import com.hipo.domain.UserAccount;
import org.springframework.core.MethodParameter;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
public class LoginAccountIdArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
boolean hasLoginAccountIdAnnotation = parameter.hasParameterAnnotation(LoginAccountId.class);
boolean hasLongType = Long.class.isAssignableFrom(parameter.getParameterType());
return hasLoginAccountIdAnnotation && hasLongType;
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal == "anonymousUser") {
return -1L;
}
UserAccount userAccount = (UserAccount) principal;
return userAccount.getAccount().getId();
}
}
ArgumentResolver를 설정하는 HandlerMethodArgumentResolver를 상속받는다.
파라미터로 사용할 값을 반환하고 해당 파라미터가 적용될 어노테이션과 타입을 지정한다.
□ supportsParameter
[supportsPrameter]
@Override
public boolean supportsParameter(MethodParameter parameter) {
boolean hasLoginAccountIdAnnotation = parameter.hasParameterAnnotation(LoginAccountId.class);
boolean hasLongType = Long.class.isAssignableFrom(parameter.getParameterType());
return hasLoginAccountIdAnnotation && hasLongType;
}
해당 클래스의 resolverArgument로 파라미터가 반환될 때 적용되는 어노테이션과 파라미터의 타입을 지정한다.
● [1] : 파라미터에 적용된 어노테이션이 @LoginAccountId 인지를 판단한다.
● [2] : 파라미터의 타입이 Long 타입인지를 판단한다.
● [3] : 반환값이 참일 때만 해당 클래스의 resolveArgument()가 적용된다.
위의 코드와 같이 해당 클래스에서 Overriede 된 supportsParameter()는 파라미터가 @LoginAccountId의 어노테이션이 적용되고 Long 타입일 경우에 지원됨을 의미한다.
즉, 컨트롤러에서 현재 로그인된 AccountId를 파라미터로 사용한다면 다음과 같은 형태가 된다.
[LoginAccountIdArgumentResolver 사용 예]
@Controller
public void test(@LoginAccountId Long accountId){
}
□ resolverArgument
[resolverArgument]
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
//[1]
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal == "anonymousUser") { //[2]
return -1L;
}
UserAccount userAccount = (UserAccount) principal;
return userAccount.getAccount().getId(); //[3]
}
해당 클래스의 supportsParameter가 true를 반환할 때 실행되는 메서드.
SecurityContextHolder에서 현재 인증된 AccountId를 찾아서 컨트롤러의 파라미터에 반환한다.
● [1] : 인증정보인 Principal(UserAccount)을 담고 있는 전역 변수인 Security ContextHolder에서 principal을 찾는다.
● [2] : principal = "anonymousUser"는 인증되지 않은 익명 사용자 상태를 뜻하기 때문에 -1을 반환.
● [3] : UserAccount 내의 Account의 Id를 반환
■ Webconfig
Spring Mvc의 설정을 다루는 WebMvcConfigurer를 상속받는다.
[webconfig]
import com.hipo.argumentresolver.LoginAccountIdArgumentResolver;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new LoginAccountIdArgumentResolver());
}
}
커스텀한 LoginAccountIdArgumentResolver를 ArgumentResolver에 추가한다.