Bahar Güvenliğinde Rol ve Verilen Yetki Arasındaki Fark


228

Kavramlar ve uygulamalar gibi, Bahar Güvenlik vardır GrantedAuthoritybir olsun arayüzüne yetkisi / authorize için bir erişim kontrol eder.

Ben gibi izin verilen operasyonlar, bu istiyoruz createSubUsers veya deleteAccounts Bir sağlayacak, yönetici (rolle ROLE_ADMIN).

Çevrimiçi gördüğüm öğreticiler / demolar olarak kafam karışıyor. Okuduğum şeyi bağlamaya çalışıyorum, ama sanırım ikisine birbirinin yerine geçiyoruz.

Dize hasRoletüketiyor muyum GrantedAuthority? Kesinlikle anlamakta yanlış yapıyorum. Bahar Güvenliğinde kavramsal olarak bunlar nelerdir?

Bir kullanıcının rolünü, bu rol için yetkililerden ayrı olarak nasıl saklayabilirim?

Ben de (son GrantedAuthority notu) org.springframework.security.core.userdetails.UserDetailstüketen kimlik doğrulama sağlayıcısı DAO başvurulan kullanılan arabirim bakıyorum User:

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

Yoksa diğer ikisini ayırmanın başka bir yolu var mı? Yoksa desteklenmiyor mu ve kendimizinkini mi yapmalıyız?

Yanıtlar:


366

Bir GrantedAuthority'yi bir "izin" veya "hak" olarak düşünün. Bu "izinler" (normal olarak) dize ( getAuthority()yöntemle) olarak ifade edilir . Bu dizeler izinleri tanımlamanıza ve seçmenlerinizin bir şeye erişim izni verip vermediklerine karar vermelerine izin verir.

Kullanıcılara güvenlik bağlamına koyarak farklı GrantedAuthority'ler (izinler) verebilirsiniz. Bunu normalde gerekli GrantedAuthorities döndüren bir UserDetails uygulaması döndüren kendi UserDetailsService uygulayarak yaparsınız.

Roller (birçok örnekte kullanıldığı gibi), bir rolün önekle başlayan bir GrantedAuthority olduğunu söyleyen bir adlandırma kuralına sahip "izinlerdir" ROLE_. Başka bir şey yok. Bir rol sadece bir GrantedAuthority - bir "izin" - bir "hak" tır. Bahar güvenliğinde, ROLE_öneki rolünün özellikle ROLE_önekin varsayılan olarak kullanıldığı RoleVoter'da olduğu gibi ele alındığı birçok yer görürsünüz . Bu, rol adlarını ROLE_önek ile vermenizi sağlar . Bahar güvenliğinden 4 önce, "rollerin" bu özel muamelesi çok tutarlı bir şekilde takip edilmemiştir ve yetkililer ve roller genellikle aynı şekilde ele alınmıştır (örn.hasAuthority()hasRole()). Bahar Güvenlik 4 ile rollerin tedavi "rolleri" ile fırsatlar (gibi o daha tutarlı ve kodudur RoleVoter, hasRoleifade vs) her zaman ekler ROLE_sizin için önek. Yani hasAuthority('ROLE_ADMIN')aynı anlamda hasRole('ADMIN')çünkü ROLE_önek otomatik olarak eklenir. Daha fazla bilgi için yay güvenliği 3 ila 4 geçiş kılavuzuna bakın.

Ama yine de: bir rol sadece özel bir ROLE_öneki olan bir otoritedir . Yani Bahar güvenliği 3 @PreAuthorize("hasRole('ROLE_XYZ')")ile aynıdır @PreAuthorize("hasAuthority('ROLE_XYZ')")ve Bahar güvenliği 4 @PreAuthorize("hasRole('XYZ')")ile aynıdır @PreAuthorize("hasAuthority('ROLE_XYZ')").

Kullanım durumunuzla ilgili:

Kullanıcıların rolleri vardır ve roller belirli işlemleri gerçekleştirebilir.

GrantedAuthoritiesBir kullanıcının ait olduğu roller ve bir rolün gerçekleştirebileceği işlemler için sonuç alabilirsiniz. GrantedAuthoritiesRoller için ön eki ROLE_ve operasyon ön eki OP_. Operasyon makamları olabilir için bir örnek OP_DELETE_ACCOUNT, OP_CREATE_USER, OP_RUN_BATCH_JOBvb Rolleri olabilir ROLE_ADMIN, ROLE_USER, ROLE_OWNERvb

GrantedAuthorityVarlıklarınızın bu (sözde kod) örneğinde olduğu gibi uygulanmasını sağlayabilirsiniz :

@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;
    }
}

Veritabanınızda oluşturmak roller ve operasyonların kimlikleri GrantedAuthority temsilini, örneğin olurdu ROLE_ADMIN, OP_DELETE_ACCOUNT) (Bir kullanıcı teyid edildiğinde vb nokta bütün rollerin tüm GrantedAuthorities ve ilgili işlemleri UserDetails.getAuthorities döndü emin olun yöntem.

Örnek: kimliğine sahip yönetici rolü ROLE_ADMINoperasyonları vardır OP_DELETE_ACCOUNT, OP_READ_ACCOUNT, OP_RUN_BATCH_JOBkendisine atanmış. Kimliğine ROLE_USERsahip kullanıcı rolünün işlemi vardır OP_READ_ACCOUNT.

Ortaya çıkan güvenlik bağlamında bir yönetici günlükleri GrantedAuthorities olacaksa: ROLE_ADMIN, OP_DELETE_ACCOUNT, OP_READ_ACCOUNT,OP_RUN_BATCH_JOB

Bir kullanıcının giriş yaparsa, bu sahip olacaktır: ROLE_USER,OP_READ_ACCOUNT

UserDetailsService, bu rollerin tüm rollerini ve tüm işlemlerini toplamaya ve bunları döndürülen UserDetails örneğinde getAuthorities () yöntemiyle kullanılabilir hale getirmeye özen gösterir.


2
Teşekkür ederim! Ben her yerde neden "hasRole ('rolename')" Bahar 4 -> Onların belgelerini gözden geçirmek tam olarak hızlı değildi çalışma değildi için arıyorum. Sadece hızlı bir "bulmak ve değiştirmek" ve ben geri yolda!
Jørgen Skår Fischer

12
Bu harika bir cevap. Biraz farklı açıklamak için bir şey, hasRole('xyz')Bahar Güvenlik 4 ROLE_ öneki hasAuthority('xyz')olmasını beklerken, önek beklemiyor ve ne geçtiğini tam olarak değerlendiriyor. Bu çözümü kullandım, ancak o hasRole('OP_MY_PERMISSION')zamandan beri sorunla karşılaştım ROLE_ öneki ihtiyaç vardı. Bunun yerine, hasAuthority('OP_MY_PERMISSION')öneki olmadığımdan beri kullanmalıydım .
randal4


1
JSTL springframework.org/security/tags <sec:authorize access="hasRole('ADMIN')">ile aynı<sec:authorize access="hasRole('ROLE_ADMIN')">
Alex78191

1
Evet. OP_ sadece keyfi bir önektir. ROLE_ bazı bahar uygulamalarında özel bir anlama sahiptir.
James

9

Bahar güvenliğinde yetki ve roller aynıdır. GrantedAuthority'nin getAuthority () dizesi roldür (varsayılan uygulamaya göre SimpleGrantedAuthority).

Durumunuz için Hiyerarşik Rolleri kullanabilirsiniz

<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>

Aradığınız sol değil, ama umarım yardımcı olur

Düzenle : Yorumunuzu yanıtlayın

Rol, bahar güvenliğinde izin gibidir. hasRole ile intercept-url kullanmak, hangi rol / izin için hangi işleme izin verildiğini çok ince bir şekilde kontrol eder.

Uygulamamızda işleyiş şeklimiz, örneğin view_account, delete_account, add_account vb. İçin her işlem (veya dinlenme url'si) için izin (yani rol) tanımlarız. Sonra yönetici, guest_user, normal_user gibi her kullanıcı için mantıksal profiller oluştururuz. Profiller, yay güvenliğinden bağımsız olarak sadece izinlerin mantıksal gruplandırmasıdır. Yeni bir kullanıcı eklendiğinde, ona bir profil atanır (izin verilen tüm izinlere sahip). Artık kullanıcı bir eylem gerçekleştirmeye çalıştığında, o eylem için izin / rol verilen kullanıcı yetkilerine göre kontrol edilir.

Ayrıca defaultn RoleVoter, ROLE_ önekini kullanır, bu nedenle ROLE_ ile başlayan herhangi bir yetki rol olarak kabul edilir, rol seçicisinde özel bir RolePrefix kullanarak ve bahar güvenliğinde kullanarak bu varsayılan davranışı değiştirebilirsiniz.


1
Yardımın için teşekkürler. Hiyerarşi başka bir şey gibi görünüyor. Şimdi yapmayı düşündüğüm şekilde (eğer Spring Security kullanmam gerekiyorsa) hem rolü hem de otoriteyi aynı listede saklamak ve her ikisi için de kontroller yapmak için hasRole yüklemini kullanmaktır. Bunun hakkında daha fazla düşünmek - bu muhtemelen Spring Security'deki çocuklar tarafından kasıtlı olarak bırakılıyor mu? Roller ve İmtiyazlar / Yetkiler - veya diğer yetkilendirme uygulamalarının tam listesinde hasRole kullanarak kontrol etmek dışında intercept-url kullanma olasılığı var mıdır. Ayrıca, ROLE_ önekinin eklenmesi gerekir? Kongre mi?
Chinmay

7

Bu kavramlar arasındaki ilişkiyi anlamanın bir başka yolu, bir ROLE'yi Yetki kabı olarak yorumlamaktır.

Yetkililer, bazen belirli veri kapsamı veya bağlamıyla birleştirilmiş belirli bir işlemi hedefleyen ayrıntılı izinlerdir. Örneğin, Okuma, Yazma, Yönetme, belirli bir bilgi kapsamına yönelik çeşitli izin düzeylerini temsil edebilir.

Ayrıca, yetkililer bir talebin işleme akışında derinlemesine uygulanırken, ROLE Kontrolöre ulaşmadan önce talep filtresi yoluyla filtrelenir. En iyi uygulamalar, iş katmanındaki Denetleyiciyi geçen makamların uygulanmasını öngörür.

Öte yandan, ROLES bir izin kümesinin kaba taneli gösterimidir. ROLE_READER yalnızca Okuma veya Görüntüleme yetkisine sahipken, ROLE_EDITOR hem Okuma hem Yazma yetkisine sahip olacaktır. Roller esas olarak http gibi istek işlemenin dışında bir ilk tarama için kullanılır. ... .antMatcher (...). hasRole (ROLE_MANAGER)

Yetkililer, talebin süreç akışında derin bir şekilde uygulanıyor, iznin daha hassas bir şekilde uygulanmasına izin veriyor. Örneğin, bir kullanıcının bir kaynağı ilk seviyeye getirmek için Okuma Yazma izni olabilir, ancak yalnızca bir alt kaynağa Okuma izni olabilir. ROLE_READER'a sahip olmak, bu kaynağı düzenlemek için Yazma iznine ihtiyaç duyduğundan birinci düzey kaynağı düzenleme hakkını kısıtlar, ancak bir @PreAuthorize önleme aracı alt kaynağı düzenleme kararını engelleyebilir.

Jake


2

Diğerlerinin de belirttiği gibi, rolleri daha ayrıntılı izinler için kapsayıcılar olarak düşünüyorum.

Her ne kadar Hiyerarşi Rolü uygulamasının bu ayrıntılı izin üzerinde ince bir denetim olmadığını buldum.
Bu nedenle, ilişkileri yönetmek ve güvenlik bağlamında izin verilen yetkiler olarak izinleri enjekte etmek için bir kütüphane oluşturdum.

Uygulamada, daha sonra kullanıcının Rolü ile ilişkili olan CREATE, READ, UPDATE, DELETE gibi bir dizi izin alabilirim.

Veya READ_POST, READ_PUBLISHED_POST, CREATE_POST, PUBLISH_POST gibi daha spesifik izinler

Bu izinler nispeten statiktir, ancak rollerin onlarla olan ilişkisi dinamik olabilir.

Misal -

@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));
}

Bu izinlerin bir rolle ilişkisini yönetmek için API'ler oluşturabilirsiniz.

Başka bir cevabı kopyalamak / yapıştırmak istemiyorum, bu yüzden SO hakkında daha eksiksiz bir açıklamanın bağlantısı.
https://stackoverflow.com/a/60251931/1308685

Uygulamamı yeniden kullanmak için bir repo oluşturdum. Lütfen katkıda bulunmaktan çekinmeyin!
https://github.com/savantly-net/spring-role-permissions

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.