대머리개발자

url path마다 권한 설정 본문

개발이야기/개념

url path마다 권한 설정

대머리개발자 2024. 7. 9. 10:10
728x90

스프링 시큐리티를 이용하면 쉽게(?) 적용 가능하다.

http
.csrf().disable()
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN") // Only ADMIN users can access /admin/**
.antMatchers("/user/**").hasAnyRole("ADMIN", "USER") // ADMIN and USER can access /user/**
.anyRequest().authenticated() // Any other req
...

 

나름 인증서버를 구축해서 사용하기 때문에...비지니스 로직에서 녹여야 한다.

 

아르메리아 프레임워크를 적용해 인증서버를 구축했기 때문에 쉽게(?) 적용할 수 있다. 

@Bean
public ArmeriaServerConfigurator armeriaServerConfigurator() {
	return serverBuilder -> {
 		..
    	// oauth check
    	serverBuilder.decorator(AuthService::new);
 		..
 	}
}

 

모든 요청은 이제 AuthService 통과 한다. with 필터!

 

인그레스 인증을 AuthService 처리 한다.

nginx.ingress.kubernetes.io/auth-url: https://main.domain.co.kr/v2/ingress-oauth

 

요청에 대한 전체 적인 Flow를 보면

 

 

k8s에서 첫번째 관문은 인그레스가 담당한다.

인그레스는  정상적인  요청인지 auth-url을 통해서 확인 하고 라우팅을 한다.

 

 

인그레스와 인증 사이의 주고 받는 관계에서 원본 요청의 주소를 아래와 같이 확인 할 수 있다. 

request.headers().get("x-auth-request-redirect")

 

 

해당 Path 마다 권한을 녹이면 되겠다.

 

그냥 잘 만들어진 콩게이트웨이는 적용하자. 앞으론 .ㅠ ㅋ ㅠ

비공식적이지만 관리자 콘솔을 통해서 권한을 적용할 수 있더라....

 

윽 가즈아!!!

create table if not exists `permissionManager`
(
    seq                       BIGINT  PRIMARY KEY AUTO_INCREMENT,
    path                      varchar(32) not null,
    roleName                  varchar(100) not null,
    `type`                    varchar(10)   default 'exact', // prefix, include
    state                     varchar(2)    default 'A' comment 'A:active, D:delete'
);

 

매칭 Type 은  exact, prefix, include, .. 일단은...

바로 코드로 조져 보자.

@PostConstruct
public void init() {
    ServiceUtil.getPermissionManagerService().searchAllByState().subscribe(it -> list.add(it));
}

public static final String TYPE_PREFIX = "prefix";
public static final String TYPE_EXACT = "exact";
public static final String TYPE_INCLUDE = "include";
public static Map<String, PathCheckStrategy> authCheckStrategies = new HashMap<>();
static{
    authCheckStrategies.put(TYPE_EXACT, new ExactPathCheckStrategy());
    authCheckStrategies.put(TYPE_PREFIX, new PrefixPathCheckStrategy());
    authCheckStrategies.put(TYPE_INCLUDE, new IncludePathCheckStrategy());
}

public static Boolean isPermission(String path, List<String> permissions) {
    Optional<PermissionManager> authCheck = list.stream().filter((s) -> authCheckStrategies.get(s.getType()).isPathCheck(path, s.getPath())).findFirst();
    if(authCheck.isPresent()){
        return Arrays.stream(authCheck.get().getRoleName().split(",")).anyMatch( s -> permissions.contains(s));
    }else{
        return true;
    }
}

 

 

모든 요청을 체크 해야하는 부담이 된다... 각 EndPoint 하면 안 되나?

일단 비지니스 로직은

1. Permission 적용되지 않는 path는 by Pass

2. Permission 적용 되어 있다면 Role을 체크해서 존재하면 Pass 아니면 

if(!URIPermissionManager.isPermission(path, auths)){
       throw new AuthorizationException("not.access.authority");
}

 

 

그냥 콩게이트 적용하자!!!ㅋㅋㅜ

728x90