我正在使用NodeJS API构建离子2应用程序,在服务器端我使用jsonwebtoken在登录成功后创建令牌并将其保存在客户端的localStorage中。我的问题是如何比较并检查令牌在expireIN时间后是否仍然有效!
这是服务器路由端代码:
// :::::: G E T T H E P A C K A G E W E N E E D : : : : : : : :
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var morgan = require('morgan');
var mongoose = require('mongoose');
var cors=require('cors');
var jwt = require('jsonwebtoken'); // used to create, sign, and verify tokens
var config = require('./config'); // get our config file
// ─── GET an instance of the router for api routes ────────────────────────────────────────────────────────────────────────
var apiRoutes = express.Router();
var users =require('./app/routes/users');
//
// ────────────────────────────────────────────── II ──────────────────────────────────────────────────────────────────────
// :::::: CONFIGURATION : : : : : : : :
var port = process.env.PORT || 1991; // used to create, sign, and verify tokens
mongoose.connect(config.database, { useMongoClient: true }); // connect to database
app.set('superSecret', config.secret); // secret variable
//
// ────────────────────────────────────────────── III ──────────────────────────────────────────────────────────────────────
// :::::: USE BODY PARSER SO WE CAN GET INFO FROM POST AND/OR URL PARAMETERS : : : : : : : :
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
// :::::: USE MORGAN TO LOG REQUESTS TO THE CONSOLE: : : :
app.use(morgan('dev'));
app.use(cors());
// ──────────────────────────────────────────────────────────────
// :::::: R O U T E S : : : : : : : :
// ──────────────────────────────────────────────────────────────
// ─── A P I ROUTES ────────────────────────────────────────
// :::::: MIDDLEWARE to secure route begin with /api: : : :
apiRoutes.use(function(req, res, next) {
console.log('hah');
var token = req.body.token || req.query.token || req.headers['x-access-token'];
if (token) {
// verifies secret and checks exp
jwt.verify(token, app.get('superSecret'), function(err, decoded) {
console.log([err,decoded]);
if (err) { //failed verification.
return res.json({"error": true, success:false, message:'Faild to authenticate token'});
}
req.decoded = decoded;
next(); //no error, proceed
});
} else {
// forbidden without token
return res.status(403).send({
success: false,
message: 'No token provided.'
});
}
});
apiRoutes.get('/', function(req, res) {
res.json({ message: 'Welcome to the coolest API on earth!' });
});
app.use('/api', apiRoutes);
app.use('/user', users);
// ──────────────────────────────────────────────────
// :::::: S T A R T the server: : : : : :
app.listen(port);
console.log('Magic happens at http://localhost:' + port);
用户路线:
const express=require('express');
const router=express.Router();
const passport= require('passport');
const jwt=require('jsonwebtoken');
var userRoutes = express.Router();
var config = require('../../config'); // get our config file
var User = require('../../app/models/User'); // get our mongoose model
//
// ─── ROUTE TO REGISTER USER ──────────────────────────────────────────────────────────────────────
//
userRoutes.post('/signup', function(req, res) {
if (!req.body.email || !req.body.password || !req.body.firstname || !req.body.lastname || !req.body.gender || !req.body.isTrainer) {
res.json({ success: false, msg: 'set up required fields' });
} else {
var newUser = new User({
email: req.body.email,
password: req.body.password,
firstname: req.body.firstname,
lastname: req.body.lastname,
gender: req.body.gender,
isTrainer: req.body.isTraine
});
User.find({ email: req.body.email}, function(err, user){
if (err) {
res.send({ success: false, msg:'authentication error'})
}
else if (user.length != 0) {
res.send({success: false, msg:'Email already exists'})
console.log(user);
}else {
// save the user
newUser.save(function(err) {
if (err) {
console.log(err);
}else {
res.send({ success: true, msg: 'Your account created successfully! ' });
}
});
}
})
}
});
userRoutes.post('/signin', function(req, res) {
User.findOne({
email: req.body.email
}, function(err, user) {
if (err) throw err;
if (!user) {
res.send({ success: false, msg: 'Check your email' });
} else {
// check if password matches
user.comparePassword(req.body.password, function(err, isMatch) {
if (isMatch && !err) {
// if user is found and password is right create a token
var token = jwt.sign(user, config.secret,{
expiresIn: 30
});
// return the information including token as JSON
res.json({
success: true,
token: token,
username: user.username
});
} else {
res.send({ success: false, msg: 'Check your password!' });
}
});
}
});
});
userRoutes.get('/users', function(req, res) {
User.find({}, function(err, users) {
res.json(users);
});
});
module.exports= userRoutes;
ionic authProvider:
import { Injectable} from '@angular/core';
import {Http, Headers} from '@angular/http';
import { Storage } from '@ionic/storage';
import 'rxjs/add/operator/map';
@Injectable()
export class AuthenticationProvider{
public token: any;
isLoggedin: boolean;
constructor(public http: Http, public storage: Storage) {
this.http = http;
this.isLoggedin = false;
this.token = null;
}
//check authentication to /api
checkAuthentication(){
return new Promise((resolve, reject)=> {
//load token if exist
this.storage.get('token').then((value)=> {
this.token = value;
let headers = new Headers();
headers.append('Authorisation', this.token);
this.http.get('http://localhost:1991/api', {headers:headers})
.subscribe(res => {
resolve(res);
}, (err) => {
reject(err);
});
});
});
}
storeUserCredentials(token) {
window.localStorage.setItem('token', token);
this.useCredentials(token);
}
loadUserCredentials() {
var token = window.localStorage.getItem('token');
this.useCredentials(token);
}
destroyUserCredentials() {
this.isLoggedin = false;
this.token = null;
window.localStorage.removeItem('token');
}
useCredentials(token) {
this.isLoggedin = true;
this.token = token;
}
isLogged(){
if(window.localStorage.getItem('token')){
return true
}else{
return false;
}
}
signin(usercreds){
let headers = new Headers();
headers.append('Content-Type', 'application/json');
return new Promise((resolve,reject) => {
this.http.post('http://localhost:1991/user/signin', usercreds, {headers: headers}).subscribe( data => {
if(data.json().success){
this.storeUserCredentials(data.json().token);
resolve(true);
}
else
reject(data.json().msg);
});
});
}
signup(details){
let headers = new Headers();
headers.append('content-Type', 'application/json');
return new Promise((resolve,reject) =>{
this.http.post('http://localhost:1991/user/signup', details, {headers: headers}).subscribe(data =>{
if(data.json().success){
resolve(true)
}else{
reject(data.json().msg);
}
});
});
}
logout(){
this.destroyUserCredentials();
}
}
ionic login.ts
import { Component, trigger, state, style, transition, animate, keyframes } from '@angular/core';
import { AuthenticationProvider } from '../../providers/authentication/authentication';
import { NavController,AlertController, NavParams, LoadingController } from 'ionic-angular';
import { SignupPage } from '../signup/signup';
import { MainPage } from '../main/main';
/**
* Generated class for the LoginPage page.
*
* See http://ionicframework.com/docs/components/#navigation for more info
* on Ionic pages and navigation.
*/
@Component({
selector: 'page-login',
templateUrl: 'login.html',
animations: [
//For the logo
trigger('flyInBottomSlow', [
state('in', style({
transform: 'translate3d(0,0,0)'
})),
transition('void => *', [
style({transform: 'translate3d(0,2000px,0'}),
animate('2000ms ease-in-out')
])
]),
//For the background detail
trigger('flyInBottomFast', [
state('in', style({
transform: 'translate3d(0,0,0)'
})),
transition('void => *', [
style({transform: 'translate3d(0,2000px,0)'}),
animate('1000ms ease-in-out')
])
]),
//For the login form
trigger('bounceInBottom', [
state('in', style({
transform: 'translate3d(0,0,0)'
})),
transition('void => *', [
animate('2000ms 200ms ease-in', keyframes([
style({transform: 'translate3d(0,2000px,0)', offset: 0}),
style({transform: 'translate3d(0,-20px,0)', offset: 0.9}),
style({transform: 'translate3d(0,0,0)', offset: 1})
]))
])
]),
//For login button
trigger('fadeIn', [
state('in', style({
opacity: 1
})),
transition('void => *', [
style({opacity: 0}),
animate('1000ms 2000ms ease-in')
])
])
]
})
export class LoginPage {
logoState: any = "in";
cloudState: any = "in";
loginState: any = "in";
formState: any = "in";
usercreds = {
email: '',
password: ''
};
loadinglogin: any;
loadingfailed: any;
fbUserData: any;
constructor(private alertCtrl: AlertController, public navCtrl: NavController, public navParams: NavParams, public authenticationProvider: AuthenticationProvider, public loadingCtrl: LoadingController) {
this.navCtrl = navCtrl;
}
ionViewDidLoad() {
this.showLoaderOnlogin();
this.authenticationProvider.checkAuthentication().then((res) => {
this.loadinglogin.dismiss();
}, (err) => {
console.log("Not already authorized");
this.loadinglogin.dismiss();
});
console.log('ionViewDidLoad LoginPage');
}
login(usercreds){
this.authenticationProvider.signin(usercreds).then(data => {
this.navCtrl.setRoot(MainPage);
}).catch(msg => {
this.presentAlert(msg);
});
}
opensignUpPage(){
this.navCtrl.push(SignupPage,{}, {animate: true, direction: 'back'} );
}
showLoaderOnlogin(){
this.loadinglogin = this.loadingCtrl.create({
content: 'Authenticating...',
showBackdrop: true,
});
this.loadinglogin.present();
}
presentAlert(msg) {
let alert = this.alertCtrl.create({
title: 'Authentication failed',
message:msg,
buttons: ['Ok'],
cssClass:'alert-faild'
});
alert.present();
}
}
令牌已成功存储在本地存储中,我想检查它是否仍然有效将其从localStorage和setRoot页面删除到登录页面,如果仍然有效则将其保存并将setRoot页面保存到主页面。
答案 0 :(得分:0)
jwt令牌在构建时没有到期功能。你可以信任一个jwt令牌。但如果你还想要这样的话。然后你可以在你用来编码innto jwt token的对象中添加一个时间字段。
profile = {'field1':'value1', expire':'time'}
result.token= jwt.encode(profile, config.secret);
当您在此时将令牌解码回对象时,查看该对象是否已过期。
jwt.verify(token, app.get('superSecret'), function(err, decoded) {
check decoded.expire here.
}