2013-11-02 5 views
6

मैं ग्लासफ़िश सर्वर 4.0 का उपयोग कर रहा हूं जिसमें मैंने विभिन्न उपयोगकर्ताओं को विभिन्न अधिकारियों/भूमिकाएं सौंपी हैं।जेएएएस में उनके अधिकार/भूमिका के अनुसार प्रत्येक उपयोगकर्ता को किसी विशिष्ट स्थान पर संसाधनों का उपयोग कैसे करें?

उपयोगकर्ता के पास एकाधिक प्राधिकरण/भूमिकाएं हो सकती हैं। उदाहरण के लिए, एक व्यवस्थापक उपयोगकर्ता ROLE_ADMIN (व्यवस्थापकीय कार्यों को करने के लिए) और ROLE_USER (एक पंजीकृत उपयोगकर्ता के रूप में कार्य करने के लिए) से जुड़ा हो सकता है।

मेरे web.xml में, यह निम्नानुसार कॉन्फ़िगर किया गया है।

<security-constraint> 
    <display-name>AdminConstraint</display-name> 
    <web-resource-collection> 
     <web-resource-name>ROLE_ADMIN</web-resource-name> 
     <description/> 
     <url-pattern>/admin_side/*</url-pattern> 
    </web-resource-collection> 
    <auth-constraint> 
     <description/> 
     <role-name>ROLE_ADMIN</role-name> 
    </auth-constraint> 
    <user-data-constraint> 
     <description/> 
     <transport-guarantee>CONFIDENTIAL</transport-guarantee> 
    </user-data-constraint> 
</security-constraint> 

<security-constraint> 
    <display-name>UserConstraint</display-name> 
    <web-resource-collection> 
     <web-resource-name>ROLE_USER</web-resource-name> 
     <description/> 
     <url-pattern>/user_side/*</url-pattern> 
    </web-resource-collection> 
    <auth-constraint> 
     <description/> 
     <role-name>ROLE_USER</role-name> 
    </auth-constraint> 
    <user-data-constraint> 
     <description/> 
     <transport-guarantee>CONFIDENTIAL</transport-guarantee> 
    </user-data-constraint> 
</security-constraint> 

<login-config> 
    <!--<auth-method>DIGEST</auth-method>--> 
    <auth-method>FORM</auth-method> 
    <realm-name>projectRealm</realm-name> 
    <form-login-config> 
     <form-login-page>/utility/Login.jsf</form-login-page> 
     <form-error-page>/utility/ErrorPage.jsf</form-error-page> 
    </form-login-config> 
</login-config> 

<security-role> 
    <description/> 
    <role-name>ROLE_ADMIN</role-name> 
</security-role> 

<security-role> 
    <description/> 
    <role-name>ROLE_USER</role-name> 
</security-role> 

यह ठीक काम करता है।


दो URL प्रतिमानों /admin_side/* और /user_side/* रहे हैं। व्यवस्थापक के पास दो भूमिकाएं ROLE_ADMIN और ROLE_USER हैं।

जब व्यवस्थापक अधिकार ROLE_USER का उपयोग करने में लॉग करता है, केवल/user_side/* में स्थित संसाधनों एक्सेस किया जाना चाहिए। /admin_side/* में स्थित संसाधनों को एक्सेस करने से मना कर दिया जाना चाहिए क्योंकि व्यवस्थापक एक पंजीकृत उपयोगकर्ता के रूप में लॉग इन है, न कि व्यवस्थापक के रूप में।

अब तक मेरे मामले में क्या होता है यह है कि जब व्यवस्थापक किसी भी प्राधिकरण का उपयोग करने में लॉग इन करता है, तो दोनों स्थानों में संसाधनों का उपयोग किया जा सकता है जो पूरी तरह से अवैध है। ऐसा इसलिए है क्योंकि सिस्टम उस विशेष उपयोगकर्ता के लिए दोनों अधिकारियों को ढूंढने में सक्षम है।

प्रत्येक उपयोगकर्ता अपने अधिकार/भूमिका के अनुसार किसी विशिष्ट स्थान पर संसाधनों का उपयोग कैसे करें?


प्रमाणीकरण फिल्टर:

@WebFilter(filterName = "SecurityCheck", urlPatterns = {"/jass/*"}) 
public final class SecurityCheck implements Filter 
{ 
    private FilterConfig filterConfig = null; 

    @Resource(mappedName="jms/destinationFactory") 
    private ConnectionFactory connectionFactory; 
    @Resource(mappedName="jms/destination") 
    private Queue queue; 
    @EJB 
    private final UserBeanLocal userService=null; 

    public SecurityCheck() {} 

    private void sendJMSMessageToDestination(String message) throws JMSException 
    { 
     Connection connection = null; 
     Session session = null; 

     try 
     { 
      connection = connectionFactory.createConnection(); 
      session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); 
      MessageProducer messageProducer = session.createProducer(queue); 
      TextMessage textMessage = session.createTextMessage(); 
      textMessage.setText(message); 
      messageProducer.send(textMessage); 
     } 
     finally 
     { 
      if(session!=null){session.close();} 
      if(connection!=null){connection.close();} 
     } 
    } 

    private void doBeforeProcessing(ServletRequest request, ServletResponse response) throws IOException, ServletException 
    { 
     HttpServletRequest httpServletRequest=(HttpServletRequest)request; 
     httpServletRequest.login(httpServletRequest.getParameter("userName"), httpServletRequest.getParameter("password")); 
    } 

    private void doAfterProcessing(ServletRequest request, ServletResponse response) throws IOException, ServletException, JMSException 
    { 
     HttpServletRequest httpServletRequest=(HttpServletRequest)request; 
     HttpServletResponse httpServletResponse=(HttpServletResponse)response; 
     ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext(); 
     Map<String, Object> sessionMap = externalContext.getSessionMap(); 

     if(httpServletRequest.isUserInRole("ROLE_USER")) 
     { 
      sendJMSMessageToDestination(httpServletRequest.getLocalName()); 
      UserTable userTable = userService.setLastLogin(httpServletRequest.getParameter("userName")); 
      userTable.setPassword(null); 
      sessionMap.put("userName", userTable!=null?userTable.getFirstName():"Unknown"); 
      sessionMap.put("user", userTable); 

      httpServletResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); 
      httpServletResponse.setHeader("Pragma", "no-cache"); 
      httpServletResponse.setDateHeader("Expires", 0); 
      httpServletResponse.sendRedirect("../user_side/Home.jsf"); 
     } 
     else if(httpServletRequest.isUserInRole("ROLE_ADMIN")) 
     { 
      sendJMSMessageToDestination(httpServletRequest.getLocalName()); 
      UserTable userTable = userService.setLastLogin(httpServletRequest.getParameter("userName")); 
      userTable.setPassword(null); 
      sessionMap.put("adminName", userTable!=null?userTable.getFirstName():"Unknown"); 
      sessionMap.put("user", userTable); 

      httpServletResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); 
      httpServletResponse.setHeader("Pragma", "no-cache"); 
      httpServletResponse.setDateHeader("Expires", 0); 
      httpServletResponse.sendRedirect("../admin_side/Home.jsf"); 
     } 
    } 

    @Override 
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException 
    { 
     try 
     { 
      doBeforeProcessing(request, response); 
     } 
     catch (Exception e) 
     { 
      HttpServletResponse httpServletResponse=(HttpServletResponse)response; 
      //FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error", "Incorrect user name and/or password. Access denied.")); 
      httpServletResponse.sendRedirect("../utility/Login.jsf"); 
      return; 
     } 

     chain.doFilter(request, response); 

     try 
     { 
      doAfterProcessing(request, response); 
     } 
     catch (JMSException ex) 
     { 
      Logger.getLogger(SecurityCheck.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 

    //The rest of the filter. 
} 

आप तो अपने आवेदन में अन्य चीजों को देखने की जरूरत है, तो कृपया मुझे बताएं।

+0

आप एक पंजीकृत उपयोगकर्ता के रूप में व्यवस्थापक में कितनी लॉगिंग कर रहे हैं? यदि किसी विशेष उपयोगकर्ता के पास कई भूमिकाएं हैं, तो वास्तव में उनमें से केवल एक का उपयोग करके लॉगिन करने का कोई तरीका नहीं है। तो पूरा सवाल उलझन में है। – BalusC

+0

यह एक फ़िल्टर है जो उपयोगकर्ताओं को प्रमाणित करता है। फ़िल्टर को यूआरएल पटर में मैप किया गया है - '/ jass/*' (गलती से टाइप किया गया, '/ jaas/* 'होना चाहिए था)। यह एक निर्देशिका इंगित करता है जिसमें केवल एक पृष्ठ है- 'temp.jsp' जहां अनुरोध भेजा जाता है, जब जेएसएफ पृष्ठ पर लॉगिन बटन दबाया जाता है (इसके संबंधित जेएसएफ प्रबंधित बीन के माध्यम से)। क्या व्यवस्थापक के रूप में एक बार लॉग इन करने का कोई तरीका नहीं है और एक बार उपयोगकर्ता के समान आईडी/पासवर्ड का उपयोग करने का कोई तरीका नहीं है? मुझे ऐसा भी लगा लेकिन सोचा कि कंटेनर ऐसा करने के लिए कुछ तंत्र का समर्थन कर सकता है। मैंने कुछ ट्यूटोरियल में देखा लेकिन इसके बारे में कुछ भी नहीं मिला। – Tiny

उत्तर

1

आपको लगता है कि जब उपयोगकर्ता के पास कई भूमिकाएं होती हैं, तो यह उपयोगकर्ता एक साथ उन भूमिकाओं में से केवल एक का उपयोग करके लॉगिन कर सकता है। यह सच नहीं है। उपयोगकर्ता प्रति-भूमिका के आधार पर लॉग इन नहीं हैं। उपयोगकर्ता प्रति उपयोगकर्ता आधार पर लॉग इन हैं। यदि किसी उपयोगकर्ता के पास कई भूमिकाएं हैं, तो वे सभी पूरे लॉगिन सत्र में उपयोग और लागू होंगे।

असल में, यह नहीं है जिससे उपयोगकर्ता पूरे सत्र में केवल एक निर्दिष्ट भूमिकाओं को चुनने और उपयोग करने के लिए संभव हो। अब तक यह बहुत अधिक लगता है कि आपके व्यवस्थापक को पहले स्थान पर ROLE_USER नहीं होना चाहिए। लेकिन यह वास्तविक दुनिया में थोड़ा सा अर्थ बनाता है। भूमिकाओं को मौजूदा भूमिकाओं को "विस्तारित" नहीं करना चाहिए। अर्थात। ROLE_ADMIN को उसी प्रतिबंध को ROLE_USER के रूप में कॉपी नहीं करना चाहिए और उसके बाद कुछ और जोड़ें। नहीं, इसे पूरी तरह से बिल्कुल प्रतिनिधित्व करना चाहिए कि "कुछ और"। व्यवस्थापक उपयोगकर्ताओं को तब दोनों भूमिकाएं नियुक्त की जाती हैं (आपने वह हिस्सा सही ढंग से किया था)।अन्यथा आप उन कोडों पर कोड के दौरान डुप्लिकेट चेक के साथ समाप्त होते हैं जिन्हें उपयोगकर्ता और व्यवस्थापक दोनों द्वारा एक्सेस/उपयोग किया जा सकता है। और फिर मैं इस पर एक तीसरी भूमिका के बारे में बात नहीं कर रहा हूं जिसके लिए कोड में ट्रिपल चेक की आवश्यकता हो सकती है। आपको मौजूदा स्थान को सभी जगहों पर संपादित करना होगा।

यदि आप रनटाइम के दौरान प्रोग्रामेटिक रूप से भूमिकाओं को टॉगल करना चाहते हैं, तो शायद आप नियमित उपयोगकर्ता के रूप में साइट को "पूर्वावलोकन" करने में सक्षम होना चाहते हैं (उदाहरण के लिए यह जांचें कि साइट कैसा दिखता है जब व्यवस्थापक-केवल अनुभाग/बटन होते हैं

  1. सत्र विशेषता के रूप में कुछ ध्वज सेट या शायद अनुरोध पैरामीटर के रूप में और उस पर कोड की जांच हो: छिपा), तो वहाँ मूल रूप से दो विकल्प हैं। जैसे

    <h:form> 
        <h:selectBooleanCheckbox value="#{sessionScope.preview}"> 
         <f:ajax render="@all" /> 
        </h:selectBooleanCheckbox> 
    </h:form> 
    

    (ध्यान दें: के रूप में किया जाता है, #{sessionScope} एक अंतर्निहित ईएल चर ExternalContext#getSessionMap() जिक्र है कोड है, कोई अतिरिक्त समर्थन सेम आवश्यक)

    और फिर मास्टर tamplate में:

    <c:set var="userIsAdmin" value="#{request.isUserInRole('ROLE_ADMIN') and not preview}" scope="request" /> 
    

    और कुछ व्यवस्थापक विशिष्ट सामग्री वाले लक्षित विचारों में:

    <h:commandButton value="Some awesome admin button" rendered="#{userIsAdmin}" /> 
    

  2. नियमित उपयोगकर्ता के रूप में प्रोग्रामेटिक लॉगिन करें। कंटेनर प्रबंधित प्रमाणीकरण को प्रोग्रामेटिक रूप से ट्रिगर करने के लिए आप HttpServletRequest#login() का उपयोग कर सकते हैं। इस तरह एक व्यवस्थापक एक अलग उपयोगकर्ता का "प्रतिरूपण" कर सकता है और साइट ब्राउज़ कर सकता है जैसे कि वह विशेष उपयोगकर्ता के रूप में लॉग-इन है। जैसे

    public void runAs(User user) { 
        // ... 
        try { 
         request.login(user.getUsername(), user.getPassword()); 
         originalUser = currentUser; 
         currentUser = user; 
         // ... 
        } catch (ServletException e) { 
         // ... 
        } 
    } 
    
    public void releaseRunAs() { 
        // ... 
        try { 
         request.login(originalUser.getUsername(), originalUser.getPassword()); 
         currentUser = originalUser; 
         // ... 
        } catch (ServletException e) { 
         // ... 
        } 
    } 
    

    तुम भी (, में पिछले बाहर पिछले) एक लिलो में सभी पिछले उपयोगकर्ताओं पकड़ कर यह विस्तार कर सकते हैं सत्र दायरे में कतार: एक सत्र में सेम scoped। इसके लिए अपाचे शिरो जैसे अधिकांश सुरक्षा ढांचे में builtin APIs है।

+0

मैं वर्तमान में जटिलता में अनावश्यक रूप से जाने के बजाय "* प्रति उपयोगकर्ता आधार *" विधि पर चिपक जाता हूं। मुख्य रूप से, मैं जानना चाहता था कि यह कंटेनर द्वारा समर्थित है, बॉक्स के बाहर जिसके लिए मैं ओरेकल दस्तावेजों को आगे और पीछे फिसलने से पूरी तरह से थक गया था :) अब मैंने अपना बड़ा संदेह हटा दिया है। धन्यवाद। – Tiny

1

मुझे लगता है कि होने के लिए आपने जो व्यवहार किया है, उसे बहुत सावधान के साथ बहुत सावधान रहें, शायद इसके बजाय एक और व्यवस्थापक खाता जोड़ें और उस खाते से ROLE_USER को हटा दें।

+0

इस सवाल से पूछने से पहले, मैंने यह भी सोचा कि यह केवल इस प्रश्न का उत्तर होगा :)। ऐसा करने पर, हम यह नहीं कह सकते कि एक उपयोगकर्ता के पास कई प्राधिकरण/भूमिकाएं हो सकती हैं क्योंकि उपयोगकर्ता को एकाधिक अधिकारियों/भूमिकाओं के अनुरूप कई खाते होने की आवश्यकता होती है। हालांकि एक उपयोगकर्ता के पास विभिन्न प्राधिकरण/भूमिकाओं के साथ कई खाते हो सकते हैं, ** वे सभी सिस्टम ** ** द्वारा अलग-अलग उपयोगकर्ताओं के रूप में माना जाता है। – Tiny

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