2016-08-23 12 views
19

मैं रेडक्स के साथ प्रतिक्रिया और प्रतिक्रिया राउटर के साथ वेबसाइट बना रहा हूं। । मार्गों (पृष्ठों) के बहुत सारे में लॉग इन करने की आवश्यकता है मैं के लिए लॉग इन रीडायरेक्ट कर सकते हैं, तो उपयोगकर्ता इस तरह प्रवेश न होने पर:रिएक्ट राउटर पर, राज्य में लॉग इन कैसे रहें पृष्ठ को रीफ्रेश करें?

function requireAuth(nextState, replace) { 
    let loggedIn = store.getState().AppReducer.UserReducer.loggedIn; 

    if(!loggedIn) { 
     replace({ 
      pathname: '/login', 
      state: { 
       nextpathname: nextState.location.pathname 
      } 
     }); 
    } 
} 

ReactDOM.render(
    <Provider store={store}> 
     <Router history={history}> 
      <Route path="/" component={App}> 
       <IndexRoute component={Index} /> 
       <Route path="login" component={Login} /> 
       <Route path="register" component={Register} /> 
       <Route path="dashboard" component={Graph} onEnter={requireAuth}> 
        ... some other route requires logged in ... 
       </Route> 
      </Route> 
     </Router> 
    </Provider>, 
    document.getElementById('entry') 
); 

कृपया कोड देखते हैं, मैं करने के लिए '/ लॉग इन' मार्ग यदि उपयोगकर्ता रीडायरेक्ट करने के लिए हुक onEnter इस्तेमाल किया लॉग इन नहीं किया गया है। उपयोगकर्ता लॉग इन करने के लिए डेटा स्टोर में है, और यह उपयोगकर्ता लॉग इन करने के बाद अपडेट होगा।

यह पूरी तरह से काम कर रहा है, लेकिन समस्या तब होती है जब मैं पृष्ठ को रीफ्रेश करता हूं, स्टोर रीसेट हो जाएगा और उपयोगकर्ता नहीं होगा राज्य में वापस लॉग इन करें।

मुझे पता है ऐसा इसलिए होता है क्योंकि रेडक्स स्टोर केवल मेमोरी स्टोरेज है, इसलिए रीफेश पेज सभी डेटा खो देगा।

प्रत्येक रीफ्रेश पर सर्वर सत्र की जांच करें, लेकिन यह बहुत अधिक अनुरोध हो सकता है, इसलिए यह बुरा विचार दिखता है।

लॉग इन किए गए राज्य डेटा को स्थानीय स्टोरेज में सहेजें, लेकिन इस मामले में, मुझे यह जांचना चाहिए कि प्रत्येक AJAX कॉल विफल हो गई है क्योंकि अनुरोध अस्वीकार कर दिया गया है क्योंकि सत्र समाप्त हो गया है या किसी चीज़ की तरह मौजूद नहीं है, और यह भी बुरा विचार दिखता है।

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

किसी भी सलाह की बहुत सराहना की जाएगी।

उत्तर

24

जाने का एक और तरीका है JSON Web Tokens (JWT) जो प्रत्येक मार्ग के लिए आवश्यक है, और localStorage जेडब्ल्यूटी की जांच के लिए आवश्यक है।

टी एल; डॉ

  • सामने के छोर पर आप एक साइन-इन और साइन अप मार्ग कि सर्वर पर प्रमाणीकरण के अनुसार एक जेडब्ल्यूटी के लिए अपने सर्वर क्वेरी करता है। एक बार उचित जेडब्ल्यूटी पास कर दिया तो आप राज्य की संपत्ति पर सेट कर देंगे। आपके पास एक साइनआउट रूट हो सकता है जो उपयोगकर्ता को स्थिति को गलत पर सेट करने की अनुमति देता है।

  • index.js जो अपने मार्गों, प्रतिपादन से पहले स्थानीय भंडारण जांच कर सकते हैं इस प्रकार ताज़ा करने पर राज्य खोने लेकिन कुछ सुरक्षा रखने के साथ आपकी समस्या को दूर करने में शामिल है।

  • सभी अपने आवेदन में प्रमाणीकरण की आवश्यकता मार्गों एक रचना घटक के माध्यम से प्रदान की गई , और सर्वर एपीआई पर प्राधिकरण के लिए शीर्ष लेख में होने JWTs की आवश्यकता के साथ सुरक्षित हैं।

इसे सेट अप करने में थोड़ा समय लगता है लेकिन यह आपके एप्लिकेशन को 'उचित' सुरक्षित बनाएगा।


अपनी समस्या को हल करने के लिए: जैसा कि नीचे दिखाया, यदि आवश्यक हो प्रमाणीकृत करने के लिए राज्य को अद्यतन करने

अपने index.js फ़ाइल में मार्गों से पहले स्थानीय भंडारण की जाँच करें।

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

इस प्रकार मार्गों में आप कुछ इस तरह होगा:

import React from 'react'; 
import ReactDOM from 'react-dom'; 
import { Provider } from 'react-redux'; 
import { createStore, applyMiddleware, compose } from 'redux'; 
import { Router, Route, browserHistory, IndexRoute } from 'react-router'; 
import reduxThunk from 'redux-thunk'; 
import { AUTHENTICATE_THE_USER } from './actions/types'; 
import RequireAuth from './components/auth/require_auth'; 
import reducers from './reducers'; 

/* ...import necessary components */ 

const createStoreWithMiddleware = compose(applyMiddleware(reduxThunk))(createStore); 

const store = createStoreWithMiddleware(reducers); 

/* ... */ 

// Check for token and update application state if required 
const token = localStorage.getItem('token'); 
if (token) { 
    store.dispatch({ type: AUTHENTICATE_THE_USER }); 
} 

/* ... */ 

ReactDOM.render(
    <Provider store={store}> 
    <Router history={history}> 
     <Route path="/" component={App}> 
     <IndexRoute component={Index} /> 
     <Route path="login" component={Login} /> 
     <Route path="register" component={Register} /> 
     <Route path="dashboard" component={RequireAuth{Graph}} /> 
     <Route path="isauthenticated" component={RequireAuth(IsAuthenticated)} /> 
     ... some other route requires logged in ... 
     </Route> 
    </Router> 
    </Provider> 
    , .getElementById('entry')); 

RequiredAuth रचना घटक Graph और IsAuthenticated (उचित नाम घटकों के किसी भी संख्या हो सकता है), जबकि है

index.js

सत्य होने के लिए state.authenticated की आवश्यकता है।

घटक, इस मामले में Graph और IsAuthenticated प्रस्तुत किया गया है यदि state.authenticated सत्य है। अन्यथा रूट रूट पर वापस डिफ़ॉल्ट है।


फिर आप इस तरह के एक रचनाकृत घटक का निर्माण कर सकते हैं, जिसके माध्यम से आपके सभी मार्ग प्रदान किए जाते हैं। यह जांच करेगा कि जिस स्थिति में आप धारण कर रहे हैं, उपयोगकर्ता को प्रमाणीकृत किया गया है या नहीं (बूलियन) प्रतिपादन से पहले सच है।

require_auth.js

import React, { Component } from 'react'; 
import { connect } from 'react-redux'; 

export default function (ComposedComponent) { 

    // If user not authenticated render out to root 

    class Authentication extends Component { 
    static contextTypes = { 
     router: React.PropTypes.object 
    }; 

    componentWillMount() { 
     if (!this.props.authenticated) { 
     this.context.router.push('/'); 
     } 
    } 

    componentWillUpdate(nextProps) { 
     if (!nextProps.authenticated) { 
     this.context.router.push('/'); 
     } 
    } 

    render() { 
     return <ComposedComponent {...this.props} />; 
    } 
    } 

    function mapStateToProps(state) { 
    return { authenticated: state.authenticated }; 
    } 

    return connect(mapStateToProps)(Authentication); 
} 

साइनअप/साइन-इन की ओर आप ने एक ऐसी कार्रवाई जेडब्ल्यूटी संग्रहीत करता है और राज्य एक कार्रवाई-निर्माता के माध्यम से प्रमाणीकृत करने के लिए सेट बना सकते हैं पर -> redux दुकान । Async HTTP अनुरोध प्रतिक्रिया चक्र चलाने के लिए यह उदाहरण makes use of axios

export function signinUser({ email, password }) { 

    // Note using the npm package 'redux-thunk' 
    // giving direct access to the dispatch method 
    return function (dispatch) { 

    // Submit email and password to server 
    axios.post(`${API_URL}/signin`, { email, password }) 
     .then(response => { 
     // If request is good update state - user is authenticated 
     dispatch({ type: AUTHENTICATE_THE_USER }); 

     // - Save the JWT in localStorage 
     localStorage.setItem('token', response.data.token); 

     // - redirect to the route '/isauthenticated' 
     browserHistory.push('/isauthenticated'); 
     }) 
     .catch(() => { 
     // If request is bad show an error to the user 
     dispatch(authenticationError('Incorrect email or password!')); 
     }); 
    }; 
} 

आप भी अपनी दुकान (इस मामले में Redux) और निश्चित रूप से कार्रवाई निर्माता स्थापित करने के लिए की आवश्यकता होगी।

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

सर्वर एपीआई पर उपयोगकर्ताओं के लिए जेडब्ल्यूटी बनाना और पार्स करना एक और कदम है। I have found passport to be effective.

+0

आपके उदाहरण में IsAuthenticated composedComponent है, है ना? – klode

+0

'RequiredAuth' रचनाकृत घटक है जबकि' IsAuthenticated' उचित नामित घटकों की संख्या हो सकती है जिसके लिए 'state.authenticated' सत्य होना आवश्यक है। उत्तर अपडेट किया गया। – alexi2

+0

धन्यवाद, नया संपादन अधिक स्पष्ट है। – klode

1

लॉग इन स्थिति और समाप्ति तिथि के साथ sessionStorage का उपयोग क्यों नहीं कर रहे हैं? सत्रस्थान स्थिति की जांच के लिए आपको और कोड लिखना होगा, लेकिन मेरी राय में यह एकमात्र तरीका है कि आप एक्सएचआर कॉल को भेजने से बचा सकते हैं।

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