java - वसंत के माध्यम से विश्वसनीय प्रमाणीकरण




rest spring-mvc (3)

मुसीबत:
हमारे पास स्प्रिंग एमवीसी-आधारित रीस्टफुल एपीआई है जिसमें संवेदनशील जानकारी है। एपीआई सुरक्षित होना चाहिए, हालांकि प्रत्येक अनुरोध के साथ उपयोगकर्ता के प्रमाण पत्र (उपयोगकर्ता / पास कॉम्बो) भेजना वांछनीय नहीं है। प्रति आरईएसटी दिशानिर्देश (और आंतरिक व्यापार आवश्यकताओं), सर्वर को स्टेटलेस रहना चाहिए। एपीआई एक मैशप-शैली दृष्टिकोण में किसी अन्य सर्वर द्वारा उपभोग किया जाएगा।

आवश्यकताएँ:

  • ग्राहक प्रमाण पत्र के साथ .../authenticate (असुरक्षित यूआरएल) का अनुरोध करता है; सर्वर एक सुरक्षित टोकन देता है जिसमें सर्वर के लिए भविष्य के अनुरोधों को सत्यापित करने और स्टेटलेस बने रहने के लिए पर्याप्त जानकारी होती है। इसमें स्प्रिंग सिक्योरिटीज याद-मी टोकन जैसी ही जानकारी होगी।

  • क्लाइंट विभिन्न (संरक्षित) यूआरएल के बाद के अनुरोध करता है, पहले प्राप्त टोकन को एक क्वेरी पैरामीटर (या, कम वांछनीय रूप से, HTTP अनुरोध शीर्षलेख) के रूप में जोड़ना।

  • कुकीज़ को स्टोर करने की अपेक्षा नहीं की जा सकती है।

  • चूंकि हम पहले से ही वसंत का उपयोग करते हैं, समाधान को वसंत सुरक्षा का उपयोग करना चाहिए।

हम इस काम को करने की कोशिश कर रहे दीवार के खिलाफ हमारे सिर को टक्कर दे रहे हैं, इसलिए उम्मीद है कि वहां से कोई भी इस समस्या को हल कर चुका है।

उपर्युक्त परिदृश्य को देखते हुए, आप इस विशेष आवश्यकता को कैसे हल कर सकते हैं?


आप डाइजेस्ट एक्सेस प्रमाणीकरण पर विचार कर सकते हैं। अनिवार्य रूप से प्रोटोकॉल निम्नानुसार है:

  1. अनुरोध ग्राहक से किया गया है
  2. सर्वर एक अद्वितीय nonce स्ट्रिंग के साथ प्रतिक्रिया करता है
  3. ग्राहक एक उपयोगकर्ता नाम और पासवर्ड (और कुछ अन्य मूल्य) प्रदान करता है md5 nonce के साथ धोया; इस हैश को HA1 के रूप में जाना जाता है
  4. सर्वर तब ग्राहक की पहचान सत्यापित करने और अनुरोधित सामग्री को पूरा करने में सक्षम है
  5. गैर-संचार के साथ संचार तब तक जारी रह सकता है जब तक कि सर्वर एक नया नॉन प्रदान करता है (एक काउंटर का उपयोग रीप्ले हमलों को खत्म करने के लिए किया जाता है)

यह सब संचार हेडर के माध्यम से किया जाता है, जो कि jmort253 बिंदुओं के रूप में, आमतौर पर यूआरएल पैरामीटर में संवेदनशील सामग्री को संप्रेषित करने से अधिक सुरक्षित है।

डायजेस्ट एक्सेस प्रमाणीकरण स्प्रिंग सिक्योरिटी द्वारा समर्थित है। ध्यान दें कि, हालांकि दस्तावेज़ कहते हैं कि आपके पास अपने क्लाइंट के सादा-पाठ पासवर्ड तक पहुंच होनी चाहिए, यदि आपके क्लाइंट के लिए HA1 हैश है तो आप सफलतापूर्वक प्रमाणित कर सकते हैं।


आप JSON WebTokens के साथ OAuth का उपयोग क्यों शुरू नहीं करते हैं

http://projects.spring.io/spring-security-oauth/

OAuth2 एक मानकीकृत प्राधिकरण प्रोटोकॉल / ढांचा है। आधिकारिक OAuth2 Specification अनुसार:

आप here अधिक जानकारी पा सकते हैं


हमने ओपी में वर्णित यह काम करने में कामयाब रहे, और उम्मीद है कि कोई और समाधान का उपयोग कर सकता है। यहां हमने जो किया है:

सुरक्षा संदर्भ सेट करें जैसे:

<security:http realm="Protected API" use-expressions="true" auto-config="false" create-session="stateless" entry-point-ref="CustomAuthenticationEntryPoint">
    <security:custom-filter ref="authenticationTokenProcessingFilter" position="FORM_LOGIN_FILTER" />
    <security:intercept-url pattern="/authenticate" access="permitAll"/>
    <security:intercept-url pattern="/**" access="isAuthenticated()" />
</security:http>

<bean id="CustomAuthenticationEntryPoint"
    class="com.demo.api.support.spring.CustomAuthenticationEntryPoint" />

<bean id="authenticationTokenProcessingFilter"
    class="com.demo.api.support.spring.AuthenticationTokenProcessingFilter" >
    <constructor-arg ref="authenticationManager" />
</bean>

जैसा कि आप देख सकते हैं, हमने एक कस्टम AuthenticationEntryPoint बनाया है, जो मूल रूप से केवल 401 Unauthorized लौटाता है यदि अनुरोध हमारे AuthenticationTokenProcessingFilter फ़िल्टर द्वारा फ़िल्टर श्रृंखला में प्रमाणीकृत नहीं किया गया था।

कस्टम प्रमाणीकरण एंटरपॉइंट :

public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException authException) throws IOException, ServletException {
        response.sendError( HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized: Authentication token was either missing or invalid." );
    }
}

प्रमाणीकरण टोकनप्रोसेसिंग फ़िल्टर :

public class AuthenticationTokenProcessingFilter extends GenericFilterBean {

    @Autowired UserService userService;
    @Autowired TokenUtils tokenUtils;
    AuthenticationManager authManager;

    public AuthenticationTokenProcessingFilter(AuthenticationManager authManager) {
        this.authManager = authManager;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        @SuppressWarnings("unchecked")
        Map<String, String[]> parms = request.getParameterMap();

        if(parms.containsKey("token")) {
            String token = parms.get("token")[0]; // grab the first "token" parameter

            // validate the token
            if (tokenUtils.validate(token)) {
                // determine the user based on the (already validated) token
                UserDetails userDetails = tokenUtils.getUserFromToken(token);
                // build an Authentication object with the user's info
                UsernamePasswordAuthenticationToken authentication = 
                        new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails((HttpServletRequest) request));
                // set the authentication into the SecurityContext
                SecurityContextHolder.getContext().setAuthentication(authManager.authenticate(authentication));         
            }
        }
        // continue thru the filter chain
        chain.doFilter(request, response);
    }
}

जाहिर है, TokenUtils में कुछ गोपनीय (और बहुत मामला-विशिष्ट) कोड शामिल है और इसे आसानी से साझा नहीं किया जा सकता है। यहां इसका इंटरफ़ेस है:

public interface TokenUtils {
    String getToken(UserDetails userDetails);
    String getToken(UserDetails userDetails, Long expiration);
    boolean validate(String token);
    UserDetails getUserFromToken(String token);
}

यह आपको अच्छी शुरूआत में ले जाना चाहिए। हैप्पी कोडिंग :)





spring-security