Использование koa-jwt с koa-router

Я реализую службу Nextjs с koa, koa-router и 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), он покажет содержимое информационной панели.

Спасибо за помощь.


person Jimmy Lin    schedule 05.06.2018    source источник
comment
возможно, я немного опоздал, но могу помочь вам, если вы все еще сталкиваетесь с проблемой. Я совершенно уверен, что вы делаете запрос неправильно. Не могли бы вы задокументировать, как вы выполняете запрос? Вы включаете токен носителя авторизации в заголовок запроса?   -  person Javier Aviles    schedule 18.06.2018
comment
Теперь я меняю свою авторизацию с пути на компонент, и это работает хорошо. Я все еще хочу знать, как сделать авторизацию по пути. Да, я включаю токен авторизации в заголовок запроса.   -  person Jimmy Lin    schedule 19.06.2018
comment
Посмотрите на ответ и посмотрите, поможет ли он вам :)   -  person Javier Aviles    schedule 19.06.2018
comment
Я отредактировал ответ, не видел, что это было для nextjs, извините! не знал, как это работает раньше, но только что посмотрел их документ, и я думаю, что этот подойдет   -  person Javier Aviles    schedule 19.06.2018


Ответы (1)


Вам нужно включить часть jwt в ваш server.use, а не в маршрутизатор. Сделайте два разных маршрутизатора, один с открытыми маршрутами и один с защищенными. Затем установите открытые маршруты, установите промежуточное ПО 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);
  })
person Javier Aviles    schedule 19.06.2018
comment
Спасибо за ваш ответ, однако куда вы положили router.get('*', async ctx... этот роутер. В защищенном или в открытом? Я пробовал этот метод, но он не работает с каталогом *, потому что веб-сайт отображается из маршрута *. - person Jimmy Lin; 19.06.2018
comment
взгляните на издание, как вы сказали, потому что путь * nextjs нельзя было сделать по-другому, этот работает :) - person Javier Aviles; 19.06.2018