SpringBoot Meteor

[Spring Boot] Spring Security 시큐리티 권한 업데이트 시 동적 적용

DoubleMeteor 2021. 12. 21. 13:31

관리자 페이지에서 회원에 따른 권한을 변경하였을 때 재 로그인을 하지 않더라도

변경된 권한이 적용되어 권한이 걸린 경로로 접근하는 것을 막고 싶을 때

(로그아웃을 시킨뒤에 다시 로그인 플로우를 진행하게되면 사용자의 불편함이 예상, 그리고 권한이 바뀐 이후의

시점에도 로그아웃(세션을 끊음)을 하지않는다면 로그아웃 이전까지의 권한이 유지됨)

최초 로그인 시에 SpringSecurity가 계정 정보를 관리할 수 있도록 Authentication객체를 만들어준다.

이 Autentication객체 안에는 로그인 시점의 계정 정보를 담고 있다.

사용자의 권한이 변경 또는 추가가 되어도 update된 정보에 대해서는 Authentication객체에는 현행화(동기화)가 되지않았기 때문이다. 즉, Security가 게정정보를 관리하고있는 객체가 update되지 않았다는 말이다.

해결방법 → 유저의 권한 변경이 일어나는 시점에 기존 시큐리티가 가지고 관리하고있던 Autentication 객체의

권한만 수정(update)해주면 된다.

기존 객체에 동적으로 새로운 권한을 추가해보자.

  1. 우선 Autentication객체가 들고있는 기존 계정의 권한 정보를 가지고 온다
// 기존 계정의 정보를 들고온다.
Authentication auth = SecurityContextHolder.getContext().getAuthentication();

// 새로운 권한을 넣기위해 리스트를 하나 생성한다 (단일 권한일시에는 리스트로 할 필요 없음)
List updatedAuthorities = new ArrayList<>();
  1. 권한을 추가하거나(add), 새로운 권한을 부여한다 (cleart → add)
updatedAuthorities.add(new SimpleGrantedAuthority(userRoleType.getRole().getValue()));
  1. update한 권한정보로 다시 Security가 관리할 수 있는 객체를 생성해준다.
Authentication newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(), auth.getCredentials(), updatedAuthorities);
  1. Security가 관리하고있는 객체를 3에서 변경된 대상으로 다시 변경해준다(동기화)
// SecurityContextHolder의 Authentication에 새로운 객체정보로 update시켜줌 
SecurityContextHolder.getContext().setAuthentication(newAuth);
  • 전체코드
/**
     * 회원 권한 수정
     * @param userRoleType 회원 idx, 권한
     * @return HttpEntity
     */
    @PutMapping
    public HttpEntity<?> memberRoleUpdate(@RequestBody AdminMemberRoleUpdateDTO userRoleType ) {

        AdminRoleUpdateDTO adminRoleUpdateDTO = memberAdminService.memberRoleUpdate(userRoleType);
        if (adminRoleUpdateDTO == null) {
            return new ResponseEntity<>(new ResponseDTO<>(ResponseEnum.MEMBER_ROLE_UPDATE_FAIL), HttpStatus.EXPECTATION_FAILED);
        }

        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        List<GrantedAuthority> updatedAuthorities = new ArrayList<>();
        updatedAuthorities.add(new SimpleGrantedAuthority(userRoleType.getRole().getValue()));
        Authentication newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(), auth.getCredentials(), updatedAuthorities);
        SecurityContextHolder.getContext().setAuthentication(newAuth);

        return new ResponseEntity<>(new ResponseDTO<>(ResponseEnum.MEMBER_ROLE_UPDATE_SUCCESS, adminRoleUpdateDTO), HttpStatus.OK);
    }

회원 권한을 수정한 후 → 시큐리티 객체 정보를 업데이트(동기화) 시켜 줌

로그아웃 → 로그인을 따로하지 않더라도 시큐리티 객체정보가 업데이트 됨으로 리로드될 시에 다시 권한을 체크 가능 이후

짜놓은 로직 플로우 대로 실행