2

我正在使用koa,koa-router和实现 Nextjs 服务kow-jwt,但我对它们的路由设置感到困惑。

我的项目有 2 个页面,一个是仪表板,另一个是登录。仪表板需要通过验证,登录不。如果身份验证失败,则将用户重定向到登录页面。

我在互联网上搜索,发现了一些示例如下,没有一个将它们链接在一起。

请给我一些建议,让他们一起工作。

const app = next({dev});
const handle = app.getRequestHandler();

app.prepare()
  .then(() => {
    const server = new koa();
    const router = new koaRouter();        

    router.get('/login', async ctx => {
        await app.render(ctx.req, ctx.res, '/login', ctx.query);
        ctx.respond = false;
    });

    router.get('/dashboard', 
        jwt({
            secret: config.graphqlSecret
        }),
        async ctx => {
            await app.render(ctx.req, ctx.res, '/dashboard', ctx.query);
            ctx.respond = false;
        }
    );

    // what is the purpose of this route?
    router.get('*', async ctx => {
        await handle(ctx.req, ctx.res);
        ctx.respond = false;
    });

    server.use(async (ctx, next) => {
        try {
            await next();
        } catch (err) {
            if (err.statusCode === 401) {
                ctx.redirect('/login');
            }
        }
    });

    server.use(router.routes());
    server.use(router.allowedMethods());
    server.listen(3000);
});

使用上面的代码,行为是

  • 如果我链接到带有和不带有 jwt 令牌的仪表板,它总是重定向到登录页面。
  • 如果我从菜单链接到仪表板<Link>在 Nextjs 中实现),它会显示仪表板的内容。

谢谢您的帮助。

4

1 回答 1

2

您需要在 server.use 中包含 jwt 部分,而不是在路由器中。制作两台不同的路由器,一台使用开放路由,一台使用受保护路由。然后设置开放路由,设置jwt中间件,然后设置保护路由:

const app = next({ dev })
const handle = app.getRequestHandler()

app.prepare()
  .then(() => {
    const server = new Koa()
    const router = new Router()

    router.get('/login', async ctx => {
        await app.render(ctx.req, ctx.res, '/login', ctx.query);
        ctx.respond = false;
    });

    router.get('/dashboard', async ctx => {
        await app.render(ctx.req, ctx.res, '/dashboard', ctx.query);
        ctx.respond = false;
    });

    router.get('*', async ctx => {
      await handle(ctx.req, ctx.res)
      ctx.respond = false
    })

    // this will keep redirecting user to login until is logged in
    // if you remove it, will get an auth error unless you go manually
    // to the login path
    server.use(async (ctx, next) => {
        try {
            await next();
        } catch (err) {
            if (err.statusCode === 401) {
                ctx.redirect('/login');
            }
        }
    });

    // we need to do it this way because of the way nextjs works with '*' path    
    // Middleware below this line is only reached if JWT token is valid
    server.use(jwt({ secret: 'shared-secret' }).unless({ path: [/^\/b/] }));

    // specify in unless the unprotected path
    server.use(jwt({secret: config.graphqlSecret}).unless({ path: [/^\/login/] })).use(router.allowedMethods());

    // every route protected by default
    server.use(router.routes())

    server.listen(3000);
  })
于 2018-06-19T07:29:08.893 回答