Когда первая запущенная информация представляет собой инъекцию ExecutorService, Принцип безопасности правильно установлен для этой runnable. Каждому впоследствии представленному runnable предоставляется руководитель безопасности оригинального пользователя, а не текущий текущий runnable. Моя машина разработки работает Wildfly 8.2.Как избежать ExecutorService от переопределения Принцип безопасности Runnable
Я создаю систему отчетности для асинхронной обработки. Я создал службу, которая проверяет, какой пользователь создал задачу, и гарантирует, что только этот пользователь может запустить или завершить задачу. Код услуги приведен ниже.
@Stateless
public class ReportingService {
//EE injection security context
@Resource
SessionContext context;
//CDI security Principal
@Inject
Principal principal;
//this method handles getting the username for EE injection or CDI
private String getCurrentUser() {
if (context != null) {
return context.getCallerPrincipal().getName();
}
if (principal != null) {
return principal.getName();
}
return null;
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
@Transactional
public void registerTask(String taskId) {
//Create task
//set task.submittedBy = getCurrentUser()
//persist task
//code has been omitted since it is working
}
private void validateCurrentUserRegisteredJob(String taskId) {
String user = //get user that created task with id = id from DB
String currentUser = getCurrentUser();
if (!user.equals(currentUser)) {
throw new EJBAccesException("Current user "+currentUser+" did not register task");
}
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
@Transactional
public void startTask(String taskId) {
validateCurrentUserRegisteredJob(taskid);
//retrieve task entity, set start time to now, and merge
}
...
}
Ниже мой Runnable код
public TaskRunner() implements Runnable {
//CDI principal
@Inject
Principal principal;
@Inject
ReportingService rs;
private taskId;
public void setTaskId() {...}
public void run() {
log.debug("Inside Runner Current User: "+principal.getName());
rs.startTask(taskId);
....
}
}
Ниже приведен код из Stateless Bean, который вызывается с помощью REST конечной точки, которая стартует процесс
@Stateless
public ProjectService() {
@Inject
Instance<TaskRunner> taskRunner;
@Inject
ReportingService reportingService;
//ExecutorService that is create from Adam Bien's porcupine project
@Inject
@Dedicated
ExecutorService es;
//method that is called by rest enpoint to kick off
public void performAsynchAction(List<String> taskIds, ...rest of args...) {
taskIds.stream().forEach(t -> {
//registers task with user that made REST call
reportingService.registerTask(t);
TaskRunner runner = taskRunner.get();
runner.setTaskId(t);
log.debug("Created runner. Principal: "+runner.principal.getName());
es.submit(runner);
});
}
}
Вот является график потока вызовов
REST -> ProjectService.performAsynchAction(...)
-> reportingService.registerTask(...)
-> create CDI injected Runnable
-> submit runner to executor service
-> ExecutorService calls Runner.run()
-> rs.startTask(taskId)
Я вызываю конечную точку Rest как user1 в первый раз и регистрирую задачи: 1-2. Все они работают так, как ожидалось, и я получаю следующий вывод в своем журнале.
Created runner. Principal: user1
Created runner. Principal: user1
Inside Runner Current User: user1
Inside Runner Current User: user1
В следующий раз, когда я сделать то же самое REST вызов, как user2 и я получаю следующий результат в журнале
Created runner. Principal: user2
Inside Runner Current User: user1
EJBAccessException Current user user1 did not register task
Представляется, что Принципал Безопасность Runnable правильно установить в первый раз Runnable передается в ExecutorService. Но для каждого последующего Runneable, представленного в ExecutorService, используется Принцип безопасности первой представленной runnable. Это ошибка или предполагаемое поведение? Кто-нибудь знает о потенциальной работе?
EDIT: Я понимаю, что проект дикобраза, который я использовал для создания ExecutorService, не управлялся контейнером. Когда я переключился на ManagedExecutorService, SessionContext был правильно размножен.
@Resource(lookup = "java:jboss/ee/concurrency/executor/customExecutor")
private ManagedExecutorService es;
Вы знаете, откуда уходит ваш currentUser? 'SessionContext' или' Principal'? – flo
Оказывается, что оба они вводятся, и оба они имеют неправильное значение как в Runnable, так и в сервисе для второго вызова. – Mike