2016-06-28 27 views
6

में OAuth एक्सेस टोकन की सेवा करने की रणनीति मेरे पास एक Redux ऐप और एक दूरस्थ API है जो OAuth सर्वर के रूप में कार्य करता है। सामान्य दिनचर्या के आधार पर, उपयोगकर्ता अपने क्रेडेंशियल्स को एक टोकन में बदल देता है जिसे तब ऐप द्वारा डेटा लाने और सर्वर पर कुछ सामान करने के लिए उपयोग किया जाता है। यह टोकन स्टोर में संग्रहीत है और sessionStorage में भी संग्रहीत है।Redux अनुप्रयोग

अब, कभी-कभी एक्सेस टोकन समाप्त हो जाएगा, लेकिन चूंकि रीफ्रेश टोकन प्राप्त हो गया है, इसलिए पहले रीफ्रेश करने का प्रयास करना बेहतर है, और केवल तभी गलत होने पर उपयोगकर्ता को साइन आउट करें।

मैं साइन-ऑफ भाग को पूरी तरह समझता हूं, जो तकनीकी रूप से केवल एक निश्चित कार्रवाई को प्रेषित करने का मतलब है। लेकिन मैं टोकन रिफ्रेशमेंट रूटीन को सरल कैसे बना सकता हूं?

मैंने रेडक्स-सागा की कोशिश की, लेकिन यह बहुत verbose है। मुझे सचमुच रिमोट एपीआई पर निर्भर प्रत्येक क्रिया के लिए कोड को आंशिक रूप से डुप्लिकेट करना है, यह सुनिश्चित करने के लिए कि प्रत्येक अनुरोध जैसे पहले पहुंच टोकन की जांच करे और क्या यह अभी तक समाप्त नहीं हुआ है, और इसे अन्यथा रीफ्रेश करने का प्रबंधन करें।

एक और चीज जो मैंने करने की कोशिश की वह एक मिडलवेयर है जो रिमोट एपीआई को वादा में लिपटे अनुरोध के साथ एक निश्चित प्रकार की कार्रवाई की अपेक्षा करेगा। इस तरह के काम, लेकिन अगर मैं करने का दूसरा तरीका है तो मैं उत्सुक हूं।

क्या किसी ने कभी भी इस (सुंदर जेनेरिक) चीज को लागू किया है? कोई विचार है कि टोकन रिफ्रेशमेंट को स्वचालित कैसे करें और कोड की बढ़ी हुई मात्रा के साथ पागल न हो? शायद उच्च आदेश घटक?

+1

एक समाधान के उत्तर देने के बावजूद, हर किसी को उनके विचार और अनुभव जोड़ने के लिए बहुत स्वागत है। –

उत्तर

9

कोड के लिए बार-बार होने की आवश्यकता होती है और कुछ ऐसी चीज के लिए जो निर्बाध और सामान्य हो, मध्यवर्ती आमतौर पर जाने का तरीका होता है। यह स्टोर बनाने के दौरान मिडलवेयर को शामिल करने और एक साधारण फ़ंक्शन लिखने के लिए कोड की दो पंक्तियों को जोड़ने के रूप में सरल हो सकता है जो आपके लिए टोकन तर्क को संभालेगा।

मान लीजिए कि आप इस तरह के रूप में अपने स्टोर बनाने होता है:

import { createStore, applyMiddleware, compose } from 'redux'; 
import rootReducer from './reducers'; 
import { browserHistory } from 'react-router'; 
import { routerMiddleware } from 'react-router-redux'; 
import tokenMiddleware from './middleware/token'; 

const finalCreateStore = compose(
    applyMiddleware(
     routerMiddleware(browserHistory), 
     tokenMiddleware, 
    ), 
    window.devToolsExtension ? window.devToolsExtension() : f => f, 
)(createStore); 

तो फिर तुम इस समारोह कहीं से, प्रारंभिक अवस्था के साथ कॉल करेगा।

const store = finalCreateStore(rootReducer, initialState); 

इससे आपको स्टोर के माध्यम से आने वाले सभी कार्यों के साथ कुछ करने में मदद मिलेगी। चूंकि ऐसा मिडलवेयर होना बहुत आम है जो वादे का उपयोग करके एपीआई कॉल को संभालता है, कुछ लोग इस उद्देश्य के लिए भी इसका पुन: उपयोग करना पसंद करते हैं और दोनों को एक साथ जोड़ते हैं।

एक ठेठ मिडलवेयर कुछ इस तरह दिखेगा:

export const tokenMiddleware = ({ dispatch, getState }) => next => action => { 
    if (typeof action === 'function') { // pass along 
     return action(dispatch, getState); 
    } 

    // so let's say you have a token that's about to expire 
    // and you would like to refresh it, let's write so pseudo code 

    const currentState = getState(); 
    const userObj = state.authentication.user; 

    if (userObj.token && userObj.token.aboutToExpire) { 
     const config = getSomeConfigs(); 
     // some date calculation based on expiry time that we set in configs 
     const now = new Date(); 
     const refreshThreshold = config.token.refreshThreshold; 

     if (aboutToExpireAndIsBelowThresholdToRefresh) { 
      // refreshTheToken can be an action creator 
      // from your auth module for example 
      // it should probably be a thunk so that you can handle 
      // an api call and a promise within once you get the new token 
      next(refreshTheToken(userObj, someOtherParams); 
     } 
    } 

    .... 

    return next(action); 
} 

आपका ताज़ा टोकन thunk इस के समान कुछ हो सकता है:

function refreshToken(user, maybeSomeOtherParams) { 
    const config = getSomeConfigs; 

    return dispatch => { 
     makeAPostCallWithParamsThatReturnsPromise 
     .then(result => dispatch(saveNewToken({ 
      result, 
      ... 
     }))) 
     .catch(error => dispatch({ 
      type: uh_oh_token_refresh_failed_action_type, 
      error, 
     })); 
}; 

एक अन्य विकल्प है कि आप संभवतः जा सकते हैं संभाल करने के लिए किया जाएगा के लिए यह मार्ग बदलते समय।

मान लें कि आपके पास उन मार्गों के लिए कहीं शीर्ष स्तर का मार्ग होगा, जिन्हें प्रमाणीकरण और सिस्टम में मौजूद एक वैध उपयोगकर्ता की आवश्यकता है। आइए उन्हें authenticated routes पर कॉल करें।

आप इन authenticated routes को शीर्ष स्तर के मार्ग के साथ लपेट सकते हैं, जो onChange हैंडलर फ़ंक्शन को परिभाषित करता है।कुछ इस तरह:

<Route onChange={authEntry}> 
    <Route ... /> // authenticated routes 
    <Route ... /> 
</Route> 

जब इन मार्गों को बनाने और अपनी दुकान की स्थापना, एक बार आप की दुकान को बनाया है, तो आप इस समारोह checkAuth कहा जाता है करने के लिए बाध्य कर सकता है।

const authEntry = checkAuth.bind(null, store) 

एक और तरीका है एक समारोह में मार्ग परिभाषाओं लपेट और इसे में दुकान गुजरती हैं, और फिर आप सिर्फ एक ही उपयोग कर सकते है जाएगा करने के लिए होगा, लेकिन मुझे लगता है कि के रूप में साफ नहीं हो पाया इस (व्यक्तिगत पसंद के रूप में)।

अब यह checkAuth क्या होगा?

कुछ इस तरह:

export function checkAuth (store, previous, next, replace, callback) { 
    const currentUser = store.getState().auth.user 

    // can possibly dispatch actions from here too 
    // store.dispatch(..).then(() => callback()).. 
    // so you could possibly refresh the token here using an API call 
    // if it is about to expire 

    // you can also check if the token did actually expire and/or 
    // there's no logged in user trying to access the route, so you can redirect 

    if (!currentUser || !isLoggedIn(currentUser)) { 
     replace('/yourLoginRouteHere') 
    } 

    callback() // pass it along 
} 

इन दोनों काफी सामान्य होना चाहिए ताकि वे एक केंद्रीकृत स्थान में फिर से प्रयोग करने योग्य कोड प्रदान करते हैं। आशा है कि आप इन सहायक पाएंगे।

+0

यदि कोई अन्य कार्य प्रेषित किया जाता है तो आप इस मिडलवेयर को टोकन रीफ्रेश न करने के लिए कैसे बनाते हैं? आइए ऐसा कुछ भी कहें जो नेटवर्क से संबंधित नहीं है या कुछ अन्य अनुरोध जिन्हें प्राधिकरण टोकन की आवश्यकता नहीं है –