AspectJ Advice on Spring Security ProviderManager throws exception on startup - spring

Does anyone know why when I try to create an advice around the "doAuthentication" method of the Spring Security (v3.0) ProviderManager my application throws an exception on startup?
I am autowiring an instance of my spring authentication-manager bean into a controller and when the autowire is attempted my app fails to deploy.
Here is what my security context xml looks like...
...<authentication-manager alias="authenticationManager"> ...
Here is the pertinent part of my controller...
#Autowired
private ProviderManager authenticationManager;
and here is my advice declaration:
#After("execution(* org.springframework.security.authentication.ProviderManager.doAuthentication(..)) && args(authentication)")
Any help will be greatly appreciated!

I'm not sure from the available information, but I'm guessing that you're using Spring AOP, which uses JDK dynamic proxies by default, so you are coming across the usual problem that the proxy does not retain the type of the original class (ProviderManager). The proxy will implement the interface AuthenticationManager, however. Try autowiring using this type and see if it works. Either that or you can enable class proxying which uses cglib instead of dynamic proxies. If you're using the Spring AOP namespace, you can set the proxy-target-class attribute to true.

Related

How to inject ResourceInfo in a ContainerRequestFilter in CXF

I am trying to build a token based authentication and authorization system using Apache CXF and Spring. I am completely following this fantastic post for doing this.
But I am stuck in a problem with my AuthorizationFilter at the very beginnig. I have seen many posts, apache JIRA, github comments about it, but could not yet found the workaround about this seemingly CXF issue.
#PreMatching
#Priority(Priorities.AUTHORIZATION)
public class AuthorizationFilter implements ContainerRequestFilter {
private ResourceInfo resourceInfo;
#Context
public void setResourceInfo(ResourceInfo resourceInfo) {
this.resourceInfo = resourceInfo;
}
#Override
public void filter(final ContainerRequestContext requestContext) throws IOException {
Method method = resourceInfo.getResourceMethod();
In the above code, the injected resourceInfo is a proxy object, and it has none of the associated properties present. So, anything from that resourceInfo object is returning null, more specifically resourceInfo.getResourceMethod() is null, leading to NPE.
This is the JIRA post pertaining to this very issue, saying that:
In some circumstances (like using #ApplicationScoped annotation for example) the CDI runtime will create a proxy class for a particular bean. As the result, the CXF side is going to bind the particular provider metadata to this proxy instance. It looks logical and unambiguous.
However, the interesting things are happening when CXF will try to inject contextual proxies (#Context annotations) into the provider instance. The injections are successful but the target object for them will be the proxy instance (not the real instance behind it). Consequently, at runtime, when the proxy delegates the call to a backing instance, all contextual proxies are null in there (simply put, not set).
Referring to the recent discussions with Sergey Beryozkin, the best solution would be to delegate the #Context annotation to CDI framework (as such, relieving the CXF from doing the injection work). This proposal may need a support from the JAX-RS specification side.
Simpler (interim?) possible solution would be to complement the CDI injection with #Context injection (delegating this work to the CXF as it works right now for non-proxy beans and non-CDI deployments). This could be done by observing ProcessInjectionTarget events and supplying our own InjectionTarget (have working PoC for this approach).
Regarding constructor injection, it seems like CXF does not support passing the arguments to provider constructor (in case of CDI, w/o #Context annotation) so I it would be another (separate) issue to look at.
Can someone help me point out what is this simpler approach is all about:
Simpler (interim?) possible solution would be to complement the CDI injection with #Context injection (delegating this work to the CXF as it works right now for non-proxy beans and non-CDI deployments). This could be done by observing ProcessInjectionTarget events and supplying our own InjectionTarget (have working PoC for this approach)
Or is there any other way, where Spring Framework can inject the ResourceInfo object in a correct way?
I have registered the filters like this in my applicationContext.xml :
<jaxrs:server id="endpoints">
<jaxrs:providers>
<ref bean="authenticationFilter" />
<ref bean="authorizationFilter" />
</jaxrs:providers>
</jaxrs:server>
The problem is the #PreMatching annotation.
Global binding annotation that can be applied to a container request filter to indicate that such filter should be applied globally on all resources in the application before the actual resource matching occurs.
The key is highlighted part "before the actual resource matching occurs". So even before the resource is matched to the request, the filter is called. And if there is no resource matched yet, then it is impossible to get any information from the ResourceInfo. If you just remove the #PreMatching annotation, then the filter will be called after a matching resource is found, and you will be able to access all the info from the ResourceInfo.

How does AuthenticationManager implementation gets instantiated in SpringBoot App

Including spring security starter dependency makes AuthenticationManager available in a spring boot application. I can simply Autowire the AuthenticationManager. How does SpringBoot understand to automatically instantiate the bean for AuthenticationManager though it is in a very different jar file ?
for e.g.
I can simply write
#Autowire
AuthenticationManager authManager;
in my SpringBoot App after including the dependency. How does spring know that it is supposed to instantiate which class and how ?
The class org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration imports the configuration class org.springframework.boot.autoconfigure.security.AuthenticationManagerConfiguration, which then provides the bean for the AuthenticationManager (it will use a builder to build the authentication manager according to the configuration which is provided).

NullPointerException in AbstractRememberMeService after upgrading to Spring Boot 1.4

After upgrading from Spring Boot 1.3.8 to Spring Boot 1.4.4 I get a NullPointerException in AbstractRememberMeServices because the logger isn't instantiated successfully.
A NullPointerException is thrown on this Line.
I write a custom RememberMeService which extends AbstractRememberMeServices. This service is registered as a bean as you can see in the following code snipped:
#Bean
RememberMeServices rememberMeServices(UserDetailsService userDetailsService, UserRepository userRepository, RememberMeTokenRepository rememberMeTokenRepository, RandomService randomService) {
String key = env.getProperty("security.rememberme.key");
RememberMeService rememberMeService = new RememberMeService(key, userDetailsService, userRepository, rememberMeTokenRepository, randomService);
rememberMeService.setAlwaysRemember(true);
return rememberMeService;
}
This error seems related to this SO question. Additionally JHipster has a similar issue.
Does anyone know why the logger isn't instantiated successfully?
I know this is an old question but I just encountered the same thing in a library's custom RememberMeServices impl. You may find an indication of the problem mentioned in the Spring startup logs. For instance:
2018-04-11 07:32:07.311 INFO 1 --- [ost-startStop-1] o.s.a.f.CglibAopProxy : Final method [public final org.springframework.security.core.Authentication org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices.autoLogin(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)] cannot get proxied via CGLIB: Calls to this method will NOT be routed to the target instance and might lead to NPEs against uninitialized fields in the proxy instance.
In this case, the subclass must have some feature that requires proxying by CGLIB, such as #Transactional on a method. If no such features were present, CGLIB wouldn't be necessary and the subclass would behave as expected.
Also got this error. When I debug, I find out the properties of AbstractRememberMeServices almost all null. Then I think, maybe the inject of spring not work. So I changed my code to this:
.rememberMe()
.rememberMeServices(new MyRememberMeServices(env, userDetailsService, userRepo, tokenRepo))
.and();
It works. But I don't understand why...

Using proxy-target-class="true" with Spring beans

Im using Jersey Rest and want a Jersey filter to have access to some spring beans.
however as I've discovered from other threads, Jersey does not obtain Spring beans if they are Java proxies as opposed to generated java proxies. I want to add the proxy-target-class="true"
What are the impacts of doing so and also can this just be set on a single bean or does it need to be set on all referenced beans?
By setting proxy-target-class="true" you will be using CGLIB2 for your proxies, instead of jdk proxys.
The implications are the following, as described in the documentation:
final methods cannot be advised, as they cannot be overriden.
You will need the CGLIB 2 binaries on your classpath, whereas dynamic proxies are available with the JDK. Spring will automatically
warn you when it needs CGLIB and the CGLIB library classes are not
found on the classpath.
The constructor of your proxied object will be called twice. This is a natural consequence of the CGLIB proxy model whereby a subclass
is generated for each proxied object. For each proxied instance, two
objects are created: the actual proxied object and an instance of the
subclass that implements the advice. This behavior is not exhibited
when using JDK proxies. Usually, calling the constructor of the
proxied type twice, is not an issue, as there are usually only
assignments taking place and no real logic is implemented in the
constructor.
Also, you should be able to make a "target-proxy" for a specific component by using
proxyMode=ScopedProxyMode.TARGET_CLASS
Forcing a CGLib-Proxy although the controller formally implements an interface (SpringBoot 1.2.3.RELEASE with Spring 4.1.6.RELEASE):
#Controller
#Scope( proxyMode = ScopedProxyMode.TARGET_CLASS )
public class ServiceImpl implements ServiceIntf
{ .... }
This enables valid and working #RequestMapping and #Transactional annotations
Use the following annotation in Java Spring Config class:
#EnableAspectJAutoProxy(proxyTargetClass = true)
This is the way I made my test working:
MyTarget target = new MyTarget();
AspectJProxyFactory factory = new AspectJProxyFactory(target);
factory.setProxyTargetClass(true);

Does this annotation work for Spring declarative transaction

As far as I know, Spring uses JDK to generate dynamic proxy for the classes that implement any inferface while use Cglib to generate dynamic proxy for the classes that do not implement any inferface. For decarative transcation, Spring uses proxy to add transaction aspect. Please take a look at the code below:
interface Demo {
void methodA();
}
public class DemoImpl implements Demo{
#Transactional
public void updateA() {}
#Transactional
public void updateB() {}
}
I think updateA can work well with transaction. But how about updateB method? Does the #Transactional work for it?
Maybe my understanding is not correct. It's great if the related Spring source code is provided to explain how Spring use JDK/cglib to proxy the class and interface. Thanks
I have the config in the xml:
<tx:annotation-driven transaction-manager="transactionManager" />
JDK dynamic proxy
In this case your bean is wrapped with a proxy implementing Demo interface. From that moment you can only use that interface. Trying to inject or fetch bean of DemoImpl type will result in dreadful Abstract DAO pattern and Spring's "Proxy cannot be cast to ..." problem!
This kind of answers your question - you can only access updateA() and this is the only transactional method. Annotation around updateB() is ignored.
However if you call updateB() from updateA() it will be transactional because it will bind to a transaction started by updateA() (with default transaction propagation).
CGLIB proxy
In this case the interface is ignored. cglib will create a subclass of DemoImpl (obviously also implementing Demo interface) and apply transaction behaviour on both update*() methods. Now if you inject bean of type DemoImpl (interface is not needed in this case at all and Impl suffix is ugly) you can safely and transactionally call both methods.
See my article: Spring pitfalls: proxying and Spring AOP riddle for greater details.

Resources