Apache Shiro getSubject в @Singleton EJB bean на REST API

Разработвам уеб приложение, използвайки Java EE 6 и Shiro за REST бекенд и това е достъпно чрез интерфейс, базиран на Angular.

Създаването на сесия е деактивирано в shiro (noSessionCreation в shiro.ini) и аз удостоверявам потребителя при всяка заявка въз основа на токен, който той/тя е получил, след като е предоставил идентификационните данни за влизане.

В персонализирания филтър за удостоверяване, който извиквам

SecurityUtils.getSubject().login(bearerToken);

Това извиква областта за персонализирано удостоверяване и извършва валидирането на идентификационните данни.

Имам Dao, където искам да използвам идентификатора на потребителя, който се съхранява в основната информация на Shiro Subject.

final UserInfo userInfo = (UserInfo) SecurityUtils.getSubject().getPrincipal();
final Long currentUserId = userInfo.getId();

Самото Dao е @Singleton EJB

@Singleton
public class TaskDao {
    ...
    public List<Task> filterActiveTasks() {
    }
}

В този случай искам да филтрирам активните задачи, които принадлежат на потребителя, който има достъп до услугата.

Моят въпрос и същевременно притеснение:

Безопасна ли е тази тема? Не е ли възможно при едновременна употреба темите да се объркат?

Ако е така, как може да се избегне?

РЕДАКТИРАНЕ:

Загрижеността ми не е само за activeTasks, но също така се прилага за всички @Singleton анотирани класове, където искам да използвам статичния метод SecurityUtils.getSubject().

public List<SomeData> getSomeDataRelatedToCurrentlyLoggedInUser() {
    // Since the following is a static call in a singleton, how can I be sure
    // that when 10 users are calling this at the same time, each call will get
    // the appropriate UserInfo that was "logged-in" at the AuthenticatingFilter level
    final UserInfo userInfo = (UserInfo) SecurityUtils.getSubject().getPrincipal();
    Long currentUserId = userInfo.getId();

    return em.createNamedQuery("select s from SomeData s where s.userId = :userId").
        setParameter("userId", currentUserId).
        getResultList();

}

Частта за влизане се извършва в потребителския AuthenticatingFilter, който е -AFAIK- създаден за всеки потребител.

Така че въпросът все още остава: Ще върнат ли извикванията за SecurityUtils.getSubject() правилния потребител или е възможно да ги смесите? Как мога да извлека контекста на нишката в сингълтоните, към които потребителят е бил обвързан при изпълнение на механизма за влизане?


person SLOBY    schedule 20.08.2014    source източник


Отговори (1)


Можете просто да въведете променлива ThreadLocal във вашия singleton ejb.

По този начин поставяте само неща, свързани с текущата нишка/потребител в променливата. Например:

@Singleton
public class TaskDao {

    private static ThreadLocal<Set<ActiveTasks>> tasksThreadLocal = new ThreadLocal<>(){
        @Override
        protected Set<ActiveTasks> initialValue() {
            return new HashSet<>();
        }
    };

    filterActiveTasks() {
         Set<ActiveTasks> tasks = tasksThreadLocal.get();
         //work with the Set
    }
}

По този начин наборът е локален за всяка нишка и не могат да възникнат проблеми с многопоточност.

Що се отнася до SecurityUtils.getSubject(), този метод използва същия механизъм вътрешно, така че винаги връща само потребителя на текущата нишка, следователно потребителя, който е влязъл в текущата заявка. Той използва класа ThreadContext, който използва ThreadLocal за съхраняване на текущата сесия за потребител/влизане.

Ако по някакъв начин искате достъп до този обект (което в повечето случаи не искате), той има куп статични публични методи, които можете да извикате директно, за да зададете/получите неща като субекта или мениджъра за сигурност за текущата нишка.

person Wouter    schedule 20.08.2014
comment
Благодаря Ви за отговора! Въпросът ми не беше ясен, предполагам, актуализирах го. Моля, проверете го, защото изглежда, че решението е подобно на това, което току-що предложихте. - person SLOBY; 21.08.2014
comment
Добавена информация към отговора по отношение на вашия допълнителен въпрос, отговаря ли на него? - person Wouter; 21.08.2014
comment
Така че по принцип трябва просто да го оставя така, както е? - person SLOBY; 21.08.2014