共计 6300 个字符,预计需要花费 16 分钟才能阅读完成。
可用资源
-
NPM 包
@authing/nextjs
:https://github.com/Authing/authing-nextjs@authing/remix
:https://github.com/Authing/authing-remix
-
论坛帮忙
- Next.js 问题反馈:https://forum.authing.cn/t/topic/601
- Remix 问题反馈:https://forum.authing.cn/t/topic/602
Authing 用户池配置
该局部基本上大部分框架是通用的,首先须要创立用户池利用。
填写利用名称,能够获取到 App ID 和 App Secret 配置。
配置回调地址,留神如果是应用 Next.js 框架,倡议用 /api/xxx
的前缀(所有接口服务必须在该目录下),如果是 Remix 框架则随便。
这步的配置不焦急,能够依据后续我的项目来进行更改。
受权配置,默认即可。目前 SDK 提供的形式也是通过 code
。(后续可能会增加更多灵便的抉择,如果你对此有理解,能够集成本人的鉴权回调。)
Next.js
装置依赖
npm install --save @authing/nextjs iron-session swr
# or
yarn add @authing/nextjs iron-session swr
配置环境变量
如 config/index.ts
,或者其余中央。倡议不要疏忽该步骤,将用到的变量参数对立治理。
export const clientId =
process.env.AUTHING_CLIENT_ID || '61e4da899687d7055442f6b7';
export const clientSecret = process.env.AUTHING_CLIENT_SECRET || '';
export const appDomain =
process.env.AUTHING_CLIENT_DOMAIN || 'https://remix.authing.cn';
export const redirectUri =
process.env.AUTHING_REDIRECT_URI || 'http://localhost:3000/authing/callback';
export const logoutRedirectUri =
process.env.AUTHING_LOGOUT_REDIRECT_URI || 'http://localhost:3000/';
创立 SessionStorage
创立 lib/session.ts
。示例中应用的是 iron-session
进行创立。
创立登录、登记和回调 API
留神:登录 URL 为 /api/login
,登记为 /api/logout
创立 pages/api/login.ts
:
import {createLoginApi} from '@authing/nextjs';
import {appDomain, clientId, redirectUri} from '../../config';
export default createLoginApi({
appDomain,
clientId,
redirectUri,
scope: 'openid roles username phone profile'
});
创立 pages/api/logout.ts
:
import {withIronSessionApiRoute} from 'iron-session/next';
import {createLogoutApi} from '@authing/nextjs';
import {appDomain, logoutRedirectUri} from '../../config';
import {sessionOptions} from '../../lib/session';
export default withIronSessionApiRoute(
createLogoutApi({
appDomain,
redirectUri: logoutRedirectUri
}),
sessionOptions
);
创立 pages/api/callback.ts
:
import {createCallbackApi} from '@authing/nextjs';
import {appDomain, clientId, clientSecret} from '../../config';
import {withIronSessionApiRoute} from 'iron-session/next';
import {sessionOptions} from '../../lib/session';
export default withIronSessionApiRoute(
createCallbackApi({
appDomain,
clientId,
clientSecret,
// 登录失败返回登录页
failureRedirect: '/error',
successRedirect: '/ssr'
}),
sessionOptions
);
在 SSR 中应用
参考 pages/ssr.tsx
:
import {withIronSessionSsr} from 'iron-session/next';
import {sessionOptions} from '../lib/session';
export const getServerSideProps = withIronSessionSsr(async function ({
req,
res
}) {
const user = req.session.user;
if (user === undefined) {res.setHeader('location', '/api/login');
res.statusCode = 302;
res.end();
return {
props: {user: { isLoggedIn: false}
}
};
}
return {props: { user: req.session.user}
};
},
sessionOptions);
在 SSG 中应用
创立接口:pages/api/me.ts
:
import {withIronSessionApiRoute} from 'iron-session/next';
import {sessionOptions} from '../../lib/session';
import {NextApiRequest, NextApiResponse} from 'next';
export type User = {
isLoggedIn: boolean;
username: string;
};
export default withIronSessionApiRoute(userRoute, sessionOptions);
async function userRoute(req: NextApiRequest, res: NextApiResponse<User>) {if (req.session.user) {
// in a real world application you might read the user id from the session and then do a database request
// to get more information on the user if needed
res.json({
...req.session.user,
isLoggedIn: true
});
} else {
res.json({
isLoggedIn: false,
username: ''
});
}
}
创立钩子 hooks/use-user.ts
:
import {useEffect} from 'react';
import Router from 'next/router';
import useSWR from 'swr';
import {User} from '../pages/api/me';
export default function useUser({
redirectTo = '',
redirectIfFound = false
} = {}) {const { data: user, error} = useSWR<User>('/api/me');
useEffect(() => {// if no redirect needed, just return (example: already on /dashboard)
// if user data not yet there (fetch in progress, logged in or not) then don't do anything yet
if (!redirectTo || !user) return;
if (
// If redirectTo is set, redirect if the user was not found.
(redirectTo && !redirectIfFound && !user?.isLoggedIn) ||
// If redirectIfFound is also set, redirect if the user was found
(redirectIfFound && user?.isLoggedIn)
) {Router.push(redirectTo);
}
}, [user, redirectIfFound, redirectTo]);
return {user, error};
}
创立页面 pages/sg.tsx
:
import useUser from '../hooks/use-user';
import Link from 'next/link';
// Make sure to check https://nextjs.org/docs/basic-features/layouts for more info on how to use layouts
export default function SgProfile() {const { user} = useUser({redirectTo: '/api/login'});
return (
<>
<nav>
<Link href='/ssr'>SSR</Link> | <Link href='/api/logout'>Logout</Link>
</nav>
{user && (
<>
<pre>{JSON.stringify(user, null, 2)}</pre>
</>
)}
</>
);
}
小结
从下面的例子中能够看出,在 Next.js 中应用,须要留神以下几点:
-
你会装置更多的依赖
- 你须要本人抉择第三方的 Session 存储计划,能够是 Cookie Session,也能够是 Redis 或者 JWT
- 你须要优化你的我的项目代码,辨别好不同的页面类型。一般页面、SSR 页面、SSG 页面和 API(在
/api
目录下) - 如果不应用 SSR 你可能会依赖 SWR 之类的库去优化你页面上的申请
本示例我的项目代码下载:CSDN
Remix
装置依赖
npm install --save @authing/remix
# or
yarn add @authing/remix
配置环境变量
如 app/config.server.ts
,或者其余中央。倡议不要疏忽该步骤,将用到的变量参数对立治理。
export const clientId =
process.env.AUTHING_CLIENT_ID || '61e4da899687d7055442f6b7';
export const clientSecret = process.env.AUTHING_CLIENT_SECRET || '';
export const appDomain =
process.env.AUTHING_CLIENT_DOMAIN || 'https://remix.authing.cn';
export const redirectUri =
process.env.AUTHING_REDIRECT_URI || 'http://localhost:3000/authing/callback';
export const logoutRedirectUri =
process.env.AUTHING_LOGOUT_REDIRECT_URI || 'http://localhost:3000/';
创立 SessionStorage
创立 app/services/session.server.ts
。
留神,Remix v1.1.3(截止目前,2022 年 2 月)及之前版本请不要应用 CookieSession,会存在 UTF-8 编码解析谬误。
创立登录页、登记页和回调页
创立 app/routes/login.tsx
:
import {createLoginLoader} from '@authing/remix';
import {appDomain, clientId, redirectUri} from '~/config.server';
export const loader = createLoginLoader({
appDomain,
clientId,
redirectUri,
scope: 'openid roles username phone profile'
});
创立 app/routes/logout.tsx
:
import {createLogoutLoader} from '@authing/remix';
import {sessionStorage} from '~/services/session.server';
import {appDomain, logoutRedirectUri} from '~/config.server';
export const loader = createLogoutLoader({
redirectUri: logoutRedirectUri,
appDomain,
sessionStorage
});
创立 app/routes/authing/callback.tsx
:
import {createCallbackLoader} from '@authing/remix';
import {sessionStorage} from '~/services/session.server';
import {appDomain, clientId, clientSecret} from '~/config.server';
export const loader = createCallbackLoader({
appDomain,
clientId,
clientSecret,
// 登录失败返回登录页
failureRedirect: '/error',
successRedirect: '/user',
sessionStorage
});
在路由中应用
import {isAuthenticated} from '@authing/remix';
export const loader: LoaderFunction = async ({request}) => {const user = await isAuthenticated(request, sessionStorage);
return json(user || {});
};
// 在页面中应用
const user = useLoaderData();
小结
比照来看,第一步就发现了 Remix 不须要过多的依赖,内置了一些罕用的后端性能。
但很可怜的是,在目前的版本(Remix v1.1.3),是存在重大 Bug 的,Cookie 不能存储 UTF-8 字符串,会导致登录信息无奈读取。
本示例我的项目代码下载:CSDN
如果你对 Remix 全栈框架感兴趣,能够关注我的博客:https://willin.wang