JS:如何通过重定向功能将url传递给登录功能

Posted

技术标签:

【中文标题】JS:如何通过重定向功能将url传递给登录功能【英文标题】:JS: How to pass url through redirect function to login function 【发布时间】:2019-04-20 16:41:33 【问题描述】:

在我的 React/nextJS 应用程序中,我正在检查 getInitialProps 静态函数中的有效令牌。 我将其用作 HOC - 但在这种情况下这无关紧要。

如果令牌无效(或丢失),用户将被重定向到登录页面。这是由redirect 函数完成的,如下所示。到目前为止,一切顺利。

如何将用户从其重定向到登录组件的页面的 url 传递?

如果用户没有登录并且正在调用类似 http://my-server.com/any-page 的东西,他会被重定向到索引页面 (http://my-server.com):会有一个登录表格。如果登录成功,我想将他重定向回第一个调用页面:http://my-server.com/any-page

    以未登录用户的身份调用受限页面 重定向到索引登录页面 登录后重定向回1的页面。

我不知道如何将此信息传递给登录功能...

with-server-props.js

export default WrappedComponent =>
  class extends Component 
    static async getInitialProps (context) 
      const  req, pathname  = context
      let isValid = false

      if (req && req.headers) 
        const cookies = req.headers.cookie
        if (typeof cookies === 'string') 
          const cookiesJSON = jsHttpCookie.parse(cookies)
          initProps.token = cookiesJSON['auth-token']
          if (cookiesJSON['auth-token']) 
            jwt.verify(cookiesJSON['auth-token'], secret, (error, decoded) => 
              if (error) 
                console.error(error)
               else 
                isValid = true
              
            )
          
        
      

      // Redirect to index (=login) page if isValid is false
      if (!isValid && pathname && pathname !== '/') 
        redirect(context, pathname ? '/?ref=' + pathname : '/')
      

      return initProps
    
    render () 
      return <WrappedComponent ...this.props />
    
  

redirect.js

import Router from 'next/router'

export default (context, target) => 
  if (context.res) 
    // server
    context.res.writeHead(303,  Location: target )
    context.res.end()
   else 
    // In the browser, we just pretend like this never even happened ;)
    Router.replace(target)
  

pages/index.js

在 index.js 上有 submit 函数来登录用户。在那里,用户应该被重定向到初始页面:

_onSubmit (event) 
  this.props.loginMutation(
    variables:  username, password 
  ).then(response => 
    const token = response.data.token
    if (token) 
      Cookies.set('auth-token', token,  expires: 1 )
      this.props.client.resetStore().then(() => 
        window.location.assign('/') // <-- Redirect to initial called page
      )
    
  )

【问题讨论】:

可能只是将初始url存储到本地/会话存储中,登录后查看? 在 react 中传递数据最优雅的方式是通过 props。但是 'next/router' 正在做路由,所以你无法通过 props 传递数据。而且由于您是替换而不是推送,因此它也不会保存在“历史记录”中。除了 props,还有多种传递数据的方式,例如“全局变量”、“本地存储”、“redux 等第三方存储”。我认为使用“redux”或其他商店是更好的数据共享方式。 【参考方案1】:

您需要的是 react-router 或更具体地说是 react-router-dom 包。如果您了解它的工作方式,那就轻而易举了。

对于您的场景,您可以使用&lt;Redirect to=url /&gt;,而不是在未通过身份验证时调用redirect()。这会自动替换浏览器 url 并更新全局状态。您已经巧妙地分配了一个匹配任何特殊情况的 url 以进行陷阱。例如。 "/login/ref/:toref" 将是处理 url "/login/ref/specialaccess" 的基本表达式。

注意“:”。它是参数匹配器,需要在登录组件中检索 url。

正如他们所说,一行代码值一千字。所以我做了一个小项目来充分展示如何实现react-router-dom的一些重要特性。

在这里找到:https://codesandbox.io/s/y0znxpk30z

在项目中,当您尝试通过浏览器模拟器访问https://y0znxpk30z.codesandbox.io/specialaccess 时,在登录时通过身份验证后,您会被重定向到特殊访问页面。否则,如果您访问https://y0znxpk30z.codesandbox.io,那么您会在登录后被重定向到主页。

请记住,您必须像这样包装任何需要全局道具 withRouter 的组件:

export default withRouter(component-name);

这会在每个组件中提供this.props.locationthis.props.historythis.props.match,因为我们已经将应用程序的根组件放置在包中默认可用的&lt;BrowserRouter&gt;&lt;BrowserRouter/&gt; HOC 中。

使用this.props.match,我们可以轻松引用并重定向回我们之前在 ":toref" 中指定的 url。

你可以阅读更多关于react-routerhere

【讨论】:

听起来不错。我不太确定,但是 nextJS 也有一个路由模块。如果是这种情况,是否可以以类似的方式使用它? 可能类似于github.com/zeit/next.js/#using-a-higher-order-component ? 是的,nextJS 有它的路由模块,但它不像react-router 那样处理复杂的路由。正如你可以从这里读到的,react-etc.net/entry/next-js-to-adopt-react-routerreact-router 仍将被 nextJS 采用。所以,如果你在前端做动态路由,react-router 仍然是你最好的选择,至少据我所知。【参考方案2】:

jwt.verify函数以异步回调方式使用。

这种风格更适合 WrappedComponentcomponentDidMount 生命周期方法。 为其传递回调意味着 isValid 的值可能永远不会更新得足够早,即使客户端 JWT 令牌是有效的令牌并且用户将始终被重定向。

我建议使用不带回调的同步变体(测试以比较包装组件被渲染之前的时间)。更好的是,将jwt.verify 回调样式转换为返回承诺的函数,以便它可以在await 表达式中解析,因为getInitialPropsasync 函数。

if (req && req.headers) 
  const cookies = req.headers.cookie
  if (typeof cookies === 'string') 
    const cookiesJSON = jsHttpCookie.parse(cookies)
    initProps.token = cookiesJSON['auth-token']
    if (cookiesJSON['auth-token']) 
      try 
         const payload = jwt.verify(cookiesJSON['auth-token'], secret)
         if (payload) 
            isValid = true
         
       catch (err) 
         isValid = false
      
    
  

现在在_onsubmit方法重定向用户,你可以得到WrappedComponent.getInitialProps中设置的ref查询参数值,并用它来重定向用户。

const ref = new URLSearchParams(location.search).get('ref');
location.assign(`/$ref`);

【讨论】:

【参考方案3】:

将返回 url 作为查询参数或位置状态传递给登录页面。我在 Next.js 的文档页面上找到了一个使用查询参数推送路由的示例。

import Router from 'next/router'

const handler = () => 
  Router.push(
    pathname: '/about',
    query:  name: 'Zeit' 
  )


export default () => (
  <div>
    Click <span onClick=handler>here</span> to read more
  </div>
)

尝试使用从 HOC 传入的返回 url,而不是 Router.replace。希望这会有所帮助。

【讨论】:

【参考方案4】:

在您的 with-server-props.js 中,将路径替换为 URL object

redirect(context, 
    pathname: '/',
    query:  redirect: req.url  // req.url should give you the current url on server side
  )

这会将重定向参数添加到 url https://example.com/?redirect=/about

然后您可以使用getInitialProps 获取任何页面上的 url 参数:

this.redirectUrl = (req && req.query['redirect']) ? decodeURIComponent(req.query['redirect']) : '/'

终于

window.location.assign(this.redirectUrl)

希望有帮助,告诉我。

【讨论】:

以上是关于JS:如何通过重定向功能将url传递给登录功能的主要内容,如果未能解决你的问题,请参考以下文章

重定向页面时如何将jwt存储在cookie中并将其传递给身份验证功能?

Django:登录后重定向到上一页

如何保护 Django 中的静态 HTML 文件? (重定向前需要登录)

登录后如何将WordPress用户重定向到上一页

登录重定向后如何传递用户名?

如何在Button的onClick功能之后或期间重定向?