I added cronjobs to spring app using quartz.
inside these jobs, I would like to access spring-security secured bean methods from another app.
This is my application structure.
| - core
| - webapp
| - jobs-app
both the webapp and jobsapp use core services. jobsapp is not a web application. It just has quartz jobs in it.
Inside a job if I try to access a bean that is secured using SpringSecurity global-method-security I get an exception {org.springframework.security.AuthenticationCredentialsNotFoundException}"org.springframework.security.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext"
If I set the context using SecurityContextHolder.getContext().setAuthentication to a power user, it works.
But, I have to do this for all the jobs.
Is there a way I can make all the jobs runas a particular user? may be some configuration somewhere?
You have two choices:
move #Secured annotation up, from service to web layer. If I understand correctly your Quartz jobs access service beans directly (bypassing the web layer) so you'll bypass the security as well
implement Run-As functionality, just like you described. It doesn't have to be that manual. Try template method pattern or some AOP + annotations. It'll turn out to be rather clean.
We tried both approaches and moving security to web layer worked slightly better. This was possible because service layer was mapping nicely to Spring MVC controller methods.
Related
Can "session" scope beans be used with Spring Session and Pivotal GemFire?
When using Spring Session for "session" scope beans, Spring creates an extra HttpSession for this bean. Is this an existing issue?
What is the solution for this?
Regarding...
Can session scoped beans be used with Spring Session and GemFire?
Yes!
In fact, it does not matter which underlying "provider" is used with Spring Session either. For example, either Spring Session with GemFire/Geode (docs) or Spring Session with Redis (docs), etc, can be used and it will work just the same (in the same way).
As for...
If using Spring Session for session scoped beans Spring creates extra HttpSession for this bean, is this an existing issue?
Well, this is not exactly true.
You have to understand the underlying technologies in play here and how they all work together, including Spring Session, the Spring Framework, the Servlet Framework, your Web container (e.g. Tomcat), which is bound by the contract specified in the Java EE Servlet spec, and any other technologies you may have applied (e.g. Spring Security's Web support).
If we dive deep into Spring's architecture/infrastructure, you will begin to understand how it works, why it works and why your particular statement ("Spring creates an extra HttpSession for this bean") is not correct.
First, Spring Session registers an all important Servlet Filter, the o.s.session.web.http.SessionRepositoryFilter.
There are many different ways to do this, and the Javadoc for javax.servlet.Filter essentially hints that this is done via the Web Application "deployment descriptor".
Of course, given our menagerie of configuration options today, a Web Application deployment descriptor is pretty loosely defined, but we commonly know this to mean web.xml. However, that is not the only way in which we can configure, essentially, the Web Application's ServletContext.
Spring supports both web.xml based deployment descriptors as well as JavaConfig using the Servlet (3.0+) API.
In web.xml you would register (for example) the Spring Frameworks' o.s.web.filter.DelegatingFilterProxy, that delegates to an actual javax.servlet.Filter implementation (when Spring Session is in play, that would be the o.s.session.web.http.SessionRepositoryFilter, of course) which is also declared/defined as a "bean" (first this, then this) in the Spring container. This is necessary in order to auto-wire (inject) the appropriate Spring Session o.s.session.SessionRepository implementation (also a Spring managed bean defined in the container, e.g. for Redis) that knows how to delegate (HTTP) Session state management to the underlying "provider".
In the JavaConfig approach, the registration is performed via the core Spring Framework's o.s.web.WebApplicationInitializer concept. Read the Javadoc for more details.
Well, Spring Session provides such a WebApplicationInitializer to initialize (HTTP) Session management, the o.s.session.web.context.AbstractHttpSessionApplicationInitializer. Typically, when using Spring's Java-based Container Configuration and/or Annotation configuration approach, a developer would create a class that extends this Spring Session provided class and register the necessary configuration (e.g. connection criteria) for the underlying Session management provider; for example (see also this). The Config class is annotated with #EnableRedisHttpSession which imports the Spring #Configuration class that declares/defines the appropriate Spring Session SessionRepository implementation for the "provider" (e.g. again Redis), which is needed by the Servlet Filter (again SessionRepositoryFilter).
If you look at what the Spring Session AbstractHttpSessionApplicationInitializer does, you will see that it registers the Spring Session, SessionRepositoryFilter, indirectly via Spring Framework's DelegatingFilterProxy... from insert, then here, then here and finally, here.
As you can see, the Spring Session SessionRepositoryFilter is positioned first in the chain of Servlet Filters. The !insertBeforeOtherFilters is negated since the parameter in javax.servlet.FilterRegistration.Dynamic.addMappingForUrlPatterns(dispatcherTypes, isMatchAfter, urlPatterns...) is "isMatchAfter".
This is essential, since the Spring Session's o.s.session.web.http.SessionRepositoryFilter replaces both of the javax.servlet.http.HttpServletRequest and javax.servlet.http.HttpServletResponse. Specifically, by replacing the javax.servlet.http.HttpServletRequest, Spring Session can provide an implementation of javax.servlet.http.HttpSession (when HttpServletRequest.getSession(..) is called) that is backed by Spring Session and the provider of the developer's choice (e.g. Redis, GemFire), the whole purpose of Spring Session in the first place.
So, the Servlet Filters see the HTTP request/response before any framework code (e.g. Spring Framework's session scoped bean infrastructure), and especially before any of the Web Application's Controllers or Servlets, get to see the HTTP request/response.
So, when the core Spring Framework's session scoped bean infrastructure sees the (HTTP) Servlet request/response, it sees what Spring Session handed it, which is just an implementation the regular javax.servlet interfaces (e.g. HttpSession) backed by Spring Session.
Looking at the core Spring Framework's o.s.web.context.request.SessionScope "custom" implementation (which handles bean references/bean lifecycles for session scoped beans declared/defined in the Spring container), which extends o.s.web.context.request.AbstractRequestAttributesScope, you see that it just delegates to the o.s.web.context.request.SessionRequestAttributes class. This class is created primarily by Spring's DispatcherServlet, and defines all of its operations (e.g. setAttribute(name, value, scope)) in terms of the "provided" scope defined by the bean (definition) in question. See the source for more details. So the bean gets added to the appropriate HTTP session.
Sure, Spring "will" create a new javax.servlet.http.HttpSession on the first HTTP request, but not without Spring Session's infrastructure knowing about it, since what Spring is using in this case is an implementation of javax.servlet.http.HttpSession backed by Spring Session's "Session".
Also, getSession(true) is also just an indication that the HttpSession is "allowed" to be created if it does not already exist! A Servlet container simply does not keep creating new HTTP sessions for every HTTP request, so long as the session ID can be determined from the HTTP request (which is done via either URL injection... jsessionid or with a cookie, typically). See the javax.servlet.HttpServletRequest.getSession(boolean) for more details.
Anyway, the only other caveat to this entire story is, you need to make sure, especially for GemFire, that...
The Spring "session" scoped beans defined in the container are serializable, either using Java Serialization, or 1 of GemFire's serialization strategies. This includes whatever the bean references (other beans, object types, etc) unless those "references" are declared transient. NOTE: I am not entirely certain GemFire Reflection-based PDX serialization approach is entirely "aware" of "transient" fields. Be conscious of this.
You must make certain that the classes serialized in the session are on the GemFire Servers classpath.
I am working on a configuration option for Spring Session Data Geode/GemFire at the moment to support PDX, but that is not available yet.
Anyway, I hope this helps clear up the muddy waters a bit. I know it is a lot to digest, but it all should work as the user expects.
I will also add that I have not tested this either. However, after reviewing the code, I am pretty certain this should work.
I have made it a task to add tests and samples to cover this situation in the near future.
Cheers!
-John
I have a MVC project that uses OwinConnectorFactory and ConnectorBuilder in startup.cs to create a connector, using the passed-in IAppBuilder. How do I access the connector after startup? Let's say, during authentication?
I've tried the http owin context but couldn't find connectors in request/response items. I didn't know where else to look.
TIA
One approach how to do it is via IoC, if you are using it in the project. Initialize you container right in the class marked by OwinStarutup attribute where all middle layers are wired up too.
Add these instances into the container and leave DI to inject them where ever required.
I have read through the SimpleInjector documentation a few times. But have a few questions.
Context:
3 tier app (presentation (mvc + api controllers), service (business logic), data (repositories, entities, etc)
Unit of Work is a thin wrapper around EF's DbContext
my DbContext and Unit of Work are registered PerWebRequest, using
RegisterWebApiRequest causes an exception, because the Unit of Work is used
outside of Web API requests.
my MVC and Api controllers registered using RegisterWebApiControllers(GlobalConfiguration.Configuration) and RegisterMvcControllers(Assembly.GetExecutingAssembly())
Each controller has one or more services injected into it.
Each service has one or more repositories injected into it.
A service may also have another service injected into it.
I want the same Unit Of Work/DbContext to exist in all my services/repositories.
Questions:
Because I am using services in my MVC controllers as well as API controllers; does that mean I can not use RegisterWebApiRequest in place of RegisterPerWebRequest?
none of my services, repositories, etc, maintain any state, I would get the same functionality using PerWebRequest as Transient; is there any advantage to using PerWebRequest over Transient?
Please read the following q/a: How to configure simple injector container and lifestylse in a MVC web app with WebAPI, WCF, SignalR and Background Tasks. The answer explains that:
Putting your Web API in the same project as your MVC controllers is a bad idea from an architectural perspective.
But if you want to do this, you can use the WebRequestLifestyle in both type of applications. The WebApiRequestLifestyle is meant as lifestyle that works for Web API for both IIS and self-hosted environments, but since you placed the Web API controllers in the same project, you are clearly only interested in IIS-hosted; in that case the WebRequestLifestyle will do just fine.
Because I am using services in my MVC controllers as well as API controllers; does that mean I can not use RegisterWebApiRequest in place of RegisterPerWebRequest?
Both lifestyles use a different way of caching. The WebRequestLifestyle uses the HttpContext.Current.Items dictionary to store its SimpleInjector.Scope instance, while the WebApiRequestLifestyle uses the CallContext class to store the Scope during the lifetime of a single asynchronous operation.
Just as the WebRequestLifestyle can be used while resolving Web API controllers, you can use the WebApiRequestLifestyle (or the underlying ExecutionContextScopeLifestyle) for MVC controllers as well. But if you want this, you will create your own IDependencyResolver implementation for MVC that will explicitly start and end an ExecutionContextScope. The absense of a Scope stored in the CallContext is the reason resolving MVC controllers fails when registering services using the WebApiRequestLifestyle. But while it's possible to use the WebApiRequestLifestyle in MVC, the otherway around is much easier, since no custom code is required.
none of my services, repositories, etc, maintain any state, I would get the same functionality using PerWebRequest as Transient; is there any advantage to using PerWebRequest over Transient?
If services don't have state, it doesn't matter what lifestyle they have. The only restriction is that they have dependencies that have a lifestyle that is equal to or longer than their own. Violating this restriction is called Captive Dependencies and can cause all kinds of trouble. Because captive dependencies are bad, Simple Injector v3 checks and prevents this for you.
Although you can probably make all objects in your configuration scoped (non-transient), making them transient is usually easier to configure, and might result in better performance (although you will probably never notice the difference in real life).
Is it possible to use the Grails Cache plugin's annotations (ie: #Cacheable) on methods in normal Groovy classes? The plugin's documentation doesn't mention anything about normal Groovy classes and based on my own tests the annotations have no effect when used in a normal class. So I'm just wondering if there's a way to get the annotations to work in a normal Groovy class.
The current alternative is to simply directly access the cache in the method via the Cache Manager bean, but it would be nice to use the annotations instead.
No, the annotation only works on services and controllers. The plugin detects the annotation and creates a proxy for the service which intercepts all method calls and does the cache-related work first. So if there is a value in the cache for that method, it won't bother calling your real method but return the cached value instead. But if it's not cached, it will call your method and use its return value, but cache that for later.
This works because you have to retrieve the service from the Spring ApplicationContext (or have Grails do that for you) and this gives Spring a chance to give you the proxy instead of the real implementation instance, but there's no way for Spring to know about access to regular Groovy classes without AOP or some other more invasive solution.
Having said that, the plugin is probably being overly strict in limiting to only controllers and services. It handles controllers specially because those involve caching web requests instead of method return values, but there shouldn't be much difference between a Grails service and any other annotated Spring bean as far as caching goes. You can add your own Spring beans, either manually in grails-app/conf/spring/resources.groovy or by adding them to the grails.spring.bean.packages list in Config.groovy, so the plugin should be updated to look for all annotated classes. You can request this in the plugin's JIRA at https://jira.grails.org/browse/GPCACHE
I'm replacing the service tier in an existing older Struts2 project with Spring service beans developed for another project.
I'd like to just #Inject these service beans into my Action classes.
Is it required to use Struts' Spring Plugin? Or can I add Spring into my Struts web application like I would any other (ContextLoaderListener, applicationContext.xml, context:component-scan)?
Am I missing some reason why the Struts Spring plugin helps me in another way?
Many thanks!
Well you can do the most of the things what you have described in your question as Services layer is completely out of view for the S2 and Struts2 do not care how you are creating your Service layer instances and other things.
Benefits i am seeing of using Struts2-Spring plugin is to delegate creation of Struts2 related things to Spring like Action classes creation,Interceptors,Results etc.
My Suggestion is to use the plugin as you are going to use the Spring in your application so its very good and flexible as well powerful to use the power of Spring DI to create required objects needed by S2 else S2 will use its own data creation factory to create framework component.
Why wouldn't you use the Spring plugin?
It's essentially invisible, uses Spring to create your actions (including injecting other Spring beans), etc.
Guice's #Inject doesn't know anything about Spring beans, AFAIK, so you'd be naming classes manually, they'd be instantiated via normal Java/Guice mechanisms, wouldn't be injected with their own Spring dependencies (unless you did it manually, or via AOP, or whatever).
You'd also need to use non-Spring mechanisms for doing injection in testing, which is fine, but unless you provide more details regarding your usecase, I don't really see a reason to bypass the functionality the Spring plugin provides out-of-the-box.