Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the preferred way to handle Spring Security for JMS Listeners?

I have a somewhat monolithic Java application, built around Spring @Service beans for my business service layer. As a rule, each of my business service methods has Spring Security annotations (e.g. @PreAuthorize) to enforce appropriate authorization rules for that action.

Within the main web application flow, this works very well; each web request implicitly has authentication handled by session cookies, etc.

However, when it comes to various integration points with other, "internal" systems, I'm not seeing as clear of a solution.

For example, I am going to be consuming methods from a JMS queue, which already has its own authentication & authorization rules defined within the broker, so I want to implicitly "trust" the messages that I get. However, as things stand now, a simple enough Camel route like this:

WidgetService widgetService = lookup(WidgetService.class);
from("activemq:newWidget")
    .unmarshall(...)
    .bean(widgetService, "newWidget");

ends up throwing a AuthenticationCredentialsNotFoundException.

This tells me that Camel is calling my bean correctly, with all of the magic AOP applied from Spring.

With other things of this sort, I've resorted to applying AOP advice around the entry point for the system (e.g. around a Quartz Job's execute method), which injects a PreAuthenticatedAuthenticationToken, but I'm not sure if that's really the best approach.

Should I continue to wrap these "trusted" entry points in advice to add an Authenication context, or should I change my service layer to have special forms of some business methods which require no authentication, and just make sure I document clearly that they are not for use in web @Controller methods, etc?

like image 638
pioto Avatar asked Jul 24 '18 21:07

pioto


People also ask

Which security protection is used by Spring for all request of application?

To protect MVC applications, Spring adds a CSRF token to each generated view. This token must be submitted to the server on every HTTP request that modifies state (PATCH, POST, PUT and DELETE — not GET). This protects our application against CSRF attacks since an attacker can't get this token from their own page.

How do I start and stop JMS listener in Spring?

You can access the JMS listener containers from the registry (all or by name) and call stop() on the one(s) you want; the container will stop after any in-process messages complete their processing.

What is JMS listener container?

A message listener container is used to receive messages from a JMS message queue and drive the MessageListener that is injected into it. The listener container is responsible for all threading of message reception and dispatches into the listener for processing.


1 Answers

Unfortunately there is best way to do that. It depends on the application and in my experience all solutions work but have some drawbacks.

The first solution would be to move the @PreAuthorize up to the web level. This way you will be free to use your services internally as much as you want. I think this is the simpler solution and easier to comprehend. You want to secure your web users right? Why not apply the security to in the web layer. The problem with it is that web layer changes more often than the business layer and it is easier to leave security breach if you don't develop your controllers and endpoints carefully. I would still take that approach for most applications and let the service layer take care just of business rules and not security (which is kind of business rule too? ). Of course you can still add some default security logic to groups of controllers and stuff so you don't have to repeat yourself everywhere.

The second approach is the one that you have taken. Run such methods in authenticated context which you generate. And it is a bit counter-logic - why to run in authenticated context when there is no authenticated user? You shouldn't have to do it but unfortunately that's the only way if you want to have secured services. This methods is less prone to security errors and you can maintain the security easier. If you stick to that you can use the template pattern or create some executor class that runs stuff in context.

I cannot think of a third approach :)

like image 57
Veselin Davidov Avatar answered Nov 15 '22 00:11

Veselin Davidov