Spring Security에서 역할과 권한 부여 권한의 차이점


227

Spring Security 에는 액세스 권한 을 부여 / 제어하는 권한GrantedAuthority얻는 인터페이스 와 같은 개념과 구현 이 있습니다.

createSubUsers 또는 deleteAccounts 와 같은 허용 가능한 작업 ( 관리자 (역할 포함 ROLE_ADMIN) 에게 허용)을 원합니다 .

온라인에서 볼 수있는 튜토리얼 / 데모로 혼동되고 있습니다. 나는 내가 읽은 것을 연결하려고 노력하지만, 우리는 두 가지를 상호 교환 적으로 취급한다고 생각합니다.

문자열을 hasRole소비하는 것을 보았 GrantedAuthority습니까? 나는 분명히 이해하는 데 잘못하고 있습니다. Spring Security에서 개념적으로 무엇입니까?

해당 역할의 권한과 별도로 사용자 역할을 어떻게 저장합니까?

또한 org.springframework.security.core.userdetails.UserDetails인증 공급자가 참조한 DAO에서 사용되는 인터페이스를 살펴보고 있습니다 User(최종 GrantedAuthority 참고).

public User(String username, 
            String password, 
            boolean enabled, 
            boolean accountNonExpired,
            boolean credentialsNonExpired, 
            boolean accountNonLocked, 
            Collection<? extends GrantedAuthority> authorities)

아니면 다른 두 가지를 구별하는 다른 방법이 있습니까? 아니면 지원되지 않고 스스로 만들어야합니까?

답변:


365

GrantedAuthority를 ​​"권한"또는 "권리"라고 생각하십시오. 이러한 "권한"은 (일반적으로) 문자열 ( getAuthority()방법 과 함께)로 표현됩니다 . 이 문자열을 통해 권한을 식별하고 유권자가 무언가에 대한 액세스 권한을 부여 할 것인지 결정할 수 있습니다.

보안 컨텍스트에 배치하여 사용자에게 다른 GrantedAuthority (권한)를 부여 할 수 있습니다. 일반적으로 필요한 GrantedAuthorities를 리턴하는 UserDetails 구현을 리턴하는 고유 한 UserDetailsService를 구현하여이를 수행합니다.

역할 (많은 예제에서 사용됨)은 역할이 접두사로 시작하는 GrantedAuthority라는 이름 지정 규칙이있는 "권한"입니다 ROLE_. 더 이상 아무것도 없습니다. 역할은 단지 GrantedAuthority- "권한"- "권리"입니다. ROLE_접두사가 붙은 역할이 접두사가 ROLE_기본값으로 사용되는 RoleVoter와 같이 접두사가 있는 역할이 특별히 처리 되는 스프링 보안의 많은 부분이 있습니다 . 이를 통해 ROLE_접두사없이 역할 이름을 제공 할 수 있습니다 . Spring security 4 이전에는 이러한 "역할"의 특수한 처리가 일관되게 따르지 않았으며 권한과 역할이 종종 동일하게 취급되었습니다 (예 :hasAuthority()hasRole()). 봄 보안 4과 함께, 역할의 치료는 "역할"을 가진 거래 (같은 것을보다 일관되고 코드 RoleVoterhasRole표현 등이) 항상 추가 ROLE_당신을 위해 접두사. 그래서 hasAuthority('ROLE_ADMIN')와 같은 의미 hasRole('ADMIN')때문에 ROLE_접두사가 자동으로 추가됩니다. 추가 정보 는 스프링 보안 3-4 마이그레이션 안내서 를 참조하십시오.

그러나 여전히 : 역할은 특수한 ROLE_접두사가 있는 권한 일뿐 입니다. 따라서 스프링 보안 3의 @PreAuthorize("hasRole('ROLE_XYZ')")경우와 동일하며 @PreAuthorize("hasAuthority('ROLE_XYZ')")스프링 보안 4의 @PreAuthorize("hasRole('XYZ')")경우와 동일합니다 @PreAuthorize("hasAuthority('ROLE_XYZ')").

사용 사례와 관련하여 :

사용자에게는 역할이 있으며 역할은 특정 작업을 수행 할 수 있습니다.

GrantedAuthorities사용자가 속한 역할과 역할이 수행 할 수있는 작업으로 끝날 수 있습니다. GrantedAuthorities역할에 대한 접두사를 가지고 ROLE_와 작업은 접두사가 OP_. 조작 당국이 수에 대한 예는 OP_DELETE_ACCOUNT, OP_CREATE_USER, OP_RUN_BATCH_JOB등의 역할을 할 수있다 ROLE_ADMIN, ROLE_USER, ROLE_OWNER

GrantedAuthority이 (의사 코드) 예제와 같이 엔티티를 구현하게 할 수 있습니다 .

@Entity
class Role implements GrantedAuthority {
    @Id
    private String id;

    @ManyToMany
    private final List<Operation> allowedOperations = new ArrayList<>();

    @Override
    public String getAuthority() {
        return id;
    }

    public Collection<GrantedAuthority> getAllowedOperations() {
        return allowedOperations;
    }
}

@Entity
class User {
    @Id
    private String id;

    @ManyToMany
    private final List<Role> roles = new ArrayList<>();

    public Collection<Role> getRoles() {
        return roles;
    }
}

@Entity
class Operation implements GrantedAuthority {
    @Id
    private String id;

    @Override
    public String getAuthority() {
        return id;
    }
}

당신이 당신의 데이터베이스에서 만든 역할 및 운영의 ID는 GrantedAuthority를 표현, 예를 들면 것 ROLE_ADMIN, OP_DELETE_ACCOUNT() 사용자가 인증 된 경우 등, 반드시 모든 역할의 모든 GrantedAuthorities와 해당 작업이 UserDetails.getAuthorities에서 반환 된 것을 확인을 방법.

예 : id ROLE_ADMIN가있는 관리자 역할 에는 작업이 OP_DELETE_ACCOUNT(가 OP_READ_ACCOUNT) OP_RUN_BATCH_JOB할당되어 있습니다. id ROLE_USER가있는 사용자 역할 에는 작업이 OP_READ_ACCOUNT있습니다.

그 결과 보안 컨텍스트에서 관리자의 로그가 GrantedAuthorities이 경우 : ROLE_ADMIN, OP_DELETE_ACCOUNT, OP_READ_ACCOUNT,OP_RUN_BATCH_JOB

사용자가 그것을 기록하는 경우가있을 것입니다 ROLE_USER,OP_READ_ACCOUNT

UserDetailsService는 모든 역할과 해당 역할의 모든 작업을 수집하고 반환 된 UserDetails 인스턴스의 getAuthorities () 메서드를 통해 사용할 수 있도록주의를 기울입니다.


2
감사합니다! "hasRole ( 'rolename')"이 Spring 4에서 작동하지 않는 이유를 어디에서나 검색했습니다.-> 그들의 문서가 정확히 빠르지 않았습니다. 그냥 빨리 "찾고 교체"하고 나는 궤도에 돌아왔다!
Jørgen Skår Fischer

12
이것은 좋은 대답입니다. hasRole('xyz')Spring Security 4 에서는 약간 다르게 다르게 설명하는 한 가지가 ROLE_ 접두사를 hasAuthority('xyz')기대하지만 접두사는 기대하지 않고 전달 된 내용을 정확하게 평가합니다.이 솔루션을 사용했지만 그 hasRole('OP_MY_PERMISSION')이후 로 문제가 발생했습니다. ROLE_의 접두사가 필요했다. 대신 hasAuthority('OP_MY_PERMISSION')접두사가 없기 때문에를 사용해야했습니다 .
randal4

@ james이 질문을 볼 수 있습니까 stackoverflow.com/questions/41500031/…
kumar

1
JSTL에서 springframework.org/security/tags <sec:authorize access="hasRole('ADMIN')">는 다음과 같습니다<sec:authorize access="hasRole('ROLE_ADMIN')">
Alex78191

1
예. OP_은 임의의 접두사입니다. ROLE_은 일부 스프링 구현에서 특별한 의미를 갖습니다.
James

9

AFAIK GrantedAuthority와 역할은 봄 보안에서 동일합니다. GrantedAuthority의 getAuthority () 문자열이 역할 (기본 구현 SimpleGrantedAuthority에 따라)입니다.

귀하의 경우에는 계층 적 역할을 사용할 수 있습니다

<bean id="roleVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter">
    <constructor-arg ref="roleHierarchy" />
</bean>
<bean id="roleHierarchy"
        class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
    <property name="hierarchy">
        <value>
            ROLE_ADMIN > ROLE_createSubUsers
            ROLE_ADMIN > ROLE_deleteAccounts 
            ROLE_USER > ROLE_viewAccounts
        </value>
    </property>
</bean>

당신이 찾고있는 정확한 솔은 아니지만 그것이 도움이되기를 바랍니다.

편집 : 댓글에 답장

역할은 스프링 보안의 권한과 같습니다. hasRole과 함께 intercept-url을 사용하면 어떤 역할 / 권한에 대해 어떤 작업이 허용되는지를 매우 세밀하게 제어 할 수 있습니다.

애플리케이션에서 처리하는 방식은 view_account, delete_account, add_account 등과 같은 각 작업 (또는 나머지 URL)에 대한 권한 (즉, 역할)을 정의하는 것입니다. 그런 다음 admin, guest_user, normal_user와 같은 각 사용자에 대한 논리적 프로필을 만듭니다. 프로필은 스프링 보안과 무관하게 논리적 권한 그룹입니다. 새 사용자가 추가되면 프로파일이 할당됩니다 (허용 가능한 모든 권한을 가짐). 이제 사용자가 일부 작업을 수행하려고 할 때 해당 작업에 대한 권한 / 역할이 사용자 부여 권한과 비교하여 확인됩니다.

또한 기본 RoleVoter는 접두사 ROLE_를 사용하므로 ROLE_로 시작하는 모든 권한이 역할로 간주되므로 역할 유권자에서 사용자 정의 RolePrefix를 사용하고 스프링 보안에서이를 사용하여이 기본 동작을 변경할 수 있습니다.


1
도와 주셔서 감사합니다. 계층은 다른 것으로 보입니다. 내가 지금 생각하고있는 방법 (Spring Security를 ​​사용해야하는 경우)은 역할과 권한을 모두 동일한 목록에 저장하고 hasRole 술어를 사용하여 두 가지에 대한 검사를 수행합니다. 그것에 대해 더 생각하면-아마도 스프링 시큐리티의 사람들이 의도적으로 남겨둔 것일까 요? 역할 및 권한 / 권한의 전체 목록 또는 기타 권한 부여 응용 프로그램에서 hasRole을 사용하여 확인하는 것 외에 인터셉트 URL을 사용할 가능성이 있습니까? 또한 ROLE_ 접두사를 사용해야합니까? 컨벤션인가요?
Chinmay

7

이러한 개념 간의 관계를 이해하는 또 다른 방법은 ROLE을 권한 컨테이너로 해석하는 것입니다.

권한은 때때로 특정 데이터 범위 또는 컨텍스트와 결합 된 특정 작업을 대상으로하는 세분화 된 권한입니다. 예를 들어, 읽기, 쓰기, 관리는 주어진 정보 범위에 대한 다양한 수준의 권한을 나타낼 수 있습니다.

또한 권한이 요청의 처리 플로우에 깊이 적용되는 반면 ROLE은 컨트롤러에 도달하기 전에 요청 필터 방식으로 필터링됩니다. 모범 사례는 비즈니스 계층에서 컨트롤러를 지나서 권한 부여를 구현하도록 규정합니다.

반면에 ROLES는 권한 집합을 대략적으로 표현한 것입니다. ROLE_READER에는 읽기 또는보기 권한 만 있고 ROLE_EDITOR에는 읽기 및 쓰기 권한이 있습니다. 역할은 주로 http와 같은 요청 처리 외곽에서 첫 번째 심사에 사용됩니다. ... .antMatcher (...). hasRole (ROLE_MANAGER)

요청의 프로세스 흐름에 깊이 적용되는 권한을 통해 권한을보다 세밀하게 적용 할 수 있습니다. 예를 들어, 사용자에게 리소스를 첫 번째 수준으로 만들지 만 읽기 전용 리소스에 대한 읽기 쓰기 권한이있을 수 있습니다. ROLE_READER가 있으면이 리소스를 편집하려면 쓰기 권한이 필요하기 때문에 첫 번째 수준 리소스를 편집 할 수있는 권한이 제한되지만 @PreAuthorize 인터셉터는 하위 리소스를 편집하기 위해 잠정적으로 차단할 수 있습니다.

제이크


2

다른 사람들이 언급했듯이 역할을보다 세부적인 권한을위한 컨테이너로 생각합니다.

계층 적 역할 구현에는 이러한 세부적인 권한에 대한 미세한 제어가 부족한 것으로 나타났습니다.
그래서 관계를 관리하고 보안 컨텍스트에서 권한을 부여한 권한을 주입하는 라이브러리를 만들었습니다.

앱에 CREATE, READ, UPDATE, DELETE와 같은 권한 세트가있을 수 있으며 사용자 역할과 관련이 있습니다.

또는 READ_POST, READ_PUBLISHED_POST, CREATE_POST, PUBLISH_POST와 같은보다 구체적인 권한

이러한 권한은 비교적 정적 인 역할이지만 역할과의 관계는 동적 일 수 있습니다.

예 -

@Autowired 
RolePermissionsRepository repository;

public void setup(){
  String roleName = "ROLE_ADMIN";
  List<String> permissions = new ArrayList<String>();
  permissions.add("CREATE");
  permissions.add("READ");
  permissions.add("UPDATE");
  permissions.add("DELETE");
  repository.save(new RolePermissions(roleName, permissions));
}

이러한 권한과 역할의 관계를 관리하는 API를 만들 수 있습니다.

다른 답변을 복사 / 붙여 넣기하고 싶지 않으므로 여기에 더 자세한 설명에 대한 링크가 있습니다.
https://stackoverflow.com/a/60251931/1308685

구현을 재사용하기 위해 리포지토리를 만들었습니다. 부담없이 기부 해주세요!
https://github.com/savantly-net/spring-role-permissions

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.