ArgumentResolver
in Spring on Spring Boot
๐ ArgumentResolver
๋ก๊ทธ์ธ๋ ์ฌ์ฉ์๋ฅผ ์ ๋ ธํ ์ด์ ์ผ๋ก ํ์ธํ๋ ๋ฐฉ๋ฒ์ ์์๊น?
@Login์ด๋ผ๋ argument๋ฅผ ์ฒ๋ฆฌํด์ฃผ๋ ArgumentResolver๋ฅผ ๋ง๋ค๊ณ ์ด๋ฅผ ํ์ฉํ๋ฉด ์ถฉ๋ถํ ๊ฐ๋ฅํ๋ค.
@Login
@Login ์ ๋ ธํ ์ด์ ์ ์๋์ผ๋ก ์ธ์ ์ ์๋ ๋ก๊ทธ์ธ ํ์์ ์ฐพ์์ฃผ๊ณ ,
๋ง์ฝ ์ธ์ ์ ์๋ค๋ฉด null ์ ๋ฐํํ๋๋ก ํ๋ค.
1. @Login ์ ๋ ธํ ์ด์ ์์ฑ
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Login {}
- @Target(ElementType.PARAMETER) : ํ๋ผ๋ฏธํฐ์๋ง ์ฌ์ฉ
- @Retention(RetentionPolicy.RUNTIME) : ๋ฐํ์๊น์ง ์ ๋ ธํ ์ด์ ์ ๋ณด๊ฐ ์ ์ง
2. @Login์ ์ฒ๋ฆฌํด์ฃผ๋ ArgumentResolver ์์ฑ
// import
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
// main class
public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
// @Login ์ ๋
ธํ
์ด์
์ด ํ๋ผ๋ฏธํฐ์ ์๋์ง?
boolean hasLoginAnnotation = parameter.hasParameterAnnotation(Login.class);
/**
* parameter.getParameterType() : @Login ์ ๋
ธํ
์ด์
๋ค์ ๋ถ์ ํด๋์ค
* isAssignableFrom : ํ ๋นํ ์ ์๋์ง.
*/
boolean hasModelType = Member.class.isAssignableFrom(parameter.getParameterType());
return hasLoginAnnotation && hasModelType;
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
HttpSession session = request.getSession();
if (session == null) {
return null;
}
return session.getAttribute("LOGIN_MEMBER");
}
}
supportsParameter()
@Login ์ด๋ ธํ ์ด์ ์ด ์์ผ๋ฉด์, Model ํ์ ์ด๋ฉด ArgumentResolver๊ฐ ์คํ๋๋ค.
resolveArgument()
์ปจํธ๋กค๋ฌ ํธ์ถ ์ง์ ์ ํธ์ถ๋์ด์ ํ์ํ ํ๋ผ๋ฏธํฐ ์ ๋ณด๋ฅผ ์์ฑํด์ค๋ค.
์์ ์ฝ๋์์๋ ๋ก๊ทธ์ธ ํ์์ ๋ณด์ธ member ๊ฐ์ฒด๋ฅผ ์ฐพ์์ ๋ฐํํด์ค๋ค.
session=Member(id=1, loginId=test, name=ํ ์คํฐ, password=1234)
์ดํ ์คํ๋งMVC๋ ์ปจํธ๋กค๋ฌ์ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด์ ์ฌ๊ธฐ์์ ๋ฐํ๋ member ๊ฐ์ฒด๋ฅผ
ํ๋ผ๋ฏธํฐ์ ์ ๋ฌํด์ค๋ค.
model={member=Member(id=1, loginId=test, name=ํ ์คํฐ, password=1234)}
3. ์์ฑํ ArgumentResolver ๋ฑ๋ก
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new LoginMemberArgumentResolver());
}
}
๊ณ ์ฐฐ
JWT Token ์ธ์ฆ์ ๊ฒฝ์ฐ ์ด๋ฐ ๋ฐฉ๋ฒ์ผ๋ก ํ๋ฉด ๋๋๊ฑด๊ฐ??
โ token ์ ํจ ์ฌ๋ถ ํ์ธ
โ token์ claims ์ ๋ณด์์ ๊ณ ์ ๊ฐ(ex. Email)์ผ๋ก DB ์กฐํ
โ ๋ฐํ ๋ raw๊ฐ์ ์ปจํ๋กค๋ฌ ๊ฐ์ฒด์ ๋ฃ์ด์ค.
ArgumentResolver
@RequiredArgsConstructor
public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver {
private final UserMapper userMapper;
@Override
public boolean supportsParameter(MethodParameter parameter) {
boolean hasLoginAnnotation = parameter.hasParameterAnnotation(Login.class);
boolean hasModelType = User.class.isAssignableFrom(parameter.getParameterType());
return hasLoginAnnotation && hasModelType;
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
// Token ์ ๋ณด ํ์ธ
HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
String header = request.getHeader("Authorization");
String token = JwtUtils.getTokenFromHeader(header);
if (JwtUtils.isValideToken(token)) {
// Email ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ
String email = JwtUtils.getUserEmailFromToken(token);
// ๊ฐ์ ธ์จ email์ ๋ณด๋ก ํด๋น User๊ฐ์ฒด ๋ฐํ
User checkUser = findUserByEmail(String email);
return checkUser;
} else if (!JwtUtils.isValideToken(token)) {
/** Access Token์ด ์ ํจํ์ง ์์ ๊ฒฝ์ฐ
* ๋ง๋ฃ๋ ํ ํฐ์์ Email ๊ฐ์ ธ์จ๋ค.
* DB์์ Email๋ก ํด๋น ๊ฐ์ฒด์ Refresh Token์ ๊ฐ์ ธ์จ๋ค.
* ๋ค์ ์๋ก์ด AccessToken์ ๋ง๋ค์ด ์ค๋ค.
*/
String email = JwtUtils.getUserEmailFromToken(token);
User checkUser = findUserByEmail(String email);
String reToken = checkUser.getRetoken();
if (JwtUtils.isValideReToken(reToken)) {
// Refresh Token์ ๊ธฐ๋ฐ์ผ๋ก ์๋ก์ด Access Token์ ์์ฑ
User user = new User();
user.setAuthCode(JwtUtils.getClaimsCodeFromToken(reToken));
user.setEmail(JwtUtils.getUserEmailFromToken(reToken));
user.setUserSeq(Long.parseLong(JwtUtils.getClaimsSeqFromToken(reToken)));
response.setHeader(AuthConstants.AUTH_HEADER, AuthConstants.TOKEN_TYPE + " " + JwtUtils.generateJwtToken(user));
response.setHeader(AuthConstants.RE_AUTH_HEADER, AuthConstants.TOKEN_TYPE + " " + reToken);
HttpSession session = request.getSession();
session.setAttribute(user.getEmail()+"_token", reToken);
return checkUser;
} else {
response.addHeader("Content-Type", "application/json");
response.getWriter().print("Fail");
return false;
}
}
}
}