प्रतिक्रिया-राउटर में मार्गों तक पहुंच कैसे प्रतिबंधित करें?


83

क्या किसी को पता है कि प्रतिक्रिया-राउटर में विशेष मार्गों तक पहुंच कैसे प्रतिबंधित करें? मैं जांचना चाहता हूं कि उपयोगकर्ता किसी विशेष मार्ग तक पहुंचने से पहले लॉग इन है या नहीं। मैंने सोचा कि यह सरल होगा, लेकिन डॉक्स स्पष्ट नहीं हैं कि यह कैसे करना है।

क्या यह कुछ है जिसे मुझे अपने <Route>घटकों को परिभाषित करना चाहिए, या मुझे अपने घटक संचालकों के अंदर इसे संभालना चाहिए?

<Route handler={App} path="/">
  <NotFoundRoute handler={NotFound} name="not-found"/>
  <DefaultRoute handler={Login} name="login"/>
  <Route handler={Todos} name="todos"/> {/* I want this to be restricted */}
</Route>

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

@ टान्नर सेमरड क्या आपके पास कोई गितुब भंडार है जिसके बारे में आपने इसे संक्षेप में प्राप्त किया है।
जीट

@ मैं नहीं माफी चाहता हूँ। नीचे माइकक का जवाब था, जो मुझे चाहिए था, लेकिन ध्यान रखें कि यह प्रतिक्रिया-राउटर 1.0 से पहले था। मुझे पता है कि 1.0 जारी होने के बाद से कई चीजें बदल गई हैं, लेकिन यह ज्यादातर समान है।
टान्नर सेमराद

@ jayair का जवाब है कि मैं अब क्या उपयोग कर रहा हूं, और यह महान काम करता है
Tanner Semerad

जवाबों:


94

अपडेट (अगस्त 16, 2019)

प्रतिक्रिया-राउटर v4 और रिएक्ट हुक का उपयोग करने में यह थोड़ा अलग दिखता है। चलो अपने साथ शुरू करते हैं App.js

export default function App() {
  const [isAuthenticated, userHasAuthenticated] = useState(false);

  useEffect(() => {
    onLoad();
  }, []);

  async function onLoad() {
    try {
      await Auth.currentSession();
      userHasAuthenticated(true);
    } catch (e) {
      alert(e);
    }
  }

  return (
    <div className="App container">
      <h1>Welcome to my app</h1>
      <Switch>
        <UnauthenticatedRoute
          path="/login"
          component={Login}
          appProps={{ isAuthenticated }}
        />
        <AuthenticatedRoute
          path="/todos"
          component={Todos}
          appProps={{ isAuthenticated }}
        />
        <Route component={NotFound} />
      </Switch>
    </div>
  );
}

Authयदि उपयोगकर्ता वर्तमान में प्रमाणित है, तो हम यह जांचने के लिए लाइब्रेरी का उपयोग कर रहे हैं । इसे अपने ऑर्टिकल चेक फंक्शन से बदलें। यदि ऐसा है तो हम isAuthenticatedध्वज को स्थापित करते हैं true। हम ऐसा तब करते हैं जब हमारा ऐप पहले लोड होता है। यह भी उल्लेख के लायक है, आप अपने ऐप पर एक लोडिंग साइन जोड़ना चाहते हैं, जबकि दूसरा चेक रन किया जा रहा है, इसलिए जब भी आप पेज को रिफ्रेश करते हैं, तो आप हर बार लॉगिन पेज को फ्लैश नहीं करते हैं।

फिर हम ध्वज को अपने मार्गों से पास करते हैं। हम दो प्रकार के मार्ग बनाते हैं AuthenticatedRouteऔर UnauthenticatedRoute

इस AuthenticatedRoute.jsतरह दिखता है।

export default function AuthenticatedRoute({ component: C, appProps, ...rest }) {
  return (
    <Route
      {...rest}
      render={props =>
        appProps.isAuthenticated
          ? <C {...props} {...appProps} />
          : <Redirect
              to={`/login?redirect=${props.location.pathname}${props.location.search}`}
            />}
    />
  );
}

यह जाँच करता है कि isAuthenticatedक्या सेट किया गया है true। यदि यह है, तो यह वांछित घटक को प्रस्तुत करेगा। यदि नहीं, तो यह लॉगिन पृष्ठ पर रीडायरेक्ट करेगा।

UnauthenticatedRoute.jsदूसरी ओर इस तरह दिखता है।

export default ({ component: C, appProps, ...rest }) =>
  <Route
    {...rest}
    render={props =>
      !appProps.isAuthenticated
        ? <C {...props} {...appProps} />
        : <Redirect to="/" />}
  />;

इस स्थिति में, यदि isAuthenticatedइसे सेट किया जाता है false, तो यह वांछित घटक प्रदान करेगा। और अगर यह सच है, तो यह आपको मुखपृष्ठ पर भेज देगा।

इसके विस्तृत संस्करण आप हमारे गाइड - https://serverless-stack.com/chapters/create-a-route-that-redirects.html पर पा सकते हैं ।

पुराना संस्करण

स्वीकृत उत्तर सही है लेकिन मिक्सिंस को रिएक्ट टीम द्वारा हानिकारक ( https://facebook.github.io/react/blog/2016/07/13/mixins-considered-harmful.html ) माना जाता है ।

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

यहां एचओसी का एक उदाहरण है जो जांच करेगा कि उपयोगकर्ता आगे बढ़ने से पहले लॉग इन है या नहीं। और अगर उपयोगकर्ता लॉग इन नहीं है, तो यह आपको लॉगिन पेज पर रीडायरेक्ट करेगा। यह घटक एक प्रोप नाम से लेता है isLoggedIn, जो मूल रूप से एक ध्वज है जिसे उपयोगकर्ता द्वारा लॉग इन करने पर आपका एप्लिकेशन यह दर्शाने के लिए स्टोर कर सकता है।

import React from 'react';
import { withRouter } from 'react-router';

export default function requireAuth(Component) {

  class AuthenticatedComponent extends React.Component {

    componentWillMount() {
      this.checkAuth();
    }

    checkAuth() {
      if ( ! this.props.isLoggedIn) {
        const location = this.props.location;
        const redirect = location.pathname + location.search;

        this.props.router.push(`/login?redirect=${redirect}`);
      }
    }

    render() {
      return this.props.isLoggedIn
        ? <Component { ...this.props } />
        : null;
    }

  }

  return withRouter(AuthenticatedComponent);
}

और इस HOC का उपयोग करने के लिए, बस इसे अपने मार्गों के चारों ओर लपेटें। आपके उदाहरण के मामले में, यह होगा:

<Route handler={requireAuth(Todos)} name="todos"/>

मैं इस और कुछ अन्य विषयों को एक विस्तृत चरण-दर-चरण ट्यूटोरियल में शामिल करता हूं - https://serverless-stack.com/chapters/create-a-hoc-that-checks-auth.html


यदि मेरा मूल कोड <मार्ग getComponent = {myAsyncComponentGenerator}> का उपयोग कर रहा था, तो मैं इसे इस उदाहरण के साथ कैसे काम करूंगा?
ब्रान

मेरे पास बहुत समान कोड है, लेकिन मेरा सवाल यह है कि क्या पर्याप्त सुरक्षित है? मेरा मतलब है कि एक हमलावर JS मिनिफ़ाइड कोड को बदल सकता है जैसे कि लॉगिन के this.props.isLoggedInसाथ trueऔर बायपास लॉगिन?
करीम इलाहलवी

4
@karimelhelawy यह सच है और इसकी वजह से आपको अपने सर्वर के एपीआई में प्रमाणीकरण लागू करना होगा।
cbr

7
<Route handler={}/>v1.0 में पदावनत है, आपको उपयोग करना चाहिए <Route component={} />
ज्ञान

1
componentWillMountजल्द ही पदावनत होने वाले हैं। इसे Reajs.org पर ब्लॉग पोस्ट में पढ़ें । इसके बजाय मैं प्रदान किए गए उत्तर के साथ जाऊंगा @jacob।
टॉम

29

वहाँ है (अब?) इस का एक उदाहरण के लिए React Router 4 के डॉक्स में Redirect

import { Route, Redirect } from 'react-router'

<Route exact path="/" render={() => (
  loggedIn ? (
    <Redirect to="/dashboard"/>
  ) : (
    <PublicHomePage/>
  )
)}/>

मैं फ़ंक्शन या चर के रूप में "लॉग इन" का उपयोग कैसे कर सकता हूं? क्या आप इसे थोड़ा समझा सकते हैं
कुंवर सिंह

@KunvarSingh यह शायद एक फ़ंक्शन होना चाहिए क्योंकि मान बदलता है।
जाकोब

3

react-router आपके राउटर के लिए एक घोषणात्मक दृष्टिकोण को प्रोत्साहित करता है, आपको अपने राउटर को जितना संभव हो उतना गूंगा बनाना चाहिए और अपने घटकों में अपने रूटिंग लॉजिक को रखने से बचना चाहिए।

यहां बताया गया है कि आप इसे कैसे कर सकते हैं (यह मानते हुए कि आप इसे पास करते हैं loggedIn):

const DumbRouter = ({ loggedIn }) => (
  <Router history={history}>
    <Switch>
      {[
        !loggedIn && LoggedOutRoutes,
        loggedIn && LoggedInRouter,
        <Route component={404Route} />
      ]}
    </Switch>
  </Router>
);

const LoggedInRoutes = [
  <Route path="/" component={Profile} />
];

const LoggedOutRoutes = [
  <Route path="/" component={Login} />
];

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

2

यदि आप अपने संपूर्ण एप्लिकेशन में प्रमाणीकरण का उपयोग करना चाहते हैं, तो आपको कुछ डेटा एप्लिकेशन-वाइड (जैसे टोकन) संग्रहीत करने की आवश्यकता है। आप दो रिएक्ट मिश्रणों को सेट कर सकते हैं जो $authऑब्जेक्ट के प्रबंधन के लिए जिम्मेदार हैं । यह ऑब्जेक्ट उन दो मिश्रणों के बाहर उपलब्ध नहीं होना चाहिए। यहाँ इसका उदाहरण दिया गया है:

define('userManagement', function() {
    'use strict';

    var $auth = {
        isLoggedIn: function () {
            // return something, e.g. using server-stored data
        }
    };

    return {
        Authenticator: {
           login: function(username, password) {
               // modify $auth object, or call server, or both
           }
        },

        NeedsAuthenticatedUser: {
            statics: {
                willTransitionTo: function (transition) {
                    if (!$auth.isLoggedIn()) {
                        transition.abort();
                    }
                }
            }
        }
    };
});

तब आप बस Authenticatorअपने लॉगिन घटकों (लॉगिन स्क्रीन, लॉगिन पॉपअप, आदि) के लिए मिक्सिंग कर सकते हैं और this.loginजब आपके पास सभी आवश्यक डेटा होते हैं, तो कॉल फ़ंक्शन।

सबसे महत्वपूर्ण बात NeedsAuthenticatedUserमिक्सी में मिश्रण करके अपने घटकों की रक्षा करना है । प्रत्येक घटक जिसे प्रमाणीकृत उपयोगकर्ता की आवश्यकता है, उसे इस तरह देखना होगा:

var um = require('userManagement');

var ProtectedComponent = React.createClass({
    mixins: [um.NeedsAuthenticatedUser]
    // ...
}

ध्यान दें कि NeedsAuthenticatedUserप्रतिक्रिया-राउटर एपीआई ( willTransitionToऔर transition.abort()) का उपयोग करता है ।


2
मिश्रणों को आगे बढ़ने के लिए बुरा विचार है। और पढ़ें
बोल्डनिक

एक बेहतर तरीका जो मुझे मिला: github.com/reactjs/react-router/tree/master/examples/auth-flow
boldnik

1
मिक्स को ES6 के रूप में हटा दिया गया है और प्रतिक्रिया उन्हें हटा रही है।
पियर

1

आप HOC का उपयोग कर सकते हैं और ऑर्डिन एक वैरिएबल है जिसे आप मान को सही या गलत तरीके से बदल सकते हैं (प्राधिकरण)

<Route path="/login" component={SignIn} />
<Route path="/posts" render = {() => (auth ?  (<Post />) : (<Redirect to="/login" />))}/>

0

निजी- path.tsx

import {Redirect, Route, RouteProps} from 'react-router';
import * as React from 'react';

interface PrivateRouteProps extends RouteProps {
  /**
   * '/login' for example.
   */
  redirectTo: string;

  /**
   * If true, won't redirect.
   * We are using a function instead of a bool, a bool does not seem to be updated
   * after having successfully authenticated.
   */
  isLogged: () => boolean;
}


export function PrivateRoute(props: PrivateRouteProps) {
  // `component: Component` is not typing, it assign the value to a new variable.
  let { isLogged, redirectTo, component: Component, ...rest }: any = props;

  // error: JSX type element Component does not have call signature or ... AVOIDED BY ADDING ANY, still work,
  // and did not find a proper way to fix it.
  return <Route {...rest} render={(props) => (
    isLogged()
      ? <Component {...props}/>
      : <Redirect to={{
        pathname: redirectTo,
        state: { from: props.location }
      }} />
  )} />;
}

उपयोग:

        <PrivateRoute exact={true} 
                      path="/admin/" 
                      redirectTo={'/admin/login'} 
                      isLogged={this.loginService.isLogged} 
                      component={AdminDashboardPage}/>
        <Route path="/admin/login/" component={AdminLoginPage}/>

Https://tylermcginnis.com/react-router-protected-routes-authentication/ पर आधारित है ।


-2

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

यहाँ एक उदाहरण है

Routes = (
    <Route path="/" handler={Root}>
        <Route name="login" handler={Login} />
        <Route name="forget" handler={ForgetPassword} />
        <Route handler={Main} >
            <Route name="overview" handler={Overview} />
            <Route name="profile" handler={Profile} />
            <DefaultRoute handler={Overview} />
        </Route>
        <DefaultRoute handler={Login} />
        <NotFoundRoute handler={NotFound} />
    </Route>
);

अपने मूल पृष्ठ पर, टोकन अशक्त के लिए जाँच करें या यह देखने के लिए कि उपयोगकर्ता मान्य लॉगिन है, सर्वर के साथ टोकन प्रमाणित करें।

उम्मीद है की यह मदद करेगा :)


2
सही है, इसलिए यदि प्रामाणिक नहीं हुआ है तो मैं "अवलोकन" वर्ग को कैसे रोकूंगा, या "मुख्य" हैंडलर कैसा दिखता है? उदाहरण के लिए, क्या होगा अगर "अवलोकन" में एक निर्भरता है जिसे चलाने के लिए एक प्रमाणित ऐप की आवश्यकता है? क्योंकि यह राउटर पर चलने के लिए आयात किया गया है, इसकी सभी निर्भरताएं भी आयात की गई होंगी, और इस प्रकार आपके पास एक टूटी हुई ऐप सही है?
मैरिस रोसौव जूल

यह उस प्रश्न का उत्तर नहीं देता है जो पूछा गया था
हरमनह
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.