Deadbolt 2 и Play 2.4.x: исключение нулевого указателя на недоступных страницах

Я пытаюсь реализовать простую систему аутентификации в Play Framework 2.4.x, используя Deadbolt 2.

Я следовал этому руководству, написанному Chaloner, и я реализовал свой обработчик засовов, как вы можете видеть здесь:

public class MyDeadboltHandler extends AbstractDeadboltHandler {

    public F.Promise<Optional<Result>> beforeAuthCheck(Http.Context context) {
        // returning null means that everything is OK.  Return a real result if you want a redirect to a login page or
        // somewhere else
        return F.Promise.promise(Optional::empty);
    }

    public F.Promise<Optional<Subject>> getSubject(Http.Context context) {
        // in a real application, the user name would probably be in the session following a login process
        User user = new User("MyUser", "my.email@info.com");
        return F.Promise.promise(() -> Optional.ofNullable(user));
    }

    public F.Promise<Optional<DynamicResourceHandler>> getDynamicResourceHandler(Http.Context context) {
        return F.Promise.promise(() -> Optional.of(new MyDynamicResourceHandler()));
    }

    @Override
    public F.Promise<Result> onAuthFailure(final Http.Context context, final String content) {
        // you can return any result from here - forbidden, etc
        return F.Promise.promise(() -> Controller.redirect(routes.Application.index()));
    }
}

Мой главный контроллер это:

public class Application extends Controller {

    public Result index() {
        return ok(index.render());
    }

    @SubjectPresent
    public Result denyAccess(){
        return ok(notAllowed.render());
    }

    public Result permitAccess(){
        return ok(allowed.render());
    }

    public Result errorPage(){
        return ok(errorPage.render());
    }
}

Проблема появляется, когда я пытаюсь получить доступ к странице, созданной действием denyAccess, В этом случае я получаю исключение NullPointerException на странице без трассировки стека, которую я могу прочитать, как вы можете видеть на следующем рисунке.

введите описание изображения здесь

Кажется, что метод onAuthFailure никогда не вызывается, даже когда я пытаюсь получить доступ к контроллеру denyAccess.

Вы можете увидеть полный проект здесь на моей странице github, он очень короткий, и я думаю, что он может помочь вам понять проблему.

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

1 ответ

Решение

Проблема заключается в вашей реализации HandlerCache:

@Singleton
public class MyHandlerCache implements HandlerCache {

    private final Map<String, DeadboltHandler> handlers = new HashMap<>();

    public MyHandlerCache() {
        handlers.put("DEFAULT_KEY", new MyDeadboltHandler());
    }

    @Override
    public DeadboltHandler apply(final String key) {
        return handlers.get(key);
    }

    @Override
    public DeadboltHandler get() {
        return handlers.get("DEFAULT_KEY");
    }
}

По умолчанию имя ключа обработчика по умолчанию определяется как be.objectify.deadbolt.java.ConfigKeys.DEFAULT_HANDLER_KEY но в MyHandlerCache ты используешь "DEFAULT_KEY", Однако, когда этот метод вызывается:

public DeadboltHandler apply(final String key) {
    return handlers.get(key);
}

он получит be.objectify.deadbolt.java.ConfigKeys.DEFAULT_HANDLER_KEY в качестве ключа и вернуть ноль.

Я позабочусь о том, чтобы это было зарегистрировано лучше и ясно указано в документации. Чтобы исправить вашу реализацию, замените "DEFAULT_KEY" с be.objectify.deadbolt.java.ConfigKeys.DEFAULT_HANDLER_KEY:

@Singleton
public class MyHandlerCache implements HandlerCache {

    private final Map<String, DeadboltHandler> handlers = new HashMap<>();

    public MyHandlerCache() {
        handlers.put(ConfigKeys.DEFAULT_HANDLER_KEY, new MyDeadboltHandler());
    }

    @Override
    public DeadboltHandler apply(final String key) {
        return handlers.get(key);
    }

    @Override
    public DeadboltHandler get() {
        return handlers.get(ConfigKeys.DEFAULT_HANDLER_KEY);
    }
}
Другие вопросы по тегам