Spring) Security 권한설정하기

CokeBear·2022년 8월 17일
0

spring

목록 보기
6/15

사내 전사관리시스템을 개발하는데 있어 엔드포인트 별로 권한설정이 필요했다.

위 사진은 api문서 중 일부다. 엔드포인트 별로 각각의 권한이 설정되어 있음을 알 수 있다.

  • 개요
    -> Security에서 권한 설정하는 방법은 크게 2가지다.

    1. Configure에서 설정하는방법
    2. Method위에 Anotation으로 설정하는 방법
  • 문제점
    -> 나는 48개 가량 되는 엔드포인트와 권한들을 한눈에 관리하고 싶었다.
    따라서, 1번 방법을 채택 후 엔드포인트를 Class로 만들어 관리하기 쉽게 만들었다.


  • 코드

public class EndPoint {

  private HttpMethod method;
  // Method 방식
  private String endPointName;
  // endpotint 이름
  private Role[] roles;
  // 권한들

  public static EndPoint of(HttpMethod method, String endPointName) {
    EndPoint endPoint = new EndPoint();
    endPoint.method = method;
    endPoint.endPointName = endPointName;
    endPoint.roles = new Role[]{Role.ROLE_LV1,Role.ROLE_LV2,Role.ROLE_LV3,Role.ROLE_LV4};
    return endPoint;
  }
  public static EndPoint of(HttpMethod method, String endPointName,Role ...role) {
    EndPoint endPoint = new EndPoint();
    endPoint.method = method;
    endPoint.endPointName = endPointName;
    endPoint.roles = role;
    return endPoint;
  }

  public String[] getRoles() {
    return Arrays.stream(roles)
      .map(Enum::toString)
      .toArray(String[]::new);
  }
}

  • 프로젝트에서 접근종류는 크게 3가지 경우로 엔드포인트가 분리되었다.
    1. 권한 없이 접근가능 -> NONE
    2. 모든 권한 접근가능 -> COMMON
    3. 특정 권한들만 접근가능 -> ROLES
  • 위 특징들로 열거형 상수를 구성하였고 그 안에 엔드포인트 리스트들이 있게 했다.

  • 코드

public enum EndPointAccessByLevel {

  ROLES(List.of(
    //----------- day-off ------------------
    EndPoint.of(GET,"/api/v1/day-off/remaining",ROLE_LV1,ROLE_LV2),
    EndPoint.of(GET,"/api/v1/day-off/excell",ROLE_LV2,ROLE_LV3,ROLE_LV4),
    EndPoint.of(PUT,"/api/v1/day-off",ROLE_LV1,ROLE_LV2),
    EndPoint.of(POST,"/api/v1/day-off",ROLE_LV1,ROLE_LV2),
    //----------- day-off ------------------
    ...
  )),

  COMMON(List.of(
    //----------- Day-off ------------------
    EndPoint.of(GET,"/api/v1/day-off"),
    EndPoint.of(GET,"/api/v1/day-off/**"),
    //----------- Day-off ------------------
    ...
  )),

  NONE(List.of(
    //--------------login-------------------------
    EndPoint.of(POST,"/api/v1/login"),
    //--------------login-------------------------
	...
  ));
  private final List<EndPoint> endPoints;

  EndPointAccessByLevel(List<EndPoint> endPointList) {
    endPoints = endPointList;
  }

  public List<EndPoint> getEndPoints() {
    return endPoints;
  }
}

  • 마지막으로, stream을 이용해 list에 들어간 내용들을 하나씩 security에 적용해 주었다.
private void authorizeRequests(HttpSecurity http) throws Exception {


    EndPointAccessByLevel.NONE.getEndPoints()
      .forEach(endPoint -> {
        try {
          http.authorizeRequests()
            .antMatchers(endPoint.getMethod(), endPoint.getEndPointName()).permitAll();
        } catch (Exception e) {
          throw new RuntimeException(e);
        }
      });

    EndPointAccessByLevel.ROLES.getEndPoints()
      .forEach(endPoint -> {
        try {
          http.authorizeRequests()
            .antMatchers(endPoint.getMethod(), endPoint.getEndPointName()).hasAnyAuthority(endPoint.getRoles());
        } catch (Exception e) {
          throw new RuntimeException(e);
        }
      });
    EndPointAccessByLevel.COMMON.getEndPoints()
      .forEach(endPoint -> {
        try {
          http.authorizeRequests()
            .antMatchers(endPoint.getMethod(), endPoint.getEndPointName()).hasAnyAuthority(endPoint.getRoles());
        } catch (Exception e) {
          throw new RuntimeException(e);
        }
      });
    http.authorizeRequests().anyRequest().authenticated();// 그 외 항목 전부 인증 적용
  }
profile
back end developer

0개의 댓글