Custom Annotation (예:@LoginCheck) 가 붙은 method 의 로그인 세션 체크 하는 루틴이 궁금합니다.

1,591 views
Skip to first unread message

Ryan Min

unread,
Apr 10, 2013, 6:11:37 AM4/10/13
to ks...@googlegroups.com
상황 : insert*, update*, delete* 로 시작하는 method 에 사용자 LoginCheck 를 하고 싶은데

단, 모든 insert, update, delete 가 아니고 Annotation 이 (가령 @LoginCheck 라는 Custom Annotaion 을 만들어서) 붙은 method 만 LoginCheck.check 를 실행하도록 하고 싶습니다.

LoginCheck.check 에서는 session 을 가져올 수 있어야 하고요...

세션의 사용자VO 존재 여부를 체크해서 오류 페이지로 분기하거나, 원래 method 를 실행하도록 할 예정입니다.

어떻게 구성을 잡아야 할지 감이 안오네요 초보를 위해 최대한 구체적으로 부탁 드립니다.

감사합니다. ^^


예)

@LoginCheck
public Map execute(Map parameterMap) throws Exception {
   ... some business logic ...
}

위에 @LoginCheck 가 붙어 있으므로 LoginCheck.check() 를 먼저 실행한다.
세션에 유저VO가 있으면 execute 실행
유저VO가 없으면 오류 페이지 분기 (throw Exception 하면 분기 됨)



YongHyuk Lee

unread,
Apr 10, 2013, 6:14:40 AM4/10/13
to ks...@googlegroups.com
세션을 컨트롤단 외에 다른곳에서 사용하게되면...
여러모로 좋지 않은 결과를 낳게 될거라 생각됩니다.

로그인 확인이 필요한 url리스트를 정리해서..
인터셉터로 처리함은 어떠실까요..?

나의 iPhone에서 보냄

2013. 4. 10. 19:11 Ryan Min <ryan...@gmail.com> 작성:

--
Google 그룹스 'Korea Spring User Group' 그룹에 가입했으므로 본 메일이 전송되었습니다.
이 그룹에서 탈퇴하고 더 이상 이메일을 받지 않으려면 ksug+uns...@googlegroups.com에 이메일을 보내세요.
이 그룹에 게시하려면 ks...@googlegroups.com(으)로 이메일을 보내세요.
http://groups.google.com/group/ksug?hl=ko-KR에서 그룹을 방문하세요.
더 많은 옵션을 보려면 https://groups.google.com/groups/opt_out을(를) 방문하세요.
 
 

Ryan Min

unread,
Apr 10, 2013, 8:37:42 PM4/10/13
to ks...@googlegroups.com
이 회사의 상황이, 메소드에 어노테이션을 붙여서 spring context xml 에서 어노테이션을 검출해서 해당하는 것을 LoginCheck.check 에서 LoginVO 세션을 가져와서 체크하는 방식이 최선입니다.

    @LoginCheck
    public ModelAndView mnu0101(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ...
        return new ModelAndView("[tiles]web/mnu0101").addObject("resultMap", resultMap).addObject("parameterMap", parameterMap);
     }

spring context xml 에서 위와 같은 것을 할 수 있는 구문을 만들어야 하는데 어떻게 하면 될까요 ?

부탁 드립니다.


2013년 4월 10일 수요일 오후 7시 11분 37초 UTC+9, Ryan Min 님의 말:

Ki-Seok Kim

unread,
Apr 10, 2013, 9:35:47 PM4/10/13
to ks...@googlegroups.com
AOP 를 쓰는건 어떨까요?

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LoginCheck {
}


@Aspect
@Component
public class LoginCheckProfile {

@Around(value="@annotation(logincheck)")
public Object target(ProceedingJoinPoint pjp, Logincheck logincheck) throws Throwable{
LoginVO lv = session.getAttribute("loginVO");
if(lv == null){
throw new Exception("error");
}
return pjp.proceed(); 
}

}

이런식으로 하면 될거같거든요..

xml 에는 <aop:aspectj-autoproxy /> 설정해주시고 maven 에 spring-aop 추가 시켜주시면 될거같아요..(간단하게 될거같진 않지만.)


저도 사용자 권한을  채크해서 403 error page로 이동하는것을 만들어본적이 있거든요 AOP 가 최고의 해결책은 아닐지라도.. 상당히 편합니다.

참고하세요..



2013년 4월 11일 오전 9:37, Ryan Min <ryan...@gmail.com>님의 말:

JeongHyeon Lee

unread,
Apr 11, 2013, 2:06:52 AM4/11/13
to ks...@googlegroups.com
저도 커스텀 애노테이션으로 처리 할려다가 체크하는 타입이 명확하지 않아 (실력 부족...)
서비스 단에서 체크 하는 방법으로.. 처리 했었습니다.
(왼지 모르게 코드가 지저분 하다는 생각은 많이 듭니다. T_T)

================= 서비스 ==============
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.Errors;

import com.test.common.Common;
import com.test.domain.AccountLoginVO;
import com.test.domain.AccountVO;
import com.test.domain.ResponseMyPageVO;

/**
 * 폼값 검사
 */
@Service
public class FormValidator {
   
    @Autowired
    private AccountsService accountsService;
   
    /**
     * 아이디, 닉네임, 이메일 DB 검사
     * @param accountVO
     * @param errors
     * @return
     */
    public boolean AccountRegisterValid(final AccountVO accountVO, final Errors errors) {
        String id = accountVO.getId();
        String nickname = accountVO.getNickname();
        String password = accountVO.getPassword();
        String password2 = accountVO.getPassword2();
        String email = accountVO.getEmail();
        if ((id.length() >= 5) && (id.length() <= 12) && !id.isEmpty()) {
            if (accountsService.WhoisId(id) != null) {
                errors.rejectValue("id", "error.accountVO", Common.getMessageRed("해당 아이디는 이미 등록되어 있습니다!"));
            }
        }
        if ((nickname.length() >= 2) && (nickname.length() <= 14) && !nickname.isEmpty()) {
            if (accountsService.WhoisNickname(nickname) != null) {
                errors.rejectValue("nickname", "error.accountVO", Common.getMessageRed("해당 닉네임은 이미 등록되어 있습니다!"));
            }
        }
        if (!password2.isEmpty() && !password.equals(password2)) {
            errors.rejectValue("password2", "error.accountVO", Common.getMessageRed("첫번째 입력한 비밀번호와 일치하지 않습니다!"));
        }
        if ((email.length() <= 321) && !email.isEmpty()) {
            if (!Common.isValidMail(email)) {
                errors.rejectValue("email", "error.accountVO", Common.getMessageRed("올바른 이메일이 아닙니다!"));
            } else {
                if (accountsService.WhoisEMail(email) != null) {
                    errors.rejectValue("email", "error.accountVO", Common.getMessageRed("해당 이메일은 이미 등록되어 있습니다!"));
                }
            }
        }
        return (errors.hasErrors());
    }
   
    /**
     * 폼값 에러가 없을 때 (아이디, 닉네임, 이메일) 정상 안내 메시지 반환
     * @param errors
     * @return
     */
    public boolean AccountRegisterValidSuccess(final Errors errors) {
        if (!errors.hasFieldErrors("id")) {
            errors.rejectValue("id", "error.accountVO", Common.getMessageGreen("등록 가능한 아이디입니다."));
        }
        if (!errors.hasFieldErrors("nickname")) {
            errors.rejectValue("nickname", "error.accountVO", Common.getMessageGreen("등록 가능한 닉네임입니다."));
        }
        if (!errors.hasFieldErrors("password2")) {
            errors.rejectValue("password2", "error.accountVO", Common.getMessageGreen("첫번째 입력한 비밀번호와 일치합니다."));
        }
        if (!errors.hasFieldErrors("email")) {
            errors.rejectValue("email", "error.accountVO", Common.getMessageGreen("등록 가능한 이메일입니다."));
        }
        return (errors.hasErrors());
    }
   
    /**
     * 로그인 검사
     * @param accountLoginVO
     * @param errors
     * @return
     */
    public boolean AccountLoginValid(final AccountLoginVO accountLoginVO, final Errors errors) {
        String id = accountLoginVO.getId();
        String password = accountLoginVO.getPassword();
        if (!id.isEmpty() && !password.isEmpty()) {
            AccountVO seq = accountsService.Login(id, password, "", false);
            if (seq == null) {
                errors.rejectValue("id", "error.accountLoginVO", "아이디 또는 비밀번호 일치하는 데이터가 없습니다!");
            } else {
                ResponseMyPageVO mypage = accountsService.MyPage(seq.getSeq());
                if (mypage != null) {
                    if (mypage.getIs_email_valid().equals("N")) {
                        errors.rejectValue("id", "error.accountLoginVO", "해당 계정은 이메일 인증이 안된 계정입니다!");
                    } else {
                        if (mypage.getAccessLevel() == -1) {
                            errors.rejectValue("id", "error.accountLoginVO", "해당 계정은 차단된 계정입니다!");
                        }
                    }
                }
            }
        }
        return (errors.hasErrors());
    }
   
    /**
     * 회원 정보 변경 검사
     * @param responseMyPageVO
     * @param errors
     * @return
     */
    public boolean AccountUpdateValid(final ResponseMyPageVO responseMyPageVO, final Errors errors) {
        String nickname = responseMyPageVO.getNickname();
        ResponseMyPageVO mypage = accountsService.MyPage(Long.valueOf(Common.getSessionName("seq")));
        if (mypage != null) {
            if (mypage.getNickname().equals(responseMyPageVO.getNickname())) {
                errors.rejectValue("nickname", "error.responseMyPageVO", "닉네임을 변경하지 않았습니다!");
            } else {
                if ((nickname.length() >= 2) && (nickname.length() <= 14) && !nickname.isEmpty()) {
                    if (accountsService.WhoisNickname(nickname) != null) {
                        errors.rejectValue("nickname", "error.responseMyPageVO", Common.getMessageRed("해당 닉네임은 이미 등록되어 있습니다!"));
                    }
                }
            }
        }
        return (errors.hasErrors());
    }
   
}
================= 서비스 ==============

============ 콘트롤러 ==================
@Controller
@RequestMapping(value = "/Account")
@WebServlet(name = "Account", asyncSupported = true) // Recommand (Spring v3.2.x, Servlet v3.1)
class AccountsController {
   
    private static final Logger log = Logger.getLogger(AccountsController.class);
   
    @Autowired
    private AccountsService accountsService;
   
    @Autowired
    private FormValidator formValidator;

    /**
     * 회원 가입 뷰
     * @param accountVO
     * @return
     */
    @RequestMapping(value = "/Register", method = RequestMethod.GET)
    public ModelAndView doGetAccountRegister(AccountVO accountVO) {
        if (Common.getSessionName("seq") == null) {
            log.debug("GET : /WEB-INF/jsp/Account/Register.jsp");
            return new ModelAndView("/Account/Register");
        } else {
            return new ModelAndView(new RedirectView("/"));
        }
    }

    /**
     * 회원 가입 처리
     * @param accountVO
     * @param errors
     * @param model
     * @return
     */
    @RequestMapping(value = "/Register", method = RequestMethod.POST)
    public ModelAndView doPostAccountRegister(@Valid @ModelAttribute AccountVO accountVO, Errors errors, Model model) {
        if (Common.getSessionName("seq") == null) {
            formValidator.AccountRegisterValid(accountVO, errors);
            if (errors.hasErrors()) {
                formValidator.AccountRegisterValidSuccess(errors);
                log.debug("POST : /WEB-INF/jsp/Account/Register.jsp");
                return new ModelAndView("/Account/Register");
            } else {
                model.addAttribute("result", accountsService.NewAccountRegister(accountVO));
                log.debug("POST : /WEB-INF/jsp/Account/RegisterSuccess.jsp");
                return new ModelAndView("/Account/RegisterSuccess");
            }
        } else {
            return new ModelAndView(new RedirectView("/"));
        }
    }

}
============ 콘트롤러 ==================

2013년 4월 11일 오전 10:35, Ki-Seok Kim <hello...@gmail.com>님의 말:

Ryan Min

unread,
Apr 12, 2013, 12:51:40 AM4/12/13
to ks...@googlegroups.com
두분 답변 참고하겠습니다.

Ki-Seok Kim 님꼐 질문 드릴게 있는데요

LoginVO lv = session.getAttribute("loginVO");

부분에서 session 은 어떻게 받아 올 수 있는건지요 ? 



2013년 4월 10일 수요일 오후 7시 11분 37초 UTC+9, Ryan Min 님의 말:
상황 : insert*, update*, delete* 로 시작하는 method 에 사용자 LoginCheck 를 하고 싶은데

Ki-Seok Kim

unread,
Apr 14, 2013, 8:23:55 PM4/14/13
to ks...@googlegroups.com
안녕하세요. 

ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
HttpSession session = attr.getRequest().getSession();

이런식으로 session 을 얻을수 있구요.. 추가적으로 advice 될때 파라미터를 읽어올수 있습니다.

예를 들어

@LoginCheck
public ModelMap getUser(HttpServletRequest request, HttpServletResponse response)
{ ... }

이 메소드를 advice 한다고 할때 

Object[] params = pjp.getArgs();

이렇게 파라미터를 가져올수 있습니다. 




2013년 4월 12일 오후 1:51, Ryan Min <ryan...@gmail.com>님의 말:

Munsu Kim

unread,
Apr 14, 2013, 8:34:55 PM4/14/13
to ks...@googlegroups.com
저도 같은 고민을 한 적이 오래전에 있었는데
Ki-Seok Kim 말씀따라 RequestContextHolder 에서 session 값을 얻어온 적이 있네염.
쓰레드로컬을 다루는 부분이니 value 를 get 하는 데에만 쓰시고 다른 목적으론 안쓰시는게 좋겠어요.
저때 전 AOP 를 쓸까하다가.... 너무 특정 service 단에서만 필요해서 쓰지 않았었는데 좋은 말씀이시네요. :)




2013년 4월 15일 오전 9:23, Ki-Seok Kim <hello...@gmail.com>님의 말:
Reply all
Reply to author
Forward
0 new messages