私のReact/nextJSアプリケーションでは、getInitialProps
静的関数で有効なトークンをチェックしています。私はこれをHOCとして使用していますが、この場合は問題になりません。
トークンが無効(または欠落)の場合、ユーザーはログインページにリダイレクトされます。これは、以下に示すようにredirect
関数によって実行されます。ここまでは順調ですね。
ユーザーがログインコンポーネントにリダイレクトされるページのURLを渡すにはどうすればよいですか?
ユーザーがログインしておらず、http://my-server.com/any-pageのようなものを呼び出している場合、ユーザーはにリダイレクトされます。インデックスページ(http://my-server.com):ログインフォームがあります。ログインに成功したら、最初に呼び出されたページにリダイレクトしたいと思います:http://my-server.com/any-page
この情報をログイン機能に渡す方法がわかりません...
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
})
}
})
}
あなたのwith-server-props.js
パスを RLオブジェクト に置き換えます
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-router
_、より具体的には_react-router-dom
_パッケージです。それがどのように機能するかを理解していれば、それは簡単です。
シナリオでは、認証されていないときにredirect()
を呼び出す代わりに、_<Redirect to={url} />
_を使用します。これにより、ブラウザのURLが自動的に置き換えられ、グローバル状態が更新されます。ただし、トラップする特殊なケースに一致するURLはすでに微妙に割り当てられています。例えば。 「/ login/ref /:toref」は、URL「/ login/ref/{specialaccess}」を処理するための基本式になります。
「:」に注意してください。これはparamsマッチャーであり、ログインコンポーネントで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.location
_、_this.props.history
_、および_this.props.match
_が提供されます。これは、アプリのルートコンポーネントがパッケージからデフォルトで利用可能な_<BrowserRouter><BrowserRouter/>
_ HOC内に既に配置されているためです。
_this.props.match
_を使用すると、以前に「:toref」で指定したURLを簡単に参照してリダイレクトできます。
_react-router
_ ここ についてもっと読むことができます
jwt.verify
関数は非同期コールバック方式で使用されます。
そのスタイルは、そのように使用されるcomponentDidMount
のWrappedComponent
ライフサイクルメソッドにより適しています。
コールバックを渡すと、クライアントJWTトークンが有効なトークンであり、ユーザーが常にリダイレクトされる場合でも、isValid
の値が十分に早く更新されない可能性があります。
コールバックなしで同期バリアントを使用することをお勧めします(ラップされたコンポーネントがレンダリングされるまでの時間を比較するためのテスト)。さらに良いことに、jwt.verify
コールバックスタイルをpromiseを返す関数に変換して、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}`);
戻り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から渡された戻りURLを使用してRouter.Pushを試してください。お役に立てれば。