2013-02-27 105 views
9

मैं एनोटेशन और वसंत-सुरक्षा का उपयोग करके अपने ओपन सोर्स प्रोजेक्ट में विधि स्तर सुरक्षा जोड़ने की कोशिश कर रहा हूं। जिस समस्या का मैं अब सामना कर रहा हूं वह सभी विधियों को विशेष रूप से पेजिंग के लिए ढूंढता है (उदाहरण के लिए। पृष्ठ लौटा रहा है)।स्प्रिंग डेटा जेपीए और वसंत-सुरक्षा: डेटाबेस स्तर पर फ़िल्टर करें (विशेष रूप से पेजिंग के लिए)

सूचियों पर @ पोस्टफिल्टर कामों का उपयोग करना (लेकिन मुझे व्यक्तिगत रूप से विश्वास है कि यह एप्लिकेशन में फ़िल्टर करने के लिए एक अच्छा विचार नहीं है और डेटाबेस नहीं) लेकिन पूरी तरह से पेजिंग प्रश्नों पर विफल रहता है।

यह समस्याग्रस्त है क्योंकि मेरे पास List<Compound> युक्त एक इकाई है। यौगिक के विभिन्न कार्यान्वयन हैं और उपयोगकर्ता को केवल एक यौगिकों को पढ़ने का विशेषाधिकार हो सकता है। कंपाउंड TABLE_PER_CLASS विरासत का उपयोग करता है। रिपोजिटरीज QueryDslPredicateExecutor लागू करें।

मेरी सोच प्रत्येक क्वेरी को एक अनुमान जोड़ने के लिए है जो वर्तमान उपयोगकर्ता के आधार पर रिटर्न परिणामों को सीमित करता है। हालांकि मैं एक तरह से खो गया हूं) उपयोगकर्ता और भूमिकाओं के लिए डेटा मॉडल कैसे दिखना चाहिए और बी) फिर भविष्यवाणी कैसे करें (मॉडल परिभाषित होने के बाद यह संभवतः आसान है)। या क्या querydsl पहले से ही प्रकार आधारित फ़िल्टरिंग (queried कक्षा में निहित तत्वों पर) की पेशकश करता है?

+0

प्रश्न के लिए एक को देखने [उपयोगकर्ता स्कीमा] (http://static.springsource.org/spring-security/site/docs/3.2.x/reference/springsecurity-single.html#d0e8380]) अनुभाग –

+0

मैं बहुत मतलब कि मैं मौजूदा उपयोगकर्ताओं की भूमिकाओं को ध्यान में रखकर प्रश्नों को समायोजित कर सकता हूं, उदाहरण के लिए। किसी दिए गए इकाई से भूमिका और उपयोगकर्ता से भूमिका तक संबंध होना चाहिए। –

+0

फिर एसीएल http://static.springsource.org/spring-security/site/docs/3.2.x/reference/springsecurity-single.html#domain-acls और उपयुक्त डीबी स्कीमा http: // static में एक नज़र डालें। springsource.org/spring-security/site/docs/3.2.x/reference/springsecurity-single.html#dbschema-acl –

उत्तर

2

उस समय के लिए निम्नलिखित समाधान के साथ आया है। चूंकि मेरी परियोजना अपेक्षाकृत सरल है क्योंकि यह एक और जटिल परियोजना के लिए काम नहीं कर सकती है।

  1. एक उपयोगकर्ता या तो सभी या पढ़ सकते हैं एक निश्चित वर्ग

की संस्थाओं इसलिए किसी भी प्रश्न विधि @PreAuthorize युक्त hasRole साथ टिप्पणी की जा सकती में से कोई भी।

यह अपवाद मेरे प्रोजेक्ट में Container इकाई है। इसमें Compound का कोई उप-वर्ग हो सकता है और उपयोगकर्ता को उन सभी को देखने का विशेषाधिकार नहीं हो सकता है। वे फिल्टर होना चाहिए।

इसके लिए मैंने User और Role इकाई बनाई। Compound में Role पर एक OneToOne संबंध है और वह भूमिका Compound के लिए "read_role" है। User और Role में बहुत से रिश्ते हैं।

@Entity 
public abstract class Compound {  
    //... 
    @OneToOne  
    private Role readRole; 
    //... 
} 

मेरे सभी खजाने QueryDSLPredicateExecutor को लागू करने और है कि यहाँ बहुत हाथ हो जाता है। भंडार में कस्टम खोज-तरीकों को बनाने के बजाय हम उन्हें केवल सेवा परत में बनाते हैं और repositry.findAll(predicate) और repository.findOne(predicate) का उपयोग करते हैं। भविष्यवाणी वास्तविक उपयोगकर्ता इनपुट + "सुरक्षा फ़िल्टर" रखती है।

@PreAuthorize("hasRole('read_Container'") 
public T getById(Long id) {   
    Predicate predicate = QCompoundContainer.compoundContainer.id.eq(id); 
    predicate = addSecurityFilter(predicate); 
    T container = getRepository().findOne(predicate);   
    return container; 
} 

private Predicate addSecurityFilter(Predicate predicate){   
    String userName = SecurityContextHolder.getContext().getAuthentication().getName();    
    predicate = QCompoundContainer.compoundContainer.compound.readRole 
     .users.any().username.eq(userName).and(predicate);   
    return predicate; 
} 

नोट: QCompoundContainer "मेटा मॉडल" QueryDSL द्वारा उत्पन्न वर्ग है।

पिछले आप शायद Container से User को QueryDSL पथ प्रारंभ करने की आवश्यकता:

@Entity 
public abstract class CompoundContainer<T extends Compound> 
    //... 
    @QueryInit("readRole.users") // INITIALIZE QUERY PATH 
    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL, 
      targetEntity=Compound.class) 
    private T compound; 
    //... 
} 

इस अंतिम चरण के एक NullPointerException को जन्म दे सकता हटा रहा है।

इसके अलावा संकेत: CompoundService स्वचालित रूप से बचाने पर भूमिका सेट:

if (compound.getReadRole() == null) { 
    Role role = roleRepository.findByRoleName("read_" + getCompoundClassSimpleName()); 
    if (role == null) { 
     role = new Role("read_" + getCompoundClassSimpleName()); 
     role = roleRepository.save(role); 
    } 
    compound.setReadRole(role); 
} 
compound = getRepository().save(compound) 

यह काम करता है। नकारात्मक थोड़ा सा स्पष्ट है। वही Role उसी Compound वर्ग कार्यान्वयन के प्रत्येक एकल उदाहरण से जुड़ा हुआ है।

6

वर्तमान में ऐसा कोई समर्थन नहीं है लेकिन हमारे पास यह रोडमैप पर है। आप सामान्य प्रगति के लिए DATACMNS-293 का पालन करना चाहेंगे।