我正在使用NodeJS,Express,React和Redux进行项目。
我在导航中显示当前登录用户的用户名。
我目前正在编码用户数据更新,但是在编辑数据后,用户名在导航栏中不会更改。
我知道这是因为登录用户的令牌会记住旧数据。我使用PassportJWT。编辑用户数据(editAdmin
操作)后如何在Passport中更新我的用户数据?
快速路线更新用户数据:
const saltRounds = 10;
Admin.findOne({ name: req.params.name }, (err, admin) => {
if (err) {
res.status(400).json({
errors: err
})
}
if (admin) {
bcrypt.hash(req.body.password, saltRounds, function (err, hash) {
if (err) {
res.status(400).json({
errors: err
})
}
let hashPassword = hash;
const updateAdmin = {
name: req.body.name,
email: req.body.email,
password: req.body.password === "" ? admin.password : hashPassword,
role: req.body.role
}
Admin.findOneAndUpdate(
{ _id: admin.id },
{ $set: updateAdmin },
{ new: true, useFindAndModify: false }
).then(admin => res.json(admin))
.catch(err => res.json({
errors: err
}));
});
}
})
})
Navbar.js
import React from 'react';
import { Link } from 'react-router-dom';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { logoutUser } from '../../actions/authActions';
class Navbar extends React.Component {
render() {
const { isAuthenticated, user } = this.props.auth;
return (
<nav className="navbar is-dark" role="navigation" aria-label="main navigation">
<div className="navbar-brand">
<Link to="/" className="navbar-item">
<h2>ADMIN PANEL</h2>
</Link>
<button className="navbar-burger burger" aria-label="menu" aria-expanded="false"
data-target="navbarBasicExample">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</button>
</div>
<div id="navbarBasicExample" className="navbar-menu">
<div className="navbar-start">
{isAuthenticated && <Link to="/admins" className="navbar-item"> Admins List</Link>}
</div>
{!isAuthenticated &&
<div className="navbar-end">
<div className="navbar-item">
<div className="buttons">
{/* <a href="#" className="button is-danger">
<strong>Sign up</strong>
</a> */}
<Link className="button is-danger" to="/login">Login</Link>
</div>
</div>
</div>
}
{isAuthenticated &&
<div className="navbar-end">
<div className="navbar-item">
<figure className="image is-24x24">
<img className="is-rounded" src={user.avatar} alt="profile-img" />
</figure>
<p className="navbar-item has-text-white">{user.name}</p>
<div className="buttons">
<button onClick={this.props.logoutUser} className="button is-danger">Logout</button>
</div>
</div>
</div>
}
</div>
</nav>
)
}
}
Navbar.propTypes = {
logoutUser: PropTypes.func.isRequired,
auth: PropTypes.object.isRequired
}
const mapStateToProps = state => ({
auth: state.auth
})
export default connect(mapStateToProps, { logoutUser })(Navbar);
authAction.js
import { GET_ERRORS, SET_CURRENT_USER } from './types';
import axios from 'axios';
import setAuthToken from '../utils/setAuthToken';
import jwt_decode from 'jwt-decode';
export const loginUser = (userData) => dispatch => {
axios.post('/api/users/login', userData)
.then(res => {
// Save to localStorage
const { token } = res.data;
// Set token to lS
localStorage.setItem('jwtToken', token);
// Set token to Auth header
setAuthToken(token);
const decoded = jwt_decode(token);
dispatch(setCurrentUser(decoded));
})
.catch(err => {
dispatch({
type: GET_ERRORS,
payload: err.response.data
});
});
}
export const setCurrentUser = decoded => {
return {
type: SET_CURRENT_USER,
payload: decoded
}
}
export const logoutUser = () => dispatch => {
localStorage.removeItem('jwtToken');
setAuthToken(false);
dispatch(setCurrentUser({}));
}
authReducer.js
import { SET_CURRENT_USER } from '../../actions/types';
import isEmpty from '../../validation/isEmpty';
const initialState = {
isAuthenticated: false,
user: {}
}
export default function (state = initialState, action) {
const { type, payload } = action;
switch (type) {
case SET_CURRENT_USER:
return {
...state,
isAuthenticated: !isEmpty(payload),
user: payload
}
default:
return state;
}
}
编辑:
护照配置
let JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt,
secret = require('../config/keys'),
User = require('../models/Admin/Admin');
let opts = {};
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
opts.secretOrKey = secret.secret;
module.exports = passport => {
passport.use(new JwtStrategy(opts, (jwt_payload, done) => {
User.findById(jwt_payload.id)
.then(user => {
if (user) {
return done(null, user);
}
return done(null, false);
})
.catch(err => {
console.log(err);
});
}));
};
adminsReducer(等于用户):
import { GET_ADMINS, GET_ADMIN, EDIT_ADMIN } from '../../actions/types';
const initialState = {
admins: [],
admin: null
};
export default function (state = initialState, action) {
const { type, payload } = action;
switch (type) {
case GET_ADMINS:
return {
...state,
admins: payload
}
case GET_ADMIN:
return {
...state,
admin: payload
}
case EDIT_ADMIN:
return {
...state,
admin: payload
}
default:
return state;
}
}
adminsAction:
import axios from 'axios';
import { GET_ADMINS, GET_ERRORS, GET_ADMIN, EDIT_ADMIN } from './types';
export const editAdmin = (name, editData, history) => dispatch => {
axios.post(`/api/admins/edit/${name}`, editData)
.then(res => {
dispatch({type: EDIT_ADMIN, payload: res.data});
history.push('/');
})
.catch(err => dispatch({
type: GET_ERRORS,
payload: err.response
}))
}
答案 0 :(得分:0)
您需要在编辑用户数据后在服务器端重新生成令牌,然后在响应中将其传递给客户端:
Admin.findOneAndUpdate(
{ _id: admin.id },
{ $set: updateAdmin },
{ new: true, useFindAndModify: false }
)
.then(admin => {
// generateJWT is a function you should replace with the one you are
// actually using to generate a token
const token = generateJWT(admin)
return res.json({ admin, token })
})
.catch(err => res.json({ errors: err }))
然后存储JWT并从adminsAction.js中分发setCurrentUser(decoded)
,例如:
import axios from 'axios'
import { setCurrentUser } from './authAction'
import setAuthToken from '../utils/setAuthToken'
import { GET_ADMINS, GET_ERRORS, GET_ADMIN, EDIT_ADMIN } from './types'
export const editAdmin = (name, editData, history) => dispatch => {
axios.post(`/api/admins/edit/${name}`, editData)
.then(res => {
dispatch({ type: EDIT_ADMIN, payload: res.data.admin })
// Save to localStorage
localStorage.setItem('jwtToken', res.data.token)
// Set token to Auth header
setAuthToken(res.data.token)
// Set to Redux state
dispatch(setCurrentUser(res.data.admin))
history.push('/')
})
.catch(err => dispatch({
type: GET_ERRORS,
payload: err.response
}))
}