【问题标题】:React private routes for basic authentication为基本身份验证反应私有路由
【发布时间】:2021-08-06 00:32:43
【问题描述】:

我正在尝试在我的反应应用程序中实现基本身份验证。我在标题中发送了emailpassword,同时向我的/users 端点发出GET 请求,并根据响应决定登录是否成功。如果登录成功(即用户存在于端点),那么我们推送到<projects> 组件。但我希望用户只有在他是有效用户的情况下才能访问/projects url。如何应用私有路由

这就是我的登录页面代码的样子 函数登录(){

const [password, setPassword] = React.useState("");
const [email, setEmail] = React.useState("");
const [err, setErr] = React.useState(null);

const history = useHistory();

const handleSubmit = async (event, password, email) => {
    event.preventDefault();

    var myHeaders = new Headers();
    myHeaders.set('Authorization', 'Basic ' + encode(email + ":" + password));

    var requestOptions = {
    method: 'GET',
    headers: myHeaders,
    redirect: 'follow'
    };

    let response;

    try {
        response = await fetch (`${APIlink}/users`, requestOptions)
    } catch (err) {
        setErr("Incorrect Password. Please Retry.");
        return;
    }

    const result = await response.text();
    console.log(result);
    const json = JSON.parse(result);
    console.log(json);
    console.log(response);
    

    if (response.status===200) {
        setErr(null);
        history.push("/Projects"); //valid user is redirected but /Projects is accessible by just
                                   //writing the url as well
        } else {
        setErr(json.error);
        console.log(json.error);
        }
    };

这是发送正确凭据后我的 json 对象的外观 (email: abc, password: test)

{
  "password": "test",
  "rollno": "18am200",
  "email": "abc",
  "name": "mkyong",
  "user-uid": "7e7199247de1125a6dc1518dd78ba554"
}

这就是我的回复的样子

Response { type: "cors", url: "{APIlink/users", redirected: false, status: 200, ok: true, statusText: "OK", headers: Headers, body: ReadableStream, bodyUsed: true }

App.js

function App() {
    return (
      <div >
        <HashRouter basename ='/'>
        <Switch>
          <Route path="/" component = {Home} exact/>
          <Route path="/Login" component = {LogIn}/>
          <Route path="/Register" component = {Register}/>
          <Route path="/Projects" component = {ProjectComponent} />
          <Route path="/Application" component = {Project2Component} />
          <Route path="/Demo1" component = {Project3Component} />  
          <Route path="/Demo2" component = {Project4Component} />     
        </Switch>
        </HashRouter>
    </div>
    )
  }

export default App

【问题讨论】:

  • 请添加您的App.jsxindex.js 文件的一些代码,或您已映射路线的sn-p,例如&lt;Route path={route.path} component={LoginComponent} /&gt;
  • @bonnopc 我已经添加了 App.js 代码,除了主页和登录页面,其他所有内容都应该只有登录用户才能访问。
  • 您需要某种支持用户会话和验证的身份验证架构,例如 cookie 或 JWT,这太长而无法包含在单个 SO 答案中。我建议你搜索一些相关的文章来解释。

标签: javascript reactjs react-hooks fetch basic-authentication


【解决方案1】:

您可以在登录成功响应后为您的 LocalStorage 设置一个持久值(例如isAuthenticated = true)。但请确保在用户注销后删除该值(例如isAuthenticated = false)。然后您可以在用户每次更改路线时检查该值。

我在下面为您添加了一些基本示例 -

// Login.js

/* other codes ... */
if (response.status===200) {
    localStorage.setItem('isAuthenticated', true);
    history.push("/Projects");
};
/* other codes ... */
// Logout.js

localStorage.removeItem('isAuthenticated');
// AuthRequired.js

import React, { Fragment } from "react"
import { Redirect } from "react-router-dom"

export default function AuthRequired(props){
    const isAuthenticated = localStorage.getItem('isAuthenticated')

    if(isAuthenticated){
        return props.orComponent;
    } else {
        return <Redirect to="/Login"/>
    }
}
// App.js

import { Route, Switch } from "react-router-dom"
import AuthRequired from "./AuthRequired"

/* Your other codes and imports.. */

const publicRoutes = [
    {
        path: "/Login",
        exact: true,
        component: LogIn
    },
    {
        path: "/",
        exact: true,
        component: Home
    },
];

const authRequiredRoutes = [
    {
        path: "/Projects",
        exact: true,
        component: <ProjectComponent/>
    },
    // ... other routes
]

const pathsForLayout = routes => routes.map(route => route.path)

function App() {
    return (
        <div >
            <HashRouter basename ='/'>
                <Switch>
                    <Route exact path={pathsForLayout(publicRoutes)}>
                        <Switch>
                            {
                                publicRoutes.map((route,index) => (
                                    <Route
                                        key={index}
                                        exact={route.exact}
                                        path={route.path}
                                        component={route.component}
                                    />
                                ))
                            }
                        </Switch>
                    </Route>
                    <Route exact path={pathsForLayout(authRequiredRoutes)}>
                        <Switch>
                            {
                                authRequiredRoutes.map((route,index) => (
                                    <Route
                                        key={index}
                                        exact={route.exact}
                                        path={route.path}
                                        render={() => (
                                             <AuthRequired 
                                                 {...props}
                                                 orComponent={route.component}
                                             />
                                        )}
                                    />
                                ))
                            }
                        </Switch>
                    </Route>
                    <Route component={NotFound} /> {/* Your custom 404 page */}
               </Switch>
           </HashRouter>
        </div>
    )
}

export default App

注意 - 我遵循了您的路线命名约定。这就是为什么我也将这些保留为 PascalCase。虽然声明&lt;Route/&gt;path 的推荐方法是使用kebab-case。 (例如path="/login")。

【讨论】:

    猜你喜欢
    • 2018-12-19
    • 1970-01-01
    • 1970-01-01
    • 2020-11-30
    • 2018-05-16
    • 1970-01-01
    • 2020-11-12
    • 2020-02-22
    • 2017-09-26
    相关资源
    最近更新 更多