【问题标题】:React Application + API authenticationReact 应用 + API 认证
【发布时间】:2019-01-16 16:29:57
【问题描述】:

我设置了一个 API 来访问我的后端,并实现了快速会话来验证用户身份。

当使用 Postman 登录,然后访问受保护的 GET 请求时,它工作正常。

但我正在构建的 React SPA 在登录后似乎无法使用会话进行身份验证。

我尝试了很多我在网上找到的建议(更改 CORS 标头、在 React 中使用显式 cookie 设置、更改我存储会话的方式……)但似乎都没有解决问题。

我会尝试包含相关的代码 sn-ps:

服务器端(REST API)

会话和 CORS 中间件:

//Session Middleware
api.use(session({
    genid: (req) => {
        console.log('Inside session middleware');
        console.log(req.sessionID)
        return uuid()
    },
    cookie: {
        maxAge: 60000
    },
    secret:"123",
    resave:false,
    saveUninitialized:true,
        store: new MongoStore({
        mongooseConnection:db,
        clear_interval: 3600
    })
}));

// CORS
api.use(function(req,res,next){
    res.header("Access-Control-Allow-Origin", "http://localhost:3000");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    res.header("Access-Control-Allow-Credentials", "true")
    next();
})

登录功能和护照验证:

exports.login = (req,res,next) => {
    passport.authenticate('local',(err,user,info) =>{
        //... (login handling)
    })(req,res,next);
}

// Passport Middleware
passport.use(new LocalStrategy(
    (username, password, done) => {
        Promotor.findOne({username:username,password:password}, (err,user) =>{
            if (err) {
                done(err,null);
            }
            if (!user){
                done(null,false,{message:'Invalid Credentials!'})
            } else {
                done(null,user)
            }
        });
    }
));

// Passport serializing
passport.serializeUser((user,done) => {
    done(null,user._id);
});

passport.deserializeUser((id,done) => {
    Promotor.findById(id,function(err,user){
        if(err){
            done(err,false);
        } else {
            done(null,user);
        }
    })
})

受保护的 GET 函数

(isAuthenticated() 在我的 SPA 中使用 axios 时返回 false)

exports.getNameById = (req,res) => {
    console.log(req.session)
    console.log(req._passport)
    if(!req.isAuthenticated()){ //RETURNS FALSE IN REACT & TRUE IN POSTMAN
        return res.status(401).send();
    }

    return controller.getDocumentById(Promotor,'firstname lastname',req,res);
}

客户端(React SPA)

Axios 请求登录

(适用于 Postman 和应用程序,并正确创建会话)

handleSubmit(e){
  console.log("Trying To log in");
  axios
    .post(`${api_url}/promotor/login`,{username: this.state.username, password:this.state.password})
    .then( (res) => {
      if (res.status === 200) {
        console.log(res);
        this.setState(() => ({toClientHome: true, id:res.data.id}));
      }
    });
  e.preventDefault();
}

Axios 请求访问受保护的 GET 请求

(设置会话cookie时GET请求在邮递员中有效,但不适用于axios)

getFullName(id) {
  axios
    .get(`${api_url}/promotor/name/${id}`,{
      withCredentials: true
    })
    .then((res) => {
      //... rest of the code
    });
}

【问题讨论】:

  • 我推荐使用令牌系统进行身份验证,而不是基于 cookie 的会话。 JWT 目前是一个不错的选择。
  • @DatTran 是的,在搜索答案时,我了解到 JWT 可能是比我目前使用的基于会话的方法更好的解决方案。感谢您的建议!

标签: reactjs passport.js axios express-session


【解决方案1】:

能否请将您的 cors 中间件代码放在文件顶部(在所有导入之后)!!

api.use(function(req,res,next){
    res.header("Access-Control-Allow-Origin", "http://localhost:3000");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    res.header("Access-Control-Allow-Credentials", "true")
    next();
})

然后再试一次。

【讨论】:

  • 谢谢,这个解决方案结束了我几个小时的研究!您介意详细说明为什么必须这样做吗?
  • 在定义路由之前,我们会在 express 中使用 cors 中间件功能,以便它允许不同资源访问您定义的域。如果不授予访问权限,您如何获得资源。在Javascript中文件是从上到下逐行编译的。
猜你喜欢
  • 2016-03-21
  • 2015-07-07
  • 2021-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-25
  • 2014-08-13
  • 2015-08-08
相关资源
最近更新 更多