简体   繁体   English

从服务器(节点和React)重定向后,在初始页面加载时获取会话Cookie数据

[英]Getting session cookie data on initial page load following a redirect from a server (Node and React)

I am trying to build a token system to allow authentication via an email link. 我正在尝试构建令牌系统,以允许通过电子邮件链接进行身份验证。 The flow I am thinking might work is... 我认为可能有效的流程是...

click email link (of the form site.com/login?token=hf74hf64&email=m@email.com) -> server checks the token is valid and the email is registered -> server redirects to '/' with a session cookie -> client acknowledges session cookie and authenticates the user 单击电子邮件链接(格式为site.com/login?token=hf74hf64&email=m@email.com)->服务器检查令牌是否有效并且电子邮件已注册->服务器使用会话cookie重定向到'/'->客户端确认会话cookie并验证用户身份

The last step is where I'm having trouble. 最后一步是我遇到麻烦了。 How do I detect from within my component that a session cookie is present? 如何从组件内部检测到存在会话cookie?

I was thinking of something like this in my React auth component: 我在我的React auth组件中想到了这样的事情:

class AuthenticatedComponent extends Component {
   componentWillMount() {
      if (cookie) {
         this.props.dispatch(authenticateUser())//.....
      }
   }
 }

Might this work, or do I need to make a separate fetch to the server and trigger the dispatch depending on the response? 可能会完成这项工作,还是我需要对服务器进行单独的fetch并根据响应触发分派?

We've implemented a very similar approach for our app. 我们为我们的应用实现了非常相似的方法。 For this to work, we handle all the login in Node and not in the actual components. 为此,我们在Node中而不是实际组件中处理所有登录。

  1. Check if token is provided in query string 检查查询字符串中是否提供了令牌
  2. Pass token to server to validate 将令牌传递到服务器以进行验证
  3. If token is valid, create the cookie as you would for a normal user/pass login 如果令牌有效,请像普通用户/密码登录一样创建cookie。
  4. Redirect call to original url, sans the token 重定向调用到原始URL,没有令牌

server.js server.js

// I abstracted the login functionality into one call since it's the same for us
var handleAuthRequest = function handleAuthRequest(auth_body, req, res, next) {
  request ({
    method: 'POST',
    uri: Constants.API_LOGIN_URL,
    body: auth_body,
    json: true
  }, (error, response, body) => {
    if (response.statusCode === 200) {
      // this makes a cookie with the response of the body (auth token)
      ssoUtils.generateCookies(body, res)
      // this redirects to the initial url, with the provided cookie. 
      // Assuming your router already doesn't allow certain components to be accessed 
      // without a cookie, it would work the same for the login_token auth too.
      res.redirect(req.url)
    }
    else {
      next();
    }
  })
}

// this needs to come before any other routes
app.use((req, res, next) => {
// check if login_token query string was provided
if (req.query.hasOwnProperty('login_token')) {
  var {login_token} = req.query
  // API call to server to validate token
  var jwtToken = jwt.sign({
    sub: login_token
  }, Constants.API_JWT_SECRET)
  // modify the redirect url to remove the token
  let parsed = url.parse(req.url)
  delete req.query['login_token']
  let newUrl = parsed.pathname + '?' + qs.stringify(req.query)
  req.url = newUrl
  // call the generic login handler
  return handleAuthRequest({link_token: jwtToken}, req, res, next)
} 

Assuming your server will return the same response from logging in or a valid link token, this would just redirect the call back to whatever your existing process is so no separate functionality client side is needed. 假设您的服务器将从登录中返回相同的响应或一个有效的链接令牌,那么这只会将调用重定向回现有的过程,因此不需要单独的功能客户端。 As you can see, we also sign the token in a JWT to ensure it's only accepted by the server if sent from our app. 如您所见,我们还在JWT中对令牌进行签名,以确保只有从我们的应用程序发送的令牌才能被服务器接受。

We use React Router to handle our client side routing. 我们使用React Router来处理客户端路由。 Your onEnter check for the initial route would look like this. 您的onEnter检查初始路线将如下所示。

routes.js routes.js

// token is passed in from our cookie by both the client and server 
module.exports = function (token, userAgent, originalUrl) {
  function isToken() {
    return token !== undefined && token !== null;
  }
  function ifNoTokenRedirect(nextState, replaceState) {
  // check if token is set from cookie
    if (!isToken()) {
      replaceState({ nextPathname: nextState.location.pathname}, '/signup?  redirect=' + originalUrl.pathname);
    }
  }
  return (
    // the actual routes
  )
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM