无法实施身份验证路由

时间:2019-04-27 04:04:53

标签: javascript reactjs react-router

我正在尝试学习反应,并且正在我的应用程序中设置需要您登录的路由。我正在尝试修改给出的示例here

我编写的代码应重定向用户或显示受保护的路由。但是当我登录时,我仍然被重定向。

我认为问题出在下面的PrivateRoute类中。我将其传递给在父类中设置的authenticated属性,但似乎没有更新。

在app.js中,我们声明身份验证器,并在其中执行与后端的异步登录。

我将checkLoggedIn函数传递给登录组件,在该组件中,将父级的authenticated状态属性设置为true。我正在console.log()设置状态只是为了检查它的发生情况。

当我单击从Link/protected的路由时,仍在重定向。

app.js

// imports ... 

let authenticator = new Authenticator();

class ProtectedComponent extends Component {
    render() {
        return (
            <h1>Protected!</h1>
        );
    }
}

class App extends Component {
    constructor(props){
        super(props);
        this.state = {
            authenticator: authenticator,
            authenticated: authenticator.isLoggedIn(),
        }
    }

    checkLoggedIn() {
        this.setState({authenticated: true});
        console.log(this.state);
    }

    render() {
        let routes, links = null;
        links = <div className="links">
            <Link to="/login">Login</Link>
            <Link to="/protected">Protected</Link>
        </div>;

        routes = <div className="routes">
            <Route
                path="/login"
                render={() =>
                    <Login
                        authenticator={this.state.authenticator}
                        loginCallback={this.checkLoggedIn} />
                }
            />
            <PrivateRoute
                path="/protected"
                component={ProtectedComponent}
                authenticated={this.state.authenticated}
            />
        </div>;

        return (
            <Router className="App">
                {links}
                {routes}
            </Router>
        );
    }
}

export default App;

PrivateRoute.js

// imports .... 

const PrivateRoute = ({ component: Component, authenticated, ...rest }) => (
    <Route {...rest} render={props =>
            authenticated === true
                ? (<Component {...props} />)
                : (<Redirect to={{
                        pathname: "/login",
                        state: { from: props.location }
                    }} />
                )
    }/>
);

export default PrivateRoute;

Login.js

// imports ...

class Login extends Component {
    constructor(props) {
        super(props);
        this.authenticator = props.authenticator;
        this.loginCallback = props.loginCallback;
        this.state = {
            identifier: "",
            password: "",
        }
    }

    updateState = (e, keyName = null) => {
        this.setState({[keyName]: e.target.value})
    }

    attemptLogin = (e) => {
        this.authenticator.loginPromise(this.state.identifier, this.state.password)
            .then(resp => {
                if(resp.data.success === true) {
                    this.authenticator.setToken(resp.data.api_token);
                    this.loginCallback();
                } else {
                    this.authenticator.removeToken()
                }
            })
            .catch(err => {
                console.error(err);
            });
    }

    render(){
        <button onClick={this.attemptLogin}> Log In </button>
    }
}

export default Login;

我在回调方法中将身份验证状态设置为true,但是当我转到受保护的路由(并运行它的render方法)时,它似乎评估为false。

如果我误解了反应道具系统,请告诉我。如果您想查看更多代码,请告诉我,我将修正问题。

1 个答案:

答案 0 :(得分:1)

您必须先创建PrivateRoute HOC组件:

import React from 'react';
import { Route, Redirect } from 'react-router-dom';

export const PrivateRoute = ({ component: Component, ...rest }) => (
    <Route {...rest} render={props => (
        localStorage.getItem('bpm-user')
            ? <Component {...props} />
            : <Redirect to={{ pathname: '/login', state: { from: props.location } }} />
    )} />
)

并包装最受保护的路线:

        <Switch>
            <Route path="/login" component={Login} />
            <PrivateRoute path="/new/index" component={NewIndex} />
            <PrivateRoute path="/jobs/index" component={JobsIndex} />
            <PrivateRoute path="/unions/index" component={UnionsIndex} />
            <PrivateRoute exact path="/" component={ListIndex} />
            <PrivateRoute exact path="/charges" component={MunicipalCharges} />
        </Switch>

并使用链接

<Link to="/jobs/index">Jobs</Link>

我的登录还原器

import axios from 'axios';
import * as actionTypes from './AuthActionTypes';

export const login = (user) => {
    return dispatch => {
        // for example => dispatch({type:actionTypes.REQUEST_LOGIN_USER});
        axios({
            method: 'post',
            url: '/api/auth/login',
            data: { 'username': user.username, 'password': user.password },
            headers: { 'Content-Type': 'application/json;charset=utf-8' }
        })
            .then(res => {
                localStorage.setItem('bpm-user', JSON.stringify(res.data));
                dispatch({
                    type: actionTypes.LOGIN_USER,
                    payload: res.data
                })
            })
            .catch(error => {
                 // TODO... for example => dispatch({type:actionTypes.FAILD_LOGIN_USER, payload:error});
            })
    }
}

export const logout = () => {
    localStorage.removeItem('bpm-user');
}

就像我从自己的项目中复制的示例代码一样