Shiro throws an UnavailableSecurityManagerException in custom JSON serialiser - java

I'm working on a REST API of a TomEE 7 based web app, which uses Shiro 1.3.2 for security. When an API request comes in, a SecurityManager and a Subject are created, and the latter is bound to a SubjectThreadState. I can call SecurityUtils.getSubject() anywhere in the endpoint code and the subject is always available.
However, problems arise when I try to do the same inside my custom JSON serialiser. It only serialises specific fields in some classes, so I register it on a per-field basis using this annotation:
#JsonSerialize(using = MySerialiser.class)
Long myRelatedItemId;
I wrote my serialiser based on the example code on this page under "2.7. #JsonSerialize". The serialiser needs to perform a cache lookup, and for that it has to have a Shiro subject. There is none because, thanks to the annotation above, I don't call the serialiser manually; instead Jersey calls it. This exception gets thrown (clarification: when I try to run SecurityUtils.getSubject() from the serialiser code):
org.apache.shiro.UnavailableSecurityManagerException: No SecurityManager accessible to the calling code, either bound to the org.apache.shiro.util.ThreadContext or as a vm static singleton. This is an invalid application configuration.
at org.apache.shiro.SecurityUtils.getSecurityManager(SecurityUtils.java:123)
at org.apache.shiro.subject.Subject$Builder.<init>(Subject.java:627)
at org.apache.shiro.SecurityUtils.getSubject(SecurityUtils.java:56)
I have confirmed that everything works if I call something like ObjectMapper().writeValueAsString() manually from the API endpoint code. However, that is definitely not the proper way to do it, because then the endpoint would effectively send and receive strings instead of the objects they are meant to handle.
I don't understand much about the inner workings of Shiro or Jackson, but it seems like the serialisation is being performed inside another thread, where Shiro's SubjectThreadState doesn't exist. Although if threading really is the cause, then I cannot see why Thread.currentThread().getName() returns the same value both inside and outside the serialiser, as does Thread.currentThread().getId().
I have tried a vast number of things to no avail, including:
Upgrading to Shiro 1.4.0.
Upgrading Jackson from 2.7.5 to 2.9.7.
Saving the SecurityManager instance that is created at the start of the API call inside a static ThreadLocal variable of the serialiser class.
Writing my own implementation of MessageBodyWriter which, not surprisingly, is called in exactly the same fashion.
Setting the staticSecurityManagerEnabled parameter to true in the ShiroFilter configuration in my web.xml.
Can anyone suggest how I could make the SecurityManager (or Subject) visible to the serialiser, when it's running in a thread not started by my code (clarification: or, otherwise running in parallel and started by Jersey, as far as I can tell)? Thanks in advance.
Update:
This stack trace was taken inside the serialiser:
<mypackage>.MySerializer.serialize()
com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField()
com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields()
com.fasterxml.jackson.databind.ser.BeanSerializer.serialize()
com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue()
com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize()
com.fasterxml.jackson.databind.ObjectWriter.writeValue()
com.fasterxml.jackson.jaxrs.base.ProviderBase.writeTo()
org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.invokeWriteTo()
org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo()
org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed()
org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor.aroundWriteTo()
org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed()
org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo()
org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed()
org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo()
org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse()
org.glassfish.jersey.server.ServerRuntime$Responder.processResponse()
org.glassfish.jersey.server.ServerRuntime$Responder.process()
org.glassfish.jersey.server.ServerRuntime$2.run()
This one was taken in our interceptor class where the Subject is created and bound:
<mypackage>.MySecurityInterceptor.createSession()
sun.reflect.NativeMethodAccessorImpl.invoke0()
sun.reflect.NativeMethodAccessorImpl.invoke()
sun.reflect.DelegatingMethodAccessorImpl.invoke()
java.lang.reflect.Method.invoke()
org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation.invoke()
org.apache.openejb.core.interceptor.ReflectionInvocationContext.proceed()
org.apache.openejb.monitoring.StatsInterceptor.record()
org.apache.openejb.monitoring.StatsInterceptor.invoke()
sun.reflect.GeneratedMethodAccessor111.invoke()
sun.reflect.DelegatingMethodAccessorImpl.invoke()
java.lang.reflect.Method.invoke()
org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation.invoke()
org.apache.openejb.core.interceptor.ReflectionInvocationContext.proceed()
org.apache.openejb.core.interceptor.InterceptorStack.invoke()
org.apache.openejb.core.stateless.StatelessContainer._invoke()
org.apache.openejb.core.stateless.StatelessContainer.invoke()
org.apache.openejb.core.ivm.EjbObjectProxyHandler.synchronizedBusinessMethod()
org.apache.openejb.core.ivm.EjbObjectProxyHandler.businessMethod()
org.apache.openejb.core.ivm.EjbObjectProxyHandler._invoke()
org.apache.openejb.core.ivm.BaseEjbProxyHandler.invoke()
com.sun.proxy.$Proxy279.getEntity()
org.openapitools.api.impl.MyApiServiceImpl.getEntity()
org.openapitools.api.MyApi.getEntity()
sun.reflect.NativeMethodAccessorImpl.invoke0()
sun.reflect.NativeMethodAccessorImpl.invoke()
sun.reflect.DelegatingMethodAccessorImpl.invoke()
java.lang.reflect.Method.invoke()
org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke()
org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run()
org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke()
org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch()
org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch()
org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke()
org.glassfish.jersey.server.model.ResourceMethodInvoker.apply()
org.glassfish.jersey.server.model.ResourceMethodInvoker.apply()
org.glassfish.jersey.server.ServerRuntime$2.run()
There are 46 more calls that are identical in both traces after that last line, so I excluded them. They contain a bunch of org.apache.catalina.core and org.glassfish.jersey.

Take a look at Shiro's Subject Thread Association doc

Related

Programmatically created Feign client and Eureka target

I have started a few days ago to learn about fault tolerance solutions in microservices. I have some microservices in my ecosystem and they are now interconnected with Eureka service lookup. I used FeignClient to call from one to another. As I heard and read, that Hystrix is getting into maintenance, I wondered if I could use Resilience4J in Feign instead of Hystrix. Well, at least not from annotation level right now as it seems. I found a great Feign.Builder adapter to add resilience4j fault tolerance features above a FeignClient as a decorator (https://github.com/resilience4j/resilience4j/tree/master/resilience4j-feign) so I wanted to use it.
So I used this, added together the features and added the default encoder, decoder, etc. items into the feign builder. Turns out I have to finish of course my code with a .target call which creates my client proxy and I could not really do this with Eureka in a good way:
The first constructor, which takes the class type and the URL is hardcoded, so if I add an eureka next server query into this parameter, it is just a hardcoded url for one of the instances, this is not load balanced. Some kinda workaround could be that I create prototype-scope or similar short lived scoped beans of this client and always get the "next url" for the call. This adds lots of burden to use the clients in every class I make. At least as I saw it. Maybe I could add some kind of singleton helper bean around the prototyping, but again this is not a good design as I see
I thought maybe I could create an EurekaTarget from the Target interface, but of course none of the methods indicate any "end of lifecycle" things, not even the apply method. I thought maybe that is one point which is called before doing a service call, but I saw multiple calls towards it so I had to change the url for all calls.
Do you know any better solution to do this migration?
I guess you are using Spring Boot?
The next version v1.0.0 of Resilience4j will support the #FeignClient annotation.
There was a PR which added the functionality -> https://github.com/resilience4j/resilience4j/pull/579
You can then use it as follows:
#FeignClient(name = DUMMY_FEIGN_CLIENT_NAME)
#CircuitBreaker(name = DUMMY_FEIGN_CLIENT_NAME)
public interface DummyFeignClient {
String DUMMY_FEIGN_CLIENT_NAME = "dummyFeignClient";
#GetMapping(path = "/api/{param}")
void doSomething(#PathVariable(name = "param") String param);
}

Dropwizard registering two classes/clients

I have two instances of clients with different configs that I am creating (timeout, threadpool, etc...), and would like to leverage Dropwizard's metric on both of the clients.
final JerseyClientBuilder jerseyClientBuilder = new JerseyClientBuilder(environment)
.using(configuration.getJerseyClientConfiguration());
final Client config1Client = jerseyClientBuilder.build("config1Client");
environment.jersey().register(config1Client);
final Client config2Client = jerseyClientBuilder.build("config2Client");
environment.jersey().register(config2Client);
However, I am getting
org.glassfish.jersey.internal.Errors: The following warnings have been detected:
HINT: Cannot create new registration for component type class org.glassfish.jersey.client.JerseyClient:
Existing previous registration found for the type.
And only one client's metric shows up.
How do I track both clients' metrics or is it not common to have 2 clients in a single dropwizard app?
Never mind, turned out I was an idiot (for trying to save some resource on the ClientBuilder).
2 Things that I did wrong with my original code:
1. You don't need to register Jersey clients, just the resource is enough... somehow I missed the resource part in my code and just straight up trying to register the client
2. You need to explicitly build each JerseyClientBuilder and then build your individually configured clients, then dropwizard will fetch by each JerseyClientBuilder's metrics
In the end, I just had to change my code to the following:
final Client config1Client = new JerseyClientBuilder(environment)
.using(configuration.getJerseyClientConfiguration()).build("config1Client");
final Client config2Client = new JerseyClientBuilder(environment)
.using(configuration.getJerseyClientConfiguration()).build("config2Client");
Doh.
environment.jersey().register() has a javadoc listing of Adds the given object as a Jersey singleton component meaning that the objects registered become part of the jersey dependency injection framework. Specifically this method is used to add resource classes to the jersey context, but any object with an annotation or type that Jersey looks for can be added this way. Additionally, since they are singletons you can only have one of them per any concrete type (which is why you are getting a "previous registration" error from Jersey).
I imagine that you want to have two Jersey clients to connect to two different external services via REST/HTTP. Since your service needs to talk to these others to do its work, you'll want to have the clients accessible wherever the "work" or business logic is being performed.
For example, this guide creates a resource class that requires a client to an external http service to do currency conversions. I'm not saying this is a great example (just a top google result for dropwizard external client example). In fact, I think this not a good to structure your application. I'd create several internal objects that hide from the resource class how the currency information is fetched, like a business object (BO) or data access object (DAO), etc.
For your case, you might want something like this (think of these as constructor calls). JC = jersey client, R = resource object, BO = business logic object
JC1()
JC2()
B1(JC1)
B2(JC2)
R1(B1)
R2(B2)
R3(B1, B2)
environment.jersey().register(R1)
environment.jersey().register(R2)
environment.jersey().register(R3)
The official Dropwizard docs are somewhat helpful. They at least explain how to create a jersey client; they don't explain how to structure your application.
If you're using the Jersey client builder from dropwizard, each of the clients that you create should be automatically registered to record metrics. Make sure you're using the client builder from the dropwizard-client artifact and package io.dropwizard.client. (Looks like you are because you have the using(config) method.)

Spring boot response caching

I was trying to understand the caching that happens at the client side.
Unfortunately I am unable to find any resources that can help me out.
I have employee model objects which are fairly small in size.
Once a use a GET request to obtain an employee object, I want it to be cached at the client side
Now when the request comes again to obtain the same employee, I want to see if the actual object has been modified, if not, then serve from the client cache else return the modified object also adding it to the cache.
I am using Spring boot to create a REST endpoint.
What I have been able to figure out is that cache-control would be used some how, but I am not sure how the objects would be added here in spring.
Any help here is much appreciated!!!!
Thanks,
Amar
HTTP caching is not an easy topic. There are different ways to do it, and you should probably start by familiarizing yourself with the mechanisms, this seems to be a good starting resource: HTTP caching
Then, you will probably identify some common usage patterns you will want to reuse. One way to do that is to create custom annotations and write an interceptor that reacts on them.
For example, you could write such an annotation:
#Inherited
#Retention(RUNTIME)
#Target({METHOD, TYPE})
public #interface CacheFor {
long amount();
TimeUnit unit() default TimeUnit.SECONDS;
}
and use it on controller methods like this:
#CacheFor(amount=10, unit = MINUTES)
#RequestMapping(bla bla)
public FooBar serveMyData(){
// code here
}
and in your interceptor, you will need to look at the handler method, check whether it has this annotation, and if it does, set the appropriate headers.

Spring MVC Request mapping, can this be dynamic/configurable?

With Spring MVC, I know how you set the RequestMapping in every controller and method/action.
But what if I wanted this to be configurable, so for example I the following controllers:
BlogController
- with methods for listing blogs entries, single entry, new, update, etc.
ArticleController
- with methods for listing articles entries, single entry, new, update, etc.
Now in my application, the administrator can setup 2 blogs for the webiste, and 1 article section so the urls would be like:
www.example.com/article_section1/ - uses ArticleController
www.example.com/blog1/ - uses BlogController
www.example.com/blog2/ - uses BlogController
Maybe after a while the administrator wants another article section, so they just configure that with a new section like:
www.example.com/article_section2/
This has to work dynamically/on-the-fly without having to restart the application of course.
My question is only concerned with how I will handle url mappings to my controllers.
How would this be possible with Spring MVC?
I only know how to map urls to controllers using #RequestMapping("/helloWorld") at the controller or method level, but this makes the url mappings fixed and not configurable like how I want it.
Update:
I will be storing the paths in the database, and with the mapping to the type of controller so like:
path controller
/article_section1/ article
/blog1/ blog
/blog2/ blog
..
With the above information, how could I dispatch the request to the correct controller?
Again, not looking to reload/redeploy, and I realize this will require more work but its in the spec :)
Would this sort of URL mapping work for you?
www.example.com/blog/1/
www.example.com/blog/2/
If yes, then that's easy: Spring 3 supports path variables: http://static.springsource.org/spring/docs/3.0.x/reference/mvc.html#mvc-ann-requestmapping-advanced
Alternatively, you can create a generic request mapping and your own sub-dispatcher that reads a config file, but I think that's probably more work than it's worth.
Truly changing the request mappings at runtime might be hard (and not really recommended, since small errors can easily occur). If you still wish to do it, perhaps JRebel, and more specificly LiveRebel can be interesting for live redeployment of code and configuration.
Otherwise, like other posts suggested, RequestMappings supports wildcards, the limits of this should be clear after a quick read of the official documentation.
Try using with #RequestMapping wild cards as below:
#RequestMapping(value="/article_section*/"}
public void getArticle(....){
//TODO implementation
}
#RequestMapping(value="/blog*/"}
public void getBlog(....){
//TODO implementation
}
Hope this helps!!!
Also another solution might be to create a custom annotation that holds the already defined path on the #RequestMapping and also the new one to apply, let's say #ApiRestController.
Then, before the Spring context loads, the #Controller classes can be changed to have their annotation values changed at runtime by the new one (with the desired path). By doing this, Spring will load the enhanced request mapping and not the default one.
Created a small project to exemplify this for someone that needs this in the future https://gitlab.com/jdiasamaro/spring-api-rest-controllers.
Hope it helps.
Cheers.
doesn't this work?
#RequestMapping("/helloWorld*")

Instance of resource in Java rest api

I have a java rest api. What I want to know is this:
Say one specific client (e.g. person named X is using computer Y) makes three calls to the same uri. (e.g. https://stackoverflow.com/firstname/kasav/lastname/bere). Further, say the resource has a non-static counter.
class ResourceA{
int count = 0;
#Get
public Response service(){
count++;
//return count below
}
}
Now does the caller get the same response for all three calls:
1
Or does the caller get 1 for the first call, then 2 for the second call, then 3 for the third call.
For some of you this may be obvious, but not to me. Thanks for helping.
Assuming you are using something that follows JAX-RS spec correctly.
3.1.1 Lifecycle and Environment
By default a new resource class instance is created for each request to that resource. First the
constructor (see section 3.1.2) is called, then any requested
dependencies are injected (see section 3.2), then the appropriate
method (see section 3.3) is invoked and finally the object is made
available for garbage collection. An implementation MAY offer other
resource class lifecycles, mechanisms for specifying these are outside
the scope of this specification. E.g. an implementation based on an
inversion-of-control framework may support all of the lifecycle
options provided by that framework.
As such the answer to your question is all callers will receive 1 as the class is initiated for each request.
See JSR-311 for the JAX-RS spec.
By default JAX RS resources are request scoped, means it create new instances for each request.
To process the multiple requests with the same instance of the resource you can mark the resource (class ResourceA in this case) with the annotation #Singleton.
Marking as Singleton will make the output of the ResourceA class as 1 for first request, 2 for second request and so on.

Categories

Resources