- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我现在正在设计 frontend
部分。这是我的Router
/
是登录页面。它检查 token
在localStorage
旁边。它有isAuthenticated
在 state
/select-teams
是功能页面,在让用户使用它之前必须验证 token
第一的。
问题是。
1.应该刷新token
每次之前query
APIs
?
2、器间componentWillMount
通过检查token
每次 VS 通过状态时都会起作用。哪一种是最佳实践? IMO阅读localStorage
每次都可能会减慢应用程序的速度。然而,这对我来说很容易做到,但却不是DRY
3.假设我想通过isAuthenticated
状态介于Route
之间到另一个Route
。我怎样才能做到这一点?
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import registerServiceWorker from './registerServiceWorker';
import {Provider} from 'react-redux';
import {applyMiddleware, createStore} from 'redux';
import {BrowserRouter, Route, Switch} from 'react-router-dom';
import promise from 'redux-promise';
import LoginPage from "./components/loginPage";
import reducers from './reducers/index';
import SelectTeam from './components/select_teams';
const createStoreWithMiddleware = applyMiddleware(promise)(createStore);
ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
<BrowserRouter>
<div>
<Switch>
<Route path="/select-teams" component={SelectTeam}/>
<Route path="/" component={LoginPage}/>
</Switch>
</div>
</BrowserRouter>
</Provider>
, document.getElementById('root'));
registerServiceWorker();
这是我的Component
import React, {Component} from 'react';
import {connect} from 'react-redux';
import login_image from '../images/login_image.png';
import {Field, reduxForm} from 'redux-form';
import {getTokenAuth, refreshToken} from "../actions";
import ErrorMessage from './errorMessage';
class LoginPage extends Component {
//1. Verify user token. If token is good.
//1.1 Do refresh token and
//1.2 Then put him to `select-teams` page
//1.3 Finally set isAuthenticated: true
//2. If token is not good. Let user login again.
//By setting the isAuthenticated: false
constructor(props) {
super(props);
const token = localStorage.getItem('token');
const isAuthenticated = !((token === undefined) | (token === null));
this.state = {
token: localStorage.getItem('token'),
isAuthenticated,
message: null,
statusCode: null
};
}
componentWillMount() {
console.log('Enter componentWillMount');
const token = this.state.token;
if (token === undefined || token === null)
this.setState((prevState) => {
{
isAuthenticated: false
}
});
else {
console.log('componentWillMount token is exist');
//Refresh the token. Let backend verify it
//Outcome is 1. It is expired and unable to refresh
//Or 2. It is refreshed
this.props.refreshToken(token, (res) => {
console.log(res.status);
if (res.status === 200) {
//Receive new token
localStorage.setItem('token', res.data.token);
this.setState((prevState) => {
return Object.assign(prevState, {
isAuthenticated: true,
statusCode: res.status,
message: res.statusText
});
});
this.props.history.push('/select-teams');
} else {
//Token is expired and can not be able to refresh again. Force user to do login again by remove his token
localStorage.removeItem('token');
this.setState((prevState) => {
return Object.assign(prevState, {
isAuthenticated: false,
statusCode: res.status,
message: res.data.non_field_errors
});
});
}
})
}
}
renderField(field) {
const {meta: {touched, error}} = field;
const className = `'form-group' ${touched && error ? 'has-danger' : ''}`;
return (
<div className={className}>
<label>{field.label}</label>
<input
className="form-control"
type={field.type}
placeholder={field.placeholder}
{...field.input}
/>
<div className="text-help">
{touched ? error : ''}
</div>
</div>
);
}
onSubmit(values) {
console.log(values);
this.props.getTokenAuth(values, (res) => {
console.log(res.status);
if (res.status === 200) {
localStorage.setItem('token', res.data.token);
this.setState((prevState) => {
return Object.assign(prevState, {
isAuthenticated: true,
statusCode: res.status,
message: res.statusText
});
});
this.props.history.push('/select-teams');
} else {
localStorage.removeItem('token');
this.setState((prevState) => {
return Object.assign(prevState, {
isAuthenticated: false,
statusCode: res.status,
message: res.data.non_field_errors
});
});
}
})
}
render() {
const {handleSubmit} = this.props;
return (
<div>
<img src={login_image} alt="Poink Logo"/>
<ErrorMessage
isAuthenticated={this.state.isAuthenticated}
message={this.state.message}
/>
<form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
<Field
name="userid"
component={this.renderField}
placeholder="User ID"
type="text"
/>
<Field
name="password"
component={this.renderField}
placeholder="Password"
type="password"
/>
<button type="submit" className="btn btn-primary">Submit</button>
</form>
<a className='btn btn-primary' href="https://www.magicboxasia.com/">Sign up</a>
</div>
);
}
}
function validate(values) {
const errors = {};
// Validate the inputs from 'values'
if (!values.userid) {
errors.userid = "Enter a user ID!";
}
if (!values.password) {
errors.password = "Enter your password";
}
return errors;
}
function mapStateToProps(state) {
return {
token: state.token,
isAuthenticated: state.isAuthenticated,
}
}
export default reduxForm({
validate,
form: 'LoginForm'
})(
connect(mapStateToProps, {getTokenAuth, refreshToken})(LoginPage)
);
最佳答案
您的 react 应用程序应该验证 token 是否位于本地存储/另一个存储上,并且您的后端必须验证 token 是否有效,因为如果没有其 secret ,您无法验证 token 是否有效。
我们在我工作的公司所做的是一个高阶组件,它接收一个函数来检查 token 是否存储为 Prop 。如果该函数返回 true,我们将渲染该组件,如果不返回,它将重定向到登录路由。该函数称为isAuthorized
。
const PrivateRoute = ({ component: Component, isAuthorized, ...otherProps }) => (
<Route
{...otherProps}
render={props => (
isAuthorized() ? (<Component {...props} />) :
(
<Redirect to={
{
pathname: '/login',
state: { from: props.location },
}
}
/>
)
)}
/>
);
这是我们的索引。我们导入告诉用户是否有权查看此路由的函数,在本例中为 hasToken
:
<Switch>
<PrivateRoute exact path="/" isAuthorized={hasToken} component={Home} />
<PrivateRoute exact path="/list" isAuthorized={hasToken} component={List} />
<PrivateRoute exact path="/view/:id" isAuthorized={hasToken} component={View} />
<Route component={PageNotFound} />
</Switch>
现在,如果 token 不存在,它的 PrivateRoute 负责重定向用户登录。
现在您应该考虑一种在后端返回 401(未经授权)时重定向用户登录的好方法。后端是实际的 token 验证器。在我工作的公司中,我们使用 axios 来执行 ajax 调用,并且我们创建了一个 axios 拦截器,如果后端响应返回 401 http 状态代码,该拦截器会将用户重定向到登录路由。
关于javascript - 如何将路由器中的组件状态传递到另一个路由器组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47740608/
我错过了什么,我已完成 的安装指南中要求的所有步骤 native 脚本 运行 tns doctor 给我以下输出... C:\abc\xyz>tns doctor √ Getting environm
尝试从 {addToCart(book)}}/>}> 传递数据至}> 问题: 购物车 ( render={()=> ) 收到 null,但没有收到我尝试发送的对象 已放置“console.log...
这是 _app.tsx 的外观: function MyApp({ Component, pageProps }: AppProps) { return } 我在构建项目时遇到了这个错误: Ty
我的 Laravel Vue 组件收到以下警告: [Vue warn]: Avoid mutating a prop directly since the value will be overwrit
根据这个example更详细this one我刚刚遇到了一件奇怪的事情...... 如果我使用方法作为 addTab(title,icon,component) 并且下一步想使用 setTabComp
目前我有一个捕获登录数据的表单,一个带有 TIWDBGrid 的表单,它应该返回与我从我的 mysql 数据库登录时创建的 user_id 关联的任何主机,以及一个共享数据模块。 下面是我的登录页面代
在我的react-native应用程序中,我目前有一个本地Android View (用java编写)正确渲染。当我尝试将我的react-native javascript 组件之一放入其中时,出现以
我为作业编写了简单的代码。我引用了文档和几个 youtube 视频教程系列。我的 react 代码是正确的我在运行代码时没有收到任何错误。但是这些 react-boostrap 元素没有渲染。此代码仅
几周前我刚刚开始使用 Flow,从一周前开始我就遇到了 Flow 错误,我不知道如何修复。 代码如下: // @flow import React, { Component } from "react
我想在同一个 View 中加载不同的 web2py 组件,但不是同时加载。我有 5 个 .load 文件,它们具有用于不同场景的表单字段,这些文件由 onchange 选择脚本动态调用。 web2py
关闭。这个问题是opinion-based .它目前不接受答案。 想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题. 6年前关闭。 Improve t
Blazor 有 InputNumber将输入限制为数字的组件。然而,这呈现了一个 firefox 不尊重(它允许任何文本)。 所以我尝试创建一个过滤输入的自定义组件: @inherits Inpu
我在学习 AngularDART 组件时编写了以下简单代码,但没有显示任何内容,任何人都可以帮助我知道我犯了什么错误: 我的 html 主文件:
我想在初始安装组件时或之后为 div 设置动画(淡入)。动画完成后,div 不应消失。我正在尝试使用 CSSTransition 组件并查看 reactcommunity.org 上的示例,但我根本无
我需要一个 JSF 组件来表示甘特图。是否有任何组件库(如 RichFaces)包含这样的组件? 最佳答案 JFreeChart有甘特图和PrimeFaces有一个图像组件,允许您动态地流式传输内容。
从软件工程的角度来看,组件、模块和子系统之间有什么区别? 提前致谢! 最佳答案 以下是 UML 2.5 的一些发现: 组件:该子句指定一组结构,可用于定义任意大小和复杂性的软件系统。特别是,它将组件指
我有使用非托管程序集(名为 unmanaged.dll)的托管应用程序(名为 managed.exe)。到目前为止,我们已经创建了 Interop.unmanaged.dll,managed.exe
我有一个跨多个应用程序复制的 DAL(我知道它的设计很糟糕,但现在忽略它),我想做的是这个...... 创建一个将通过所有桌面应用程序访问的 WCF DAL 组件。任何人都可以分享他们对关注的想法吗?
我有一个 ComboBox 的集合声明如下。 val cmbAll = for (i /** action here **/ } 所有这些都放在一个 TabbedPane 中。我想这不是问题。那么我
使用 VB6 创建一个 VB 应用程序。应用程序的一部分显示内部的闪存。 当我使用 printform它只是打印整个应用程序。我不知道如何单独打印闪光部分。任何帮助,将不胜感激!.. 谢谢。 最佳答案
我是一名优秀的程序员,十分优秀!