프로젝트/PongGame

LoginAccountIdArgumentResolver

히포파타마스 2022. 4. 28. 15:01

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에 추가한다.