discuz!编码
“As an application developer, we are concerned with authentication and security. We will explore one of the widely used security mechanism that is JWT(JSON Web Token). I will try to explain the key benefits and will discuss the issues most of the developer’s tackle while using JWT.”
“作为应用程序开发人员,我们关注身份验证和安全性。 我们将探索一种广泛使用的安全机制,即JWT(JSON Web令牌)。 我将尝试解释其主要优点,并讨论使用JWT时大多数开发人员所要解决的问题。”
#LET从基础开始: (# LET’s start with the basics:)
JWT is a JSON based authentication technique that is helpful for securely transmitting information between different parties in an application system.
JWT是基于JSON的身份验证技术,有助于在应用程序系统中的不同参与方之间安全地传输信息。
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/afcf897e48bfa223bd8d10298f4b74ef.png)
Let’s see how exactly it works will take the example of the above diagram to understand it. when the user login (i.e the react app sends the login request) and if the user is valid the node server returns a Jwt token that has some expiration time. This token received by react application is further used to access the protected resources (e.g API, pages). The react application is not allowed to access the protected resources without the valid token.
让我们看一下它如何工作,以上面的图表为例来理解它。 当用户登录时(即react应用发送登录请求),并且如果用户有效,则节点服务器返回Jwt令牌,该令牌具有一些到期时间。 react应用程序接收到的该令牌还用于访问受保护的资源(例如,API,页面)。 没有有效令牌,不允许React应用访问受保护的资源。
#现在,根据基础开始构建React应用程序。 (# Now after the basis lets start building our react app.)
To build the application we are using node with express-server as backend and MongoDB as our database to store the users, before we start you should install MongoDB you can use any to the database of your choice i.e MySQL, Postgresql, SQLite.Once you are done we are ready to start.
为了构建应用程序,我们使用Express Server作为后端的节点,而MongoDB作为我们存储用户的数据库,在开始之前,您应该安装MongoDB,您可以对您选择的任何数据库使用MySQL,Postgresql,SQLite。完成后,我们就可以开始了。
设置应用 (Setting Up Application)
Let's create two folders with the name client and server. The client folder will contain our front-end part (i.e react app) and the server will serve as the back-end.
让我们创建两个名为client和server的文件夹。 客户端文件夹将包含我们的前端部分(即react app),而服务器将充当后端。
Client
客户
Navigate to the client folder and the below mention command on the terminal.
导航到客户端文件夹,然后在终端上提到以下命令。
npx create-react-app .
Note: Don’t forget to mention the dot it symbolizes the current directory.
注意:不要忘了它代表当前目录的点。
The above command will initialize the react application in client dir. We will require a react-router to navigate to different links within our application. This can be installed by the below command.
上面的命令将在客户端目录中初始化react应用程序。 我们将需要一个React路由器来导航到我们应用程序中的不同链接。 可以通过以下命令安装。
npm i react-router-dom
Let's react to some of the routes and their respective pages. For a demo, we will create the following page.
让我们对一些路线及其各自的页面做出React。 对于演示,我们将创建以下页面。
and further, map it with respective routes as shown in the App.js file below.
并按照下面的App.js文件中所示的相应路线映射它。
import React from 'react';
import {NavLink, Route, Switch, BrowserRouter} from 'react-router-dom';
import Home from './home/Home';
import Login from './login/Login';
import Secret from './secret/Secret';
import withAuth from './hoc/withAuth';
import Logout from './logout/Logout';
function App() {
return (
<div className="nav">
<BrowserRouter>
<ul>
<li><NavLink activeClassName="is-active" to ="/">Home</NavLink ></li>
<li><NavLink activeClassName="is-active" to ="/secret">Secret</NavLink ></li>
<li><NavLink activeClassName="is-active" to ="/login">login</NavLink ></li>
<li><NavLink activeClassName="is-active" to ="/logout">logout</NavLink ></li>
</ul>
<div className="flex-container">
<Switch>
<Route path="/" exact component={Home} />
<Route path="/secret" component={withAuth(Secret)} />
<Route path="/login" component={Login} />
<Route path ="/logout" component ={Logout}/>
</Switch>
</div>
</BrowserRouter>
</div>
);
}
export default App;
Further, we will require an Auth guard (Higher Order Component) that will serve the purpose of Authenticating the resources or page.
此外,我们将需要一个Auth防护(高阶组件),用于保护资源或页面。
import React,{Component} from 'react';
import {Redirect} from 'react-router-dom';
export default function withAuth(ComponentInside){
return class extends Component {
constructor(){
super();
this.state={
loading:true,
redirect:false
};
}
componentDidMount() {
fetch('/checkToken', {
credentials: "include",
headers: { 'x-access-token': localStorage.getItem('token') }
})
.then(res => {
if (res.status === 200) {
this.setState({ loading: false });
} else {
const error = new Error(res.error);
throw error;
}
})
.catch(err => {
console.error(err);
this.setState({ loading: false, redirect: true });
});
}
render(){
const{loading, redirect} = this.state;
if(loading){
return null;
}
if(redirect){
return <Redirect to ="/login"/>
}
return <ComponentInside {...this.props}/>
}
}
}
This will allow only the authenticated user to access the page.
这将仅允许经过身份验证的用户访问页面。
OK, so far we are done with setting up our client.
好的 ,到目前为止,我们已经完成了设置客户端的工作。
Server
服务器
To set up the server, navigate to the server directory and run the below command one after the other.
要设置服务器,请导航至服务器目录,然后依次运行以下命令。
npm init -y // This will initilaize the npm repo
npm i express // Install express server
npm i mongoose // For mongoDB connectivity
npm i jsonwebtoken // For generating JWT
There are some dependencies which we will require that are mention in package.json file. In the end, your package.json file looks the one below.
我们需要一些依赖项,这些依赖项将在package.json文件中提及。 最后,您的package.json文件如下所示。
{
"name": "server",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"bcrypt": "^3.0.0",
"body-parser": "^1.18.3",
"cookie-parser": "^1.4.3",
"express": "^4.16.3",
"jsonwebtoken": "^8.3.0",
"mongoose": "^5.7.12",
"nodemon": "^2.0.4"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "nodemon index.js"
},
"author": "",
"license": "ISC"
}
We are using nodemon for live reloading of our application in dev env. Now let's start building our Node APIs that will allow the user to Register, Authenticate. I have set up the express server and added some API to it as below.
我们正在使用nodemon在dev env中实时重新加载我们的应用程序。 现在,让我们开始构建我们的Node API,该API将允许用户进行注册,身份验证。 我已经设置了快递服务器,并向其中添加了一些API,如下所示。
onst express = require('express');
const bodyParser = require('body-parser');
const jwt =require('jsonwebtoken');
const moongose = require('mongoose');
const User = require('./models/User');
const app = express();
app.use(bodyParser.json({}))
app.use(bodyParser.urlencoded({ extended: true }));
const secret = 'jwtdemo';
const mongo_uri="mongodb://localhost/react-jwt";
moongose.connect(mongo_uri,{ useNewUrlParser: true },((err)=>{
if(err){
throw err;
}
else{
console.log("Successfully connected");
}
}))
app.listen(process.env.PORT || 8080);
app.get('/server/home', (req,res)=>{
res.send("Welcome");
});
app.post('/server/auth', (req,res)=>{
const {email,password} = req.body;
User.findOne({email},(err,user)=>{
if(err){
res.status(500).send("Internal error");
}else if(!user){
res.status(401).send("Incorect email");
}else{
user.isCorrectPassword(password,(err,right)=>{
if(err){
res.status(500).send("Internal error");
}else if(!right){
console.log(right);
res.status(401).send("Incorect email or password");
}else {
// Issue token
const payload = { email };
const token = jwt.sign(payload, secret, {
expiresIn: '1h'
});
console.log("tokenLL",token);
// res.cookie('token', token, { httpOnly: true }).sendStatus(200);
res.json({
token: token
});
}
})
}
})
})
const chkToken = (req,res,next)=>{
const token = req.body.token ||
req.query.token ||
req.headers['x-access-token']
console.log("OOhre",token)
if(!token){
res.status(401).send('Unauthorised');
}else{
console.log("hre",token)
jwt.verify(token,secret,(err,success)=>{
console.log("error",err);
if(err){
res.status(401).send('Unauthorised');
}else{
req.email = success.email;
next();
}
})
}
}
app.get('/checktoken',chkToken,(req,res)=>{
res.sendStatus(200);
})
app.post('/server/register', (req,res)=>{
const {email,password} = req.body;
let user = new User({email,password});
user.save((err)=>{
if(err){
res.status(500).send("Internal error");
}
else{
res.status(200).send("Inserted");
}
})
})
app.get('/server/secret', chkToken, function(req, res) {
res.send('Welcome to Secret Component from Server');
});
OK, so we are done with the server and client.
好的,我们已经完成了服务器和客户端。
let's start our server and client with the following commands.
让我们使用以下命令启动服务器和客户端。
To start the client:
要启动客户端:
cd client
npm run start
For server,
对于服务器,
cd server
npm run start
This will start your application at http://localhost:3000. You can directly download or refer to our git repo for reference.
这将在http:// localhost:3000上启动您的应用程序。 您可以直接下载或参考我们的git repo以供参考。
In the end, this how your project looks like.
最后,这就是您的项目外观。
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/1b3ce3afcd747b81f3421a00ec5d517f.png)
Thanks, Ishant for helping me to create this project. You can follow us on LinkedIn and Medium for more interesting Updates.
谢谢, Ishant帮助我创建了这个项目。 您可以在LinkedIn和Medium上关注我们,以获取更多有趣的更新。
翻译自: https://medium.com/@pankajpurke05/jwt-authentication-with-react-application-5b2562966d83
discuz!编码