AOP를 이용한 권한관리

J_Eddy·2022년 11월 6일
0
post-thumbnail

프로젝트를 진행하면서 페이지별로 접근권한을 설정해줘야 할 때가 있다. 이전에 작성한 코드는 session에 저장된 role을 꺼내어 페이지에 접근 할 때 마다 권한을 체크 하였다.

case1)

🙍‍♀️: '관리' 페이지에 '관리자' 권한을 가진 사용자만 접근 가능하게 해주세요
🙍‍♂️:(관리 컨트롤러에서 권한체크 한다.)넵, 완료했습니다.

🙍‍♀️: '계정관리', '게시글관리' .. 등 약 5만개의 페이지에 권한을 부여해주세요.
🙍‍♂️: ...

case2)
예를 들어 아래 샘플 코드처럼 AuthController 클래스에 있는 컨트롤러는 사용자가 인증이 되었는지를 체크하는 로직이 필요하다.
각 컨트롤러에서 인증체크로직1,2를 중복되어 작성되었다.

@Controller
public class AuthController {

    @GetMapping("...")
    public String auth1() {
    	//인증 체크 로직1.. 
        //인증 체크 로직2.. 
        
        return ".../page1";
    }
    
    @GetMapping("...")
    public String auth2(Model model) {
    	//인증 체크 로직1.. 
        //인증 체크 로직2.. 
        
        return ".../page2";
    }

이럴 때 사용하는게 AOP이다. 공통된 기능을 하나로 묶어 여러 로직에 적용하는 것이다.

AOP란?

Aspect oriented Programming의 약자로 관점 지향 프로그래밍이다. (OOP는 객체 지향 프로그래밍) 관점 지향? 바로 이해가 안 갈 수 있지만 쉽게 말하면 어떤 관점을 중점적으로 볼것이냐 라는것이다. 위 예로 이야기 하자면 '권한 체크' 라는 관점이 생길 수 있고 이 권한을 체크 하기 위해서는 세션이라는 관점이 새로 생길 수 있다.

어노테이션 생성

권한 관리를 하기 위해서 AuthAnnotation을 만들어 보았다.

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthCheck {
    Role role() default Role.ROLE_MEMBER;
}
  • Target : 이 어노테이션이 부착될 수 있는 타입을 의미한다.
  • Retention : 어느 시점까지 메모리를 가져 갈것인지 설정한다.

인터셉터 생성

인증체크하는 로직을 작성한다. 일부 코드는 생략 했습니다.
세션에 저장된 값이 없으면 로그인이 안된것으로 간주하고 예외발생, 세션에 저장된 권한과 AuchCheck에 설정된 권한이 다를 경우 예외발생.

...

public void checkAuth(HttpSession session, Object handler) throws Exception {
	HandlerMethod method = (HandlerMethod)handler;
    AuthCheck authCheck = method.getAnnotationMethod(AuthCheck.Class);
    
    ...
    MemeberSession member = session.getAttribute("member");
    //로그인 권한이 없으면 thorw
    if( member == null ) {
    	throw Exception(...UNAUTHENTICATED);
    }
    if(!member.role.equals(authCheck.role()) {
    	throw Exception(...NO_PERMISSION);
    }
    ...
}

결론

결론 적으로 처음에 작성되었던 컨트롤러 클래스의 코드는 아래와 같이 변경될 수 있다.

//변경전
@Controller
public class AuthController {

    @GetMapping("...")
    public String auth1() {
    	//인증 체크 로직1.. 
        //인증 체크 로직2.. 
        
        return ".../page1";
    }
    
    @GetMapping("...")
    public String auth2(Model model) {
    	//인증 체크 로직1.. 
        //인증 체크 로직2.. 
        
        return ".../page2";
    }
---------------------------------------------
//변경 후
@Controller
@AuthCheck
public class AuthController {

    @GetMapping("...")
    public String auth1() {
        ...
        return ".../page1";
    }
    
    @GetMapping("...")
    public String auth2(Model model) {
        ...
        return ".../page2";
    }
profile
논리적으로 사고하고 해결하는 것을 좋아하는 개발자입니다.

0개의 댓글