2014-11-05 11 views
22

में कस्टम अभिव्यक्तियों का उपयोग कैसे करें @Preauthorize ब्लॉक में अधिक अभिव्यक्तिपूर्ण वक्तव्य बनाने का कोई तरीका है? यहां कुछ ऐसा उदाहरण दिया गया है जो मुझे अपने आप को दोहराने लगता है, क्योंकि @Preauthorize बॉक्स से बहुत स्मार्ट नहीं है।स्प्रिंग सिक्योरिटी @ प्रीअधिकृत/@ पोस्टअधिकृत एनोटेशन

@RequestMapping(value = "{id}", method = RequestMethod.DELETE) 
public void deleteGame(@PathVariable int id, @ModelAttribute User authenticatingUser) { 
    Game currentGame = gameService.findById(id); 
    if(authenticatingUser.isAdmin() || currentGame.getOwner().equals(authenticatingUser)) { 
     gameService.delete(gameService.findById(id)); 
    } else { 
     throw new SecurityException("Only an admin, or an owner can delete a game."); 
    } 
} 

जो मैं पसंद करूंगा वह कुछ ऐसा है। समस्या का

@RequestMapping(value = "{id}", method = RequestMethod.DELETE) 
@Preauthorize(isAdmin(authenicatingUser) OR isOwner(authenicatingUser, id) 
public void deleteGame(@PathVariable int id, @ModelAttribute User authenticatingUser, @ModelAttribute currentGame) { //I'm not sure how to add this either :(
    gameService.delete(gameService.findById(id)); 
} 

भाग है कि मैं इस तरह के डेटाबेस से क्वेरी खेल की एक प्रति प्राप्त करने के लिए, और फिर मालिक की तुलना के रूप में अनुमतियाँ, सत्यापित करने के लिए इस सामग्री में से कुछ लाने के लिए डेटाबेस के लिए एक प्रश्न बनाने की जरूरत है अनुरोध करने वाले व्यक्ति को खेल का। मुझे सच में यकीन नहीं है कि यह सब @Preauthorize एनोटेशन प्रोसेसर के संदर्भ में कैसे काम करता है, या मैं @Preauthorize ("") मान विशेषता में उपलब्ध वस्तुओं के संग्रह में चीजें कैसे जोड़ता हूं।

उत्तर

20

1) सबसे पहले आपको MethodSecurityExpressionRoot को दोबारा लागू करना होगा जिसमें अतिरिक्त विधि-विशिष्ट कार्यक्षमता शामिल है। मूल वसंत सुरक्षा कार्यान्वयन पैकेज निजी है और इसलिए इसे विस्तारित करना संभव नहीं है। मैं दिए गए वर्ग के लिए स्रोत कोड की जांच करने का सुझाव देता हूं।

public class CustomMethodSecurityExpressionRoot extends SecurityExpressionRoot implements MethodSecurityExpressionOperations { 

    // copy everything from the original Spring Security MethodSecurityExpressionRoot 

    // add your custom methods 

    public boolean isAdmin() { 
     // do whatever you need to do, e.g. delegate to other components 

     // hint: you can here directly access Authentication object 
     // via inherited authentication field 
    } 

    public boolean isOwner(Long id) { 
     // do whatever you need to do, e.g. delegate to other components 
    } 
} 

2) इसके बाद आप कस्टम MethodSecurityExpressionHandler कि इसके बाद के संस्करण का उपयोग करेगा CustomMethodSecurityExpressionRoot परिभाषित लागू करने के लिए की है।

public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler { 

    private final AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl(); 

    @Override 
    public void setReturnObject(Object returnObject, EvaluationContext ctx) { 
     ((MethodSecurityExpressionRoot) ctx.getRootObject().getValue()).setReturnObject(returnObject); 
    } 

    @Override 
    protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, 
     MethodInvocation invocation) { 
     final CustomMethodSecurityExpressionRoot root = new CustomMethodSecurityExpressionRoot(authentication); 
     root.setThis(invocation.getThis()); 
     root.setPermissionEvaluator(getPermissionEvaluator()); 
     root.setTrustResolver(this.trustResolver); 
     root.setRoleHierarchy(getRoleHierarchy()); 

     return root; 
    } 
} 

3) अपने संदर्भ में अभिव्यक्ति हैंडलर बीन परिभाषित करें, उदा। इस प्रकार

<bean id="methodSecurityExpressionHandler" 
    class="my.package.CustomMethodSecurityExpressionHandler"> 
    <property name="roleHierarchy" ref="roleHierarchy" /> 
    <property name="permissionEvaluator" ref="permissionEvaluator" /> 
</bean> 

4 XML के माध्यम से आप यह कर सकते हैं) ऊपर परिभाषित हैंडलर

<security:global-method-security pre-post-annotations="enabled"> 
    <security:expression-handler ref="methodSecurityExpressionHandler"/> 
</security:global-method-security> 
रजिस्टर

5) तो बस अपने @PreAuthorize और/या @PostAuthorize एनोटेशन में परिभाषित एक्सप्रेशन का उपयोग

@PreAuthorize("isAdmin() or isOwner(#id)") 
public void deleteGame(@PathVariable int id, @ModelAttribute currentGame) { 
    // do whatever needed 
} 

और एक और बात। नियंत्रक विधियों को सुरक्षित करने के लिए विधि स्तर सुरक्षा का उपयोग करना बहुत आसान नहीं है बल्कि व्यावसायिक तर्क (ए.के.ए. आपकी सेवा परत विधियों) के साथ विधियों को सुरक्षित करने के लिए है। फिर आप नीचे की तरह कुछ उपयोग कर सकते हैं।

public interface GameService { 

    // rest omitted 

    @PreAuthorize("principal.admin or #game.owner = principal.username") 
    public void delete(@P("game") Game game); 
} 

लेकिन ध्यान रखें कि यह केवल एक उदाहरण है। यह अपेक्षा करता है कि वास्तविक प्रिंसिपल में isAdmin() विधि है और गेम में getOwner() विधि स्वामी के उपयोगकर्ता नाम लौटने की विधि है।

+0

यह समाधान वसंत बूट के साथ मुझे मदद की 1.3.3.RELEASE – ali

7

आप की तरह अपनी एनोटेशन कुछ लिख सकते हैं:

@PreAuthorize("hasRole('ROLE_ADMIN') and hasPermission(#id, 'Game', 'DELETE')") 

hasPermission काम कर आप PermissionEvaluator इंटरफ़ेस को लागू करने की जरूरत है हिस्सा पाने के लिए।

फिर एक अभिव्यक्ति हैंडलर सेम को परिभाषित:

@Autowired 
private PermissionEvaluator permissionEvaluator; 

@Bean 
public DefaultMethodSecurityExpressionHandler expressionHandler() 
{ 
    DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler(); 
    handler.setPermissionEvaluator(permissionEvaluator); 
    return handler; 
} 

और अपनी सुरक्षा config में इंजेक्षन:

<global-method-security pre-post-annotations="enabled"> 
    <expression-handler ref="expressionHandler" /> 
</global-method-security> 
30

@PreAuthorize के बाद से SpEl -expressions मूल्यांकन करता है, सबसे आसान तरीका है एक सेम को इंगित करने के लिए बस है:

@PreAuthorize("@mySecurityService.someFunction()") 

MySecurityService.someFunction चाहिए वापसी प्रकार boolean है।

यदि आप Authentication -object पास करना चाहते हैं तो स्प्रिंग-सुरक्षा स्वचालित रूप से authentication नामक एक चर प्रदान करेगा। आप अपने सुरक्षित विधि के लिए पारित किसी भी तर्क का उपयोग करने के लिए किसी भी वैध स्पेल-भाव का उपयोग कर सकते नियमित अभिव्यक्ति का मूल्यांकन, स्थिर तरीकों फोन, आदि उदाहरण के लिए:

@PreAuthorize("@mySecurityService.someFunction(authentication, #someParam)") 
+0

यह मेरे लिए एक अच्छा समाधान की तरह लगता है। आप कई @ कॉम्पोनेंट्स बना सकते हैं जिनमें आपका कस्टमाइज्ड प्राधिकरण कोड शामिल है जिसे एंडपॉइंट्स में फिर से उपयोग किया जा सकता है – ashario

संबंधित मुद्दे