JS:如何通过重定向功能将url传递给登录功能
JS: How to pass url through redirect function to login function
在我的 React/nextJS 应用程序中,我正在检查 getInitialProps
静态函数中的有效令牌。
我将其用作 HOC - 但在这种情况下这无关紧要。
如果令牌无效(或丢失),用户将被重定向到登录页面。这是通过 redirect
函数完成的,如下所示。到目前为止,还不错。
如何将用户从中重定向到登录组件的页面的 url 传递给登录组件?
如果用户未登录并且正在调用 http://my-server.com/any-page, he gets redirected to the index page (http://my-server.com): There will be a login form. If the login is successful, I would like to redirect him back to the first called page: 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
})
}
})
}
您需要的是 react-router
或更具体地说 react-router-dom
包。如果您了解它的工作方式,那就轻而易举了。
对于您的方案,在未通过身份验证时不调用 redirect()
,而是使用 <Redirect to={url} />
。这会自动执行浏览器 url 替换和更新全局 state.You'' 已经巧妙地分配了一个 url 匹配任何特殊情况的陷阱。例如。 "/login/ref/:toref" 将是处理 url "/login/ref/{specialaccess}" 的基本表达式。
注意“:”。它是参数匹配器,需要在登录组件中检索 url。
正如他们所说,一行代码抵得上一千个单词。所以我做了一个小项目来充分展示如何实现 react-router-dom
.
的一些重要功能
在此处查找:https://codesandbox.io/s/y0znxpk30z
项目中访问https://y0znxpk30z.codesandbox.io/specialaccess through the browser simulator, you get redirected to the special access page after becoming authenticated on login. Otherwise if you access https://y0znxpk30z.codesandbox.io登录后跳转到首页
记住,你必须像这样包装任何需要全局属性 withRouter
的组件:
export default withRouter(component-name);
这在每个组件中提供了 this.props.location
、this.props.history
和 this.props.match
,因为我们已经将应用程序的根组件放置在包中默认可用的 <BrowserRouter><BrowserRouter/>
HOC 中。
使用 this.props.match
我们可以轻松地引用并重定向回我们之前在 ":toref" 中指定的 url。
您可以阅读更多关于 react-router
here
jwt.verify
函数以异步回调方式使用
这种风格更适合 WrappedComponent
的 componentDidMount
生命周期方法。
为其传递回调意味着 isValid
的值可能永远不会足够早地更新,即使客户端 JWT 令牌是有效的并且用户将始终被重定向。
我建议使用不带回调的同步变体(测试以比较渲染包装组件之前的时间)。更好的是,将 jwt.verify
回调样式转换为 returns 承诺的函数,以便它可以在 await
表达式中解析,因为 getInitialProps
是 async
功能。
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}`);
将 return 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>
)
而不是 Router.replace,尝试使用从 HOC 传入的 return url Router.push。希望这有帮助。
在您的 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)
希望对您有所帮助,请告诉我。
在我的 React/nextJS 应用程序中,我正在检查 getInitialProps
静态函数中的有效令牌。
我将其用作 HOC - 但在这种情况下这无关紧要。
如果令牌无效(或丢失),用户将被重定向到登录页面。这是通过 redirect
函数完成的,如下所示。到目前为止,还不错。
如何将用户从中重定向到登录组件的页面的 url 传递给登录组件?
如果用户未登录并且正在调用 http://my-server.com/any-page, he gets redirected to the index page (http://my-server.com): There will be a login form. If the login is successful, I would like to redirect him back to the first called page: 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
})
}
})
}
您需要的是 react-router
或更具体地说 react-router-dom
包。如果您了解它的工作方式,那就轻而易举了。
对于您的方案,在未通过身份验证时不调用 redirect()
,而是使用 <Redirect to={url} />
。这会自动执行浏览器 url 替换和更新全局 state.You'' 已经巧妙地分配了一个 url 匹配任何特殊情况的陷阱。例如。 "/login/ref/:toref" 将是处理 url "/login/ref/{specialaccess}" 的基本表达式。
注意“:”。它是参数匹配器,需要在登录组件中检索 url。
正如他们所说,一行代码抵得上一千个单词。所以我做了一个小项目来充分展示如何实现 react-router-dom
.
在此处查找:https://codesandbox.io/s/y0znxpk30z
项目中访问https://y0znxpk30z.codesandbox.io/specialaccess through the browser simulator, you get redirected to the special access page after becoming authenticated on login. Otherwise if you access https://y0znxpk30z.codesandbox.io登录后跳转到首页
记住,你必须像这样包装任何需要全局属性 withRouter
的组件:
export default withRouter(component-name);
这在每个组件中提供了 this.props.location
、this.props.history
和 this.props.match
,因为我们已经将应用程序的根组件放置在包中默认可用的 <BrowserRouter><BrowserRouter/>
HOC 中。
使用 this.props.match
我们可以轻松地引用并重定向回我们之前在 ":toref" 中指定的 url。
您可以阅读更多关于 react-router
here
jwt.verify
函数以异步回调方式使用
这种风格更适合 WrappedComponent
的 componentDidMount
生命周期方法。
为其传递回调意味着 isValid
的值可能永远不会足够早地更新,即使客户端 JWT 令牌是有效的并且用户将始终被重定向。
我建议使用不带回调的同步变体(测试以比较渲染包装组件之前的时间)。更好的是,将 jwt.verify
回调样式转换为 returns 承诺的函数,以便它可以在 await
表达式中解析,因为 getInitialProps
是 async
功能。
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}`);
将 return 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>
)
而不是 Router.replace,尝试使用从 HOC 传入的 return url Router.push。希望这有帮助。
在您的 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
:
this.redirectUrl = (req && req.query['redirect']) ? decodeURIComponent(req.query['redirect']) : '/'
终于
window.location.assign(this.redirectUrl)
希望对您有所帮助,请告诉我。