使用react-router等待响应时如何重定向

时间:2018-06-14 10:25:52

标签: reactjs openid

我尝试从Login Component重定向到DashBoard Component。

在这种情况下,我的登录组件称为CodeClient,DashBoard组件称为IndexComponent。

我的问题是CodeClient组件发出了使用openid进行身份验证的请求,当它进行回调时它没有输入sendToken(code, status),因为它没有获取信息。我想在之前重定向获取代码并提出请求。

如果渲染只包含:

class App extends Component {
    render() {
        return (
            <CodeClient />
        );
    }
}
export default App;

sendToken(code, status)上输入并创建Cookie,然后显示网址:http://localhost:3000/loginCallback?code=ab4d60814c50fe66de0bd9z4a3318f12&session_state=mVnqjmlT4gyTslk0cwbYeSOvxIKHqIl85pPX6Gh7f1c.63dfcdf9691b3ebcdd0cb28dcac27e94

但是,当我试图制作时,我在一秒钟内显示以前的网址,然后对此进行更改:http://localhost:3000/login

我的想法是,用户不应该在没有权限的情况下访问任何路由,并且用户将被验证并在索引页面上继续刷新导航器。

我不确定自己是否表现不错,而且我疯狂地解决问题,getToken上的输入发出请求,等待,创建Cookie并重定向到索引

谢谢,对不起我的英文

这是我的代码:

App.js

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

import './App.css';
import CodeClient from './components/Login/CodeClient';
import IndexComponent from './components/Index/IndexComponent';

const checkAuth = () => {
    const cookie = JSON.parse(localStorage.getItem('cookie'));
    if (!cookie) return false;
    try {
        const exp = cookie.exp;
        const current = new Date().getTime();
        if (exp < current) {
            return false;
        }
        return true;
    } catch (error) {
        return false;
    }
}

const Home = (props) => {
    if (checkAuth() === true) {
        return <IndexComponent {...props} />
    }
    return <Redirect to={{
        pathname: '/login',
        state: { from: props.location }
    }} />
}

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

class App extends Component {

    render() {

        return (
            <BrowserRouter>
                <Switch>
                    <Route path="/login" component={CodeClient} />
                    <PrivateRoute path="/" component={Home} />
                </Switch>
            </BrowserRouter>
        );
    }
}

export default App;

CodeClient.js

import React, { Component } from 'react';

import './CodeClient.css';
import request from 'request';

class CodeClient extends Component {

    constructor(props) {
        super(props);
        this.state = { messageError: '', ok: false };

        this.url = 'https://url_example/connect/authorize?scope=openid&response_type=code&client_id=myclientid&redirect_uri=http://localhost:3000/loginCallback';
        this.url = encodeURI(this.url);
    }

    handleLogin = (event) => {
        event.preventDefault();
        window.location.href = this.url;
    }

    componentDidMount() {
        var url_string = window.location.href;
        var url = new URL(url_string);
        var code = url.searchParams.get("code");
        var session_state = url.searchParams.get("session_state");

        if (code) {
            this.sendToken(code, session_state);
        }
    }

    sendToken = (code, state) => {
        var options = { 
            method: 'POST',
            url: 'http://localhost:8080/login',
            headers: { 'content-type': 'application/json' },
            body: { 
                code: code,
                state: state
            },
            json: true 
        };

        request(options, (error, response, body) => {
            if (error) {
                this.setState({ messageError: 'Error al autenticarse: ', error, ok: false });
                // throw new Error(error);
            }

            if (body.ok === true) {
                this.createCookie(body);
                this.props.history.push('/');
            } else {
                this.setState({ messageError: 'El código ya no sirve', ok: false });
            }
        });
    }

    createCookie = (data) => {
        var info = {
            id: data.id,
            name: data.name,
            exp: new Date().getTime() + data.expires_in,
        };
        console.log(info)
        localStorage.setItem('cookie', JSON.stringify(info));
    }

    render() {
        return (
            <div className="Menu">
                <div className="container">
                    <div className="card card-container">
                        <img id="profile-img" className="profile-img-card" src="//ssl.gstatic.com/accounts/ui/avatar_2x.png" alt="logo" />
                        <p id="profile-name" className="profile-name-card"></p>

                        <form className="form-signin">
                            {
                                (this.state.ok === false) ? <span id="reauth-email" className="reauth-email error">{this.state.messageError}</span> : 
                                    <span id="reauth-email" className="reauth-email success">{this.state.messageError}</span>
                            }

                            <button className="btn btn-lg btn-primary btn-block btn-signin" onClick={this.handleLogin} >Conectar</button>
                        </form>
                    </div>
                </div>
            </div>
        );
    }
}

export default CodeClient;

1 个答案:

答案 0 :(得分:0)

这是一种可能的解决方案,但这是一个糟糕的解决方案或实施不好。

App.js

import React, { Component } from 'react';

import './App.css';
import request from 'request';
import IndexComponent from './components/Index/IndexComponent';

const checkAuth = () => {
    const cookie = JSON.parse(localStorage.getItem('cookie'));
    if (!cookie) return false;
    try {
        const exp = cookie.exp;
        const current = new Date().getTime();
        if (exp < current) {
            return false;
        }
        return true;
    } catch (error) {
        return false;
    }
}

class App extends Component {

    constructor(props) {
        super(props);
        // window.history.pushState("", "", '/');
        this.state = { logged: false, messageError: '', ok: false };

        this.url = 'https://url_example/connect/authorize?scope=openid&response_type=code&client_id=myclientid&redirect_uri=http://localhost:3000/loginCallback';
        this.url = encodeURI(this.url);
    }

    handleLogin = (event) => {
        event.preventDefault();
        window.location.href = this.url;
    }

    componentDidMount() {
        var url_string = window.location.href;
        var url = new URL(url_string);
        var code = url.searchParams.get("code");
        var session_state = url.searchParams.get("session_state");

        if (code) {
            this.sendToken(code, session_state);
        }
    }

    sendToken = (code, state) => {
        var options = { 
            method: 'POST',
            url: 'http://localhost:8080/login',
            headers: { 'content-type': 'application/json' },
            body: { 
                code: code,
                state: state
            },
            json: true 
        };

        request(options, (error, response, body) => {
            if (error) {
                this.setState({ messageError: 'Error al autenticarse: ', error, ok: false });
                // throw new Error(error);
            }

            if (body.ok === true) {
                this.createCookie(body);
            } else {
                this.setState({ messageError: 'El código ya no sirve', ok: false });
            }
        });
    }

    createCookie = (data) => {
        var info = {
            id: data.id,
            name: data.name,
            exp: new Date().getTime() + data.expires_in,
        };
        localStorage.setItem('cookie', JSON.stringify(info));
        this.setState({ logged: true });
    }

    render() {
        if (checkAuth()) return <IndexComponent />;
        else {
            return (
                <div className="Menu">
                    <div className="container">
                        <div className="card card-container">
                            <img id="profile-img" className="profile-img-card" src="//ssl.gstatic.com/accounts/ui/avatar_2x.png" alt="logo" />
                            <p id="profile-name" className="profile-name-card"></p>

                            <form className="form-signin">
                                {
                                    (this.state.ok === false) ? <span id="reauth-email" className="reauth-email error">{this.state.messageError}</span> : 
                                        <span id="reauth-email" className="reauth-email success">{this.state.messageError}</span>
                                }

                                <button className="btn btn-lg btn-primary btn-block btn-signin" onClick={this.handleLogin} >Conectar</button>
                            </form>
                        </div>
                    </div>
                </div>
            );
        }
    }
}

export default App;

IndexComponent.js

import React, { Component } from 'react';

import './IndexComponent.css'

const checkAuth = () => {
    const cookie = JSON.parse(localStorage.getItem('cookie'));
    if (!cookie) return false;
    try {
        const exp = cookie.exp;
        const current = new Date().getTime();
        if (exp < current) {
            return false;
        }
        return true;
    } catch (error) {
        return false;
    }
}

class IndexComponent extends Component {

    constructor(props) {
        super(props);
        window.history.pushState("", "", '/menu');
        this.checkCookie();
    }

    checkCookie = () => {
        if (!checkAuth()) {
            this.logout();
        }
    }

    logout = () => {
        localStorage.setItem('cookie', null);
        window.location.href = '/';
    }

    render() {
        return (
            <div>
                <h1>Home!</h1>
                <p>Estas logueado! Muy bien!</p>
                <button onClick={() => {
                    this.logout()
                }}>Cerrar sesión</button>
            </div>
        );
    }
}

export default IndexComponent;