如何将 JWT 从客户端传递到我的 API 以进行正确身份验证?
Posted
技术标签:
【中文标题】如何将 JWT 从客户端传递到我的 API 以进行正确身份验证?【英文标题】:How can I pass a JWT from the client side to my API to be properly authenticated? 【发布时间】:2019-09-16 03:26:01 【问题描述】:我需要将带有 GET、POST、PUT、DELETE 方法的 JWT 从我的 UI 传递到我的 API。
为此,我尝试使用 ReactJS 创建一个前端。我明白了:
POST http://localhost:4000/book/ 401(未经授权) 当我尝试发送请求时。
我知道我必须传递我的令牌,这是我在向 mongo DB 发送数据时通过邮递员完成的。 我是 MERN 堆栈的新手,所以我仍在努力理解。
-
这是图书控制器
import mongoose from 'mongoose';
import book_schema from '../model/book_model';
const Book = new mongoose.model('Book', book_schema);
export const add_new_book = (req, res) =>
let new_book = new Book(req.body);
new_book.save((err, book) =>
if (err)
res.send(err);
res.json(book);
);
;
-
这些是图书路线
import add_new_book from '../controller/book_controller';
import authorization from '../controller/user_controller';
const book_routes = (app) =>
//GET
app.route('/book')
//POST
.post(authorization,add_new_book);
-
这是用户控制器
import mongoose from 'mongoose';
import bycrypt from 'bcrypt';
import jwt from 'jsonwebtoken';
import user_schema from '../model/user_model';
const User = mongoose.model('User', user_schema);
export const register = (req, res) =>
const new_user = new User(req.body);
new_user.hash_password = bycrypt.hashSync(req.body.password, 10);
new_user.save((err, user) =>
if (err)
return res.status(400).send(
message: err
);
else
user.hash_password = undefined;
return res.json(user);
);
;
export const authenticate = (req, res) =>
User.findOne(
user_name: req.body.user_name
, (err, user) =>
if (err) throw err;
if (!user)
res.status(401).json( message: 'Authentication Failed ! - No User.' )
else if (user)
if (!user.comparePassword(req.body.password, user.hash_password))
res.status(401).json( message: 'Authentication Failed ! - Wrong Password.' )
else
var token = res.json(
token: jwt.sign( user_name: user.user_name , 'RESTFULAPIs', expiresIn: '24h' )
);
//$window.sessionStorage.accessToken = response.body.access_token;
return token;
);
;
export const authorization = (req, res, next) =>
if (req.user)
next();
else
return res.status(401).json( message: 'Unauthorized User !' )
;
export const de_authenticate = (req, res) =>
;
-
这是服务器
import express from 'express';
import cors from 'cors';
import bodyParser from 'body-parser';
import mongoose from 'mongoose';
import jsonwebtoken from 'jsonwebtoken';
import db_config from './config_db.js';
const app = express();
const PORT = 4000;
//import routes here
import book_routes from './api/route/book_route';
import user_routes from './api/route/user_route';
import item_routes from './api/route/item_route';
//mongo DB connection
mongoose.Promise = global.Promise;
mongoose.connect(db_config.DB, useNewUrlParser: true ).then(
() => console.log('Database is connected') ,
err => console.log('Can not connect to the database' + err)
);
app.use(cors());
app.use(bodyParser.urlencoded( extended: true ));
app.use(bodyParser.json());
//JWT setup
app.use((req, res, next) =>
if (req.headers && req.headers.authorization && req.headers.authorization.split(' ')[0] === 'JWT')
jsonwebtoken.verify(req.headers.authorization.split(''), [1], 'RESTFULAPIs', (err, decode) =>
if (err) req.user = undefined;
req.user = decode;
//console.log(req.user );
//console.log(decode);
next();
);
else
req.user = undefined;
next();
);
//to app
book_routes(app);
user_routes(app);
item_routes(app);
app.get('/', (req, res) =>
res.send(`Node Server and Express Server Running on Port : $PORT`)
);
app.listen(PORT, function ()
console.log(`Server is running on Port: $PORT`);
);
我使用 ReactJS 开发前端并导入 axios 以通过 URL 访问 API。在 insert_book.js 文件中,我的表单提交函数是这样的,
onSubmit(e)
e.preventDefault();
const book_obj =
book_no:this.unique_id_generator(),
isbn_no: this.state.isbn_no,
author: this.state.author,
published_year: this.state.published_year,
publisher: this.state.publisher,
category:this.state.category
;
axios.post('http://localhost:4000/book/', book_obj)
.then(res => console.log(res.data));
this.setState(
isbn_no: '',
author:'',
published_year: '',
publisher: '',
category:''
)
最后我想提供用户路线代码,
import register,
authenticate,
authorization
from '../controller/user_controller';
const user_routes = (app) =>
//SIGNUP
app.route('/auth/signup')
//POST A USER
.post(register);
//SIGNIN
app.route('/auth/signin')
//AUTHENTICATE USER
.post(authenticate);
export default user_routes;
这是我卡住的地方:
-
如何将这些令牌存储在会话中以便与未来的请求一起发送?
如何使用 GET、POST、PUT、DELETE 方法附加和发送令牌值?
【问题讨论】:
使用这个将令牌保存在本地存储res=>localStorage.setItem('token',(res.data.token))
【参考方案1】:
所以将令牌存储在本地存储中:
const user: User = getUserFromBackend()
// assuming user is an object
localStorage.setItem('token', user.token);
// get token
const token = localStorage.getItem('token');
使用令牌头发出请求:
const token = localStorage.getItem('token');
fetch(url,
method: "POST",
headers:
"Content-Type": "application/json",
'Authorization': `Bearer $token`,
,
body: JSON.stringify(data), // body data type must match "Content-Type" header
)
.then(response => response.json())
【讨论】:
你能帮我实现吗?因为我在处理创建的令牌时遇到了问题。 是的,如果它保存在本地存储而不是 cookie 中,则很容易访问。【参考方案2】:虽然迟到了。如果可能的话,我建议将 JWT 存储在 cookie 中。然后,您只需读取 cookie 并在需要身份验证的请求的标头中传递 JWT。我更喜欢调用 header 键 x-api-token
并将其值设置为 JWT 字符串。
此外,您只需通过解密此 JWT 并验证,从您的后端对用户进行一次身份验证。验证 JWT 后,您可以为经过身份验证的用户创建会话。此会话将在半小时或您在应用中配置的任何内容后到期。
这样你就不需要再次发送 JWT,因为会话是有效的。我并不是说发送 JWT 不好,有时在您不为经过身份验证的用户创建会话的应用程序中是必需的。执行需要一次性身份验证的操作(如支付处理)时会发生这种情况。
使用 node 的 JWT-decode 包 (https://www.npmjs.com/package/jwt-decode) 实现这个逻辑应该不是问题。
希望这会有所帮助。
【讨论】:
以上是关于如何将 JWT 从客户端传递到我的 API 以进行正确身份验证?的主要内容,如果未能解决你的问题,请参考以下文章
如何证明 JWT 是不是有效并且是不是真的来自 Microsoft?