Как вернуться к просмотру после аутентификации в Аурелии

У меня есть мнение, что можно получить доступ по прямой ссылке из электронного письма.

Ex. Http: // MYSERVER:7747/#/ фото /ClientId/YYYY-MM-DD

Так что это настроено с использованием маршрута:

{ route: ['/pics', '/pics/:clientId/:sessionDate', 'pics'], 
  name: 'pics', moduleId: './views/pics', nav: false, title: 'Pictures', 
  auth: true, activationStrategy: activationStrategy.invokeLifecycle 
},

Поэтому, если клиент нажимает на эту ссылку и не вошел в систему, я хочу, чтобы представление перенаправлялось на экран входа в систему (я использую плагин аутентификации aurelia), а затем, когда это удается, я хочу, чтобы он вернулся на эту страницу, используя тот же urlParams.

У меня работает перенаправление на страницу входа, но вернуться к этому представлению оказывается сложно. Если я просто попробую использовать history.back() проблема в том, что плагин аутентификации подтолкнул другой navigationInstruction (loginRedirect) на историю, прежде чем я могу сделать что-нибудь. Если я просто пытаюсь жестко запрограммировать навигацию "вернуться назад дважды", я сталкиваюсь с проблемой, когда пользователь просто пытается войти в систему заново с главной страницы, а история отсутствует.

Похоже, это должно быть проще, чем есть, что я делаю не так?

2 ответа

Решение

Я заставил это работать, заменив authenticateStep плагина своим собственным:

import { inject } from 'aurelia-dependency-injection';
import { Redirect } from 'aurelia-router';
import { AuthService } from "aurelia-authentication";
import { StateStore } from "./StateStore";

@inject(AuthService, StateStore)
export class SaveNavStep {
    authService: AuthService;
    commonState: StateStore;

    constructor(authService: AuthService, commonState: StateStore) {
        this.authService = authService;
        this.commonState = commonState;
    }

    run(routingContext, next) {
        const isLoggedIn = this.authService.authenticated;
        const loginRoute = this.authService.config.loginRoute;

        if (routingContext.getAllInstructions().some(route => route.config.auth === true)) {
            if (!isLoggedIn) {
                this.commonState.postLoginNavInstr = routingContext;
                return next.cancel(new Redirect(loginRoute));
            }
        } else if (isLoggedIn && routingContext.getAllInstructions().some(route => route.fragment === loginRoute)) {
            return next.cancel(new Redirect(this.authService.config.loginRedirect));
        }

        return next();
    }
}

Единственная разница между моей и стандартной состоит в том, что я внедряю объект StateStore, где я сохраняю NavigationInstruction, которая требует аутентификации.

Затем в моей учетной записи viewModel я внедряю тот же объект StateStore (singleton) и делаю что-то подобное для входа в систему:

login() {
    var redirectUri = '#/defaultRedirectUri';

    if (this.commonState.postLoginNavInstr) {
        redirectUri = this.routing.router.generate(this.commonState.postLoginNavInstr.config.name,
                            this.commonState.postLoginNavInstr.params,
                            { replace: true });
    }
    var credentials = {
        username: this.userName,
        password: this.password,
        grant_type: "password"
    };
    this.routing.auth.login(credentials,
        { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } },
        redirectUri
    ).catch(e => {
        this.dialogService.open({
            viewModel: InfoDialog,
            model: ExceptionHelpers.exceptionToString(e)
        });
    });
}; 

Надеюсь, это поможет кому-то!

Я не использовал плагин aurelia-authentication, но я могу помочь с базовой техникой, которую вы можете использовать, которая делает это очень простым. В вашем main.js файл, установите в корне вашего приложения компонент "логин". В компоненте входа в систему, когда пользователь успешно прошел аутентификацию, задайте в корне вашего приложения компонент "оболочки" (или любой другой компонент, который вы выберете), который имеет представление маршрутизатора, и настройте маршрутизатор в своей модели представления. Как только это произойдет, маршрутизатор доставит пользователя к нужному компоненту на основе URL. Если пользователь выходит из системы, просто установите корень приложения обратно в компонент "login".

Вот небольшой поверхностный код, чтобы попытаться передать идею. Я предполагаю, что вы используете плагин SpoonX, но в этом нет необходимости. Пока вы сбрасываете корень своего приложения, когда пользователь проходит аутентификацию, оно будет работать.

В main.js

.....
aurelia.start().then(() => aurelia.setRoot('login'));
.....

В login.js

import {AuthService} from 'aurelia-authentication';
import {Aurelia, inject} from 'aurelia-framework';

@inject(AuthService, Aurelia)
export class Login {
    constructor(authService, aurelia) {
        this.authService = authService;
        this.aurelia = aurelia;
    }

    login(credentialsObject) {
        return this.authService.login(credentialsObject)
            .then(() => {
                this.authenticated = this.authService.authenticated;

                if (this.authenticated) {
                    this.aurelia.setRoot('shell');
                }
            });
    }

    .....
}

В shell.html

.....
<router-view></router-view>
.....

В shell.js

.....
configureRouter(config, router) {
    this.router = router;
    config.map(YOUR ROUTES HERE);
}
.....
Другие вопросы по тегам