How should I pass subject/principals/roles between application layers in Java? - java

I currently have a number of web applications which access a common service running in JBoss 5.0. The service is very simple, using Guice and POJOs. The web applications are authenticated and know who the user is and what roles they have. When calling the service how should I pass this authentication information to the service?
It would seem the simple approach is to simply add a parameter to the interface to take the user information. Possibly a Subject. But this has the downside of cluttering up the interface with contextual information that isn't specific to the job in hand.
void doSomething(Subject subject, ...) {
}
The alternative I have seen is to use ThreadLocal storage, put the user information in there before making the call and make this accessible via some utility class that the service can use. This cleans up the interface but hides the fact that the client of the service has to set the user information before making the call.
Is there another way of doing this? I get the feeling the AOP may be of use here too but can't quite see how. Is there some "best practice" I am missing? Would EJB help?

This cleans up the interface but hides the fact that the client of the
service has to set the user information before making the call.
True, but if you need to pass something to a particular method across the application then you are defeating the purpose of using Dependency Injection. It's there so that you don't have to pass a bunch of services and objects to other services and objects and so forth, they are created with everything they need.
Is there another way of doing this? I get the feeling the AOP may be
of use here too but can't quite see how. Is there some "best practice"
I am missing? Would EJB help?
The other way of doing this would be to use a single filter on every Servlet that calls the services that need the Subject / User. Set the user in the filter, and clear the user at the end in a try-finally block. In fact, OWASP Esapi uses this style when setting their ThreadLocalUser, it allows the User to be available in every part of the application.
Something like this:
#Singleton
public MyUserFilter extends FilterOfTheMonth {
private final Provider<Authenticator> authProvider;
#Inject
MyUserFilter(Provider<Authenticator> auth) {
this.authProvider = auth;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws java.io.IOException, ServletException {
try {
// Authenticate and SET the current user utilizing the request and/or
// session objects
authProvider.get().authenticateUser(HttpRequest currentRequest);
// Continue on here along the servlet chain
... other processing
} finally {
authProvider.get().getRidOfCurrentUser();
}
}
}

Have you considered moving the authentication process to the common service? Then you only need the session ID in the common service to identify all information about the user the request is coming from.

Related

How to create unique Id per request for REST API in Spring-boot?

I need to make my logs (log4j engine) to be more informative with a unique id per request for my REST API in Spring-Boot application.
I want to avoid using a superclass which got requestId field and extend from it.
I tried to look for a good example over the web, but it wasn't so clear.
Is there any best practice that I can use?
Using a field for such a feature would just cause problems during the integration testing on the first glance..
Ideally, just follow an SRP principle and include the generation logic inside a dedicated class which you could make an injectable #Component.. MyIdGenerator etc.
There you could have a synchronized method generateId().
Now you could use it in whichever controller it is needed and also you could set-up your integration test more easily and have more control over them.
Update:
You could take also advantage of HandleInterceptorAdapter if this should be a global strategy:
#Component
public class RequestInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
/* generate unique id here and log what is needed */
}
You can encapsulate the ID generation and logging inside this class.
There are several best practices used as follows:
Use AOP Refer :AOP used for controller layer
Use MDC
Use MDC with AOP
MDC with AOP

Sending information from a servlet back to a Filter

I have an old web application, running on Tomcat 7, that uses a very rudimentary open-session-in-view mechanism provided by a filter:
#Override public void doFilter (ServletRequest req, ServletResponse resp, FilterChain fc)
throws IOException, ServletException
{
try {
HibernateUtil.beginTransaction();
fc.doFilter(req, resp);
HibernateUtil.commitTransaction();
} catch (Throwable t) {
Logger.exception(t, "processing servlet request");
HibernateUtil.rollbackTransaction();
throw new ServletException(t);
}
}
I'm stuck with this now, and I think I'm running into one of the many flaws with OSIV (or at least this implementation of it) which is that I now want to be able to rollback transactions even without an exception being thrown. I want servlets to be able to control that, and I don't think I have much choice except to hack this functionality on somehow.
My question is: How can I communicate some sort of "rollback" flag from an arbitrary servlet back up to this filter? I want to be able to do something like this in the filter:
HibernateUtil.beginTransaction();
fc.doFilter(req, resp);
if (/* something that was set by a servlet/jsp */)
HibernateUtil.rollbackTransaction();
else
HibernateUtil.commitTransaction();
I'm not really sure what a reliable way to propagate information like that from a servlet back out to this filter is.
I don't advise using request attributes or thread-local variables, which has the following issues:
Your transaction is dependent on someone else having set a flag. If you work for a bank, I really don't wanna be a customer there.
Resource leaking if you don't clean up thread-local storage.
You can't write multithreaded code without manually copying stuff between thread-local storage.
If using request attribute, you'll have to extract the value in a Servlet and pass all the way to your DAO, assuming you're using a common multi layered architecture.
Instead, you can simply get the current transaction from the Hibernate session object and ask it to rollback. Session.getTransaction().rollback(). Best, scrap that code or find the person who wrote it and ask for a refund.

Spring MVC Interceptor exclude paths on HTTP method

I have some interceptors that need to check the headers and the authorization in some requests done to my API. For example, some requests should require user authentication (for example, to alter user details from the database) and some don't require authentication (for example, to create a user). Unfortunately, the methods for excluding paths from the interceptors don't depend on the request method.
Right now I have created an Util class that receives an array of strings of paths and methods that should be excluded from the verifications. For example: "POST /api/users" should not be intercepted by my authentication interceptor because it is for creating a user, but "PUT /api/users" should be intercepted because it is for altering an existing user (who should be logged in).
public static Boolean skipVerification(HttpServletRequest request, String... skipRequests) {
for (String string : skipRequests) {
String[] split = string.split(" ");
if(split[0].equals(request.getMethod()) && split[1].equals(request.getRequestURI()))
return true;
}
return false;
}
In the constructor of my interceptor, I add the requests that should be skipped and in the PreHandle method I return true if the request matches any one of them as they didn't need to me intercepted in the first place.
public AuthenticationHeaderInterceptor(String...skipWhen) {
this.skipWhen = skipWhen;
}
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
if(InterceptorUtils.skipVerification(request, skipWhen))
return true;
///Do Authentication Logic
}
I know that changing the URI for creating and editing users would solve this, but I prefer not to clutter my API with too many URIs and was wondering if there was a cleaner way to solve this.
Looking at the code, I was checking if you would be able to extend InterceptorRegistry, InterceptorRegistration, and MappedInterceptor. You would also have to extend PathMatcher and incorporate code to check methods as well as paths, which PathMatcher isn't meant for. So overall, the way you are doing it currently is probably best. I would also point out the code in Spring's AntPathMatcher has always been very messy and buggy so you probably wouldn't want to take on any task that involved dealing with it.

How to call a Servlet/Filter before a JSP is executed in CQ5?

In a Spring MVC application we have a Controller that would execute before calling the JSP. The Controller would prefetch some values from the database and set them in the model and forward the control to JSP.
How do I implement this feature in CQ 5? I want the SlingFilter to execute before the JSP is executed. And the JSP is not a page component but a component that appears in the side kick.
Note:
I can do this by writing my own SlingSerlvet that would prefetch my required values and use the RequestDispatcher to forward to the JSP.
But by this method I would have to go through a URL like "/bin/.*". And this is again at a page level I want this kind of functionality at component level.
So to answer your specific question, if you want a filter to be executed before a component is called you would create a filter that is listening to Component level filter scope.
See
http://sling.apache.org/documentation/the-sling-engine/filters.html
You would then have your filter change the incoming request to a SlingServletRequest and determine if the target resource is the one that you are looking for.
However this filter would be executed on every single component that is being included on a page. The reverse process of this that may be useful to you is the ResourceDecorator.
http://sling.apache.org/documentation/the-sling-engine/wrap-or-decorate-resources.html
These are executed when the resource is identified, prior to the servlet and filter calls, which would allow you to verify if a resource is a type that you are interested in, and then allows you to add additional information to the resource object.However this is, once again a service that would be applied to every resource that is identified.
However, if what you are looking for is a filter that is only executed for a specific path, then no. Sling doesn't do that. You mentioned Spring MVC and Spring MVC works on a completely different concept of MVC then what Slings version of MVC does.
EDIT
So in a traditional web app, the servlet would be at a fixed position and all filters are applied prior to the call to that servlet. In Sling you are dynamically wiring servlets together to generate the resulting page. So each time that you are in a servlet and call directly or indirectly the request dispatcher, it's executing the resolution process again and applying a series of filters again before the new servlet is executed.
To prevent a high level filter that needs to applied only to the main request being applied on every single internal dispatch, they came up with the idea of contexts, or chains of filters that are applied at different times and associated with different types of includes.
Here is a basic filter that will log a message when it's called. I did this from memory so you'll need to dink with it.
#SlingFilter(scope = SlingFilterScope.COMPONENT, order = Integer.MIN_VALUE)
public class SampleFilter implements Filter {
private static final Logger LOG = LoggerFactory.getLogger(SampleFilter.class);
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;
Resource res = slingRequest.getResource();
if (!(res == null || ResourceUtil.isNonExistingResource(res))) {
LOG.error("this servlet is called before resource {} at path {}", res.getName(),res.getPath());
}
chain.doFilter(request, response);
}
}
The important part of this is scope = SlingFilterScope.COMPONENT take a look at the page I had listed earlier and try out different combinations of slignfilterscope and you'll see how it's being applied at different times. scope = SlingFilterScope.REQUEST would be once at a top level on a per page basis.
JE Bailey's answer is correct as far as Filters are concerned, but I suspect your problem might be solved in a different way that better fits Sling's view of the world.
Sling promotes the use of OSGi services for business logic, and scripts should be a thin layer above that. Moving your logic to OSGi services and calling those from your scripts is the recommended way.
You might also have a look at Sling Models which can include processing steps (with #PostConstruct) before the rendering scripts kick in.
But by this method I would have to go through a URL like "/bin/.*".
You can also register a servlet against a resource type, as well as by path, e.g. (from the Sling documentation):
#SlingServlet(
resourceTypes = "sling/servlet/default",
selectors = "hello",
extensions = "html",
methods = "GET")
public class MyServlet extends SlingSafeMethodsServlet {
#Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
...
}
}
If you remove the "selectors", "extensions" and "methods" parameters on the annotation, this servlet would bind against all calls to sling/servlet/default without requiring binding against a set path.

How do you cache data only for the duration of the http request using apache shiro in a servlet container?

More specifically, I find that I'm implementing a custom AuthorizingRealm, which declares template methods doGetAuthenticationInfo() and doGetAuthorizationInfo() for returning AuthenticationInfo and AuthorizationInfo objects, respectively.
However, when I retrieve the data for the AuthenticationInfo (a JPA entity) in doGetAuthenticationInfo(), I find that I already have the necessary AuthorizationInfo. Alas, there's no apparantly good way to hang onto this data, so I have to throw it out only to perform another JPA lookup when the authorization filter ultimately gets its turn in the filter chain.
Behold:
public class CustomRealm extends AuthorizingRealm {
#Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
UsernamePasswordToken userPassToken = (UsernamePasswordToken) token;
String username = userPassToken.getUsername()
User user; // Contains username, password, and roles
// Perform JPA lookup by username...
return constructSimpleAuthenticationInfoFromUser(user);
}
#Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// Look up user again? :(
...
}
}
I've considered a number of possibilities:
Use realm caching. The application will run in a distributed environment so there could be any arbitrary number of JVMs running. The default realm cache manager implementations don't solve all of the inherent problems and setting up an enterprise implementations seems out of scope for this project.
Use the subject's session. There is no server-side state and I'd like to keep it that way if possible. Perhaps you can force the session to behave like request scope, but I wouldn't know how to do so and that risks being obfuscated.
Implement my own Subject. There appears to typically be one Subject instance per request, but it's unclear how to bootstrap this and I would risk losing a lot of potential functionality.
Use the Shiro ThreadContext object. I could attach the data to the ThreadContext as a threadlocal property. Servlet containers generally follow a thread-per-request model, and the Subject instance itself seems to chill out here, awaiting its inevitable garbage collection. Shiro also appears to build up and tear down the context automatically. However, there's not much documentation on this and the source code is hard for me to follow.
Finally, the default WebSecurityManager keeps singleton instances of the CustomRealm around, one per JVM it seems. Simply setting some local instance property is not thread-safe.
This seems like a common data retrieval option and a typical deployment scenario. So, what am I missing?
Thanks!
I would go with option 4 - Using ThreadLocal object as your requirement clearly says that the object lifetime must be of http request.
Have a look at this discussion: When and how should I use a ThreadLocal variable?
ThreadLocal doc: http://docs.oracle.com/javase/6/docs/api/java/lang/ThreadLocal.html

Categories

Resources