javaspringspring-securityexecutorservicesecurity-context

ExecutorService with SecurityContextHolder


I am changing single thread to multi thread execution of the method by using ExecutorService. it's calling SecurityContextHolder inside, which throwing exception:

Caused by: java.lang.Exception: Authentication object not found in security context. at com.LoggedInUser.getLoggedInUser(LoggedInUser.java:25) at com.Controller.submitRate(RateController.java:242)

My Code:

method(){

Future<Results> future = executor.submit(new callableClass(form, request));

            if (null != future.get()) {
                rates = future.get();
            }}
}


class callableClass implements Callable<RateResults> {

    private Form form;
    private HttpServletRequest request;

    public RateShippmentCaller(Form form, HttpServletRequest request) {
        super();
        this.form = form;
        this.request = request;
    }

    @Override
    public Results call() throws Exception {
        return controller.submit(form, request);
    }

}

submit(form, request){
LoggedInUser.getLoggedInUser()
}

class LoggedInUser{
    getLoggedInUser(){
       SecurityContext **secCtx** = SecurityContextHolder.getContext();
        Authentication authentication = secCtx.getAuthentication();
        if (authentication == null) {
            throw new Exception("Authentication object not found in security context.");
        }
    }
}

Please let me know how to avoid exception. secCtx is returning null.


Solution

  • Try setting the following security context holder strategy:

    SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
    

    Notice you shouldn’t use this is you have a thread pool, only if a new thread is created every time.

    Another way of transferring the context:

    Runnable runnable = new Runnable() {
        public void run() {
            // you’ll be able to access the context here
        }
    };
    SecurityContext context = SecurityContextHolder.getContext();
    DelegatingSecurityContextRunnable wrappedRunnable =
        new DelegatingSecurityContextRunnable(runnable, context);
    
    new Thread(wrappedRunnable).start();