I want to run authentication/authorization only for the calls that come from HTTP requests.
The method on the controller I want to have authentication/authorization enabled is called from more than one source. In this case, it can be either called by another controller or by a direct HTTP request.
Can I turn off authentication/authorization for the calls that come from other Controllers?
Just read further if you haven't got this clear enough yet.
Let's say I have a method doIt() on a Controller A. I also have a Controller B, in which I inject controller A. At some point on Controller B, I call 'a.doIt()', but I can also call doIt() from an HTTP call to doIt.do.
I want to test the call for authentication/authorization if the call comes from an HTTP call, but not if it comes from Controller B.
You are injecting in B the security proxied bean of A. Can't you inject A without the proxy?. Bean A proxied:
<bean id="beanASecured" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="targetName" value="beanA"/>
<property name="interceptorNames">
<value>securityInterceptor</value>
</property>
</bean>
The secutiryInterceptor:
<bean id="securityInterceptor" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
...
</bean>
Bean A not proxied:
<bean id="beanA" class="com.A"/>
Bean B injected with bean 'A not proxied':
<bean id="beanB" class="com.B">
<constructor-arg ref="beanA"/>
</bean>
You need to only configure the spring authentication on URL and not on the method invocation. This will work for you.
I don't see any way to do this, my guess is you'll just have to have a second method like doitDirectCall(..) that the actual other controller calls and doit(..) that get's called on an HTTP request.
Related
Is it possible to have to have UserDetailsService implementations in a single web application ?
To be more precise, my requirement is I have a Servlet which listens to http POST requests which needs to authenticated against a one type of user(lets say UserType 1), the Http POST request contains some fields that I could used to authentication user(user id, and some Hash String). Upon successful authentication user is again forwarded to another login page where again authentication happens this time user type is UserType 2.
Here,
The UserType 1 and UserType 2 have two separate principal and credentials.
I need to Http POST request parameters to flow to session of the UserType 2( I.e. session 2).
session 2 should survive till session 1 is destroyed.
I also guess I need to have two authentication entry points as well?
My gut feeling is that this is not possible(I wish I were wrong) !
Any clarifications or ideas regarding this?
I am not sure how nested authentication may be implemented with Spring Security. But you can have two separate UserDetailsService implementations. Consider case when you have two types of URLs /** and /admin/**, and they can be used by two separate groups of users. Starting from Spring Security 3.1 you can use multiple http tags (see corresponding documentation):
<http pattern="/admin/**" authentication-manager-ref="adminAuthenticationManager">
<intercept-url pattern="/**" access="ROLE_ADMIN" />
...
</http>
<authentication-manager id="adminAuthenticationManager" >
<authentication-provider user-service-ref="adminUserDetailsService"/>
</authentication-manager>
<bean id="adminUserDetailsService" class="com.mucompany.security.AdminUserDetailsService"/>
<!-- No pattern, so everything will be matched -->
<http authentication-manager-ref="adminAuthenticationManager">
<intercept-url pattern="/**" access="ROLE_USER" />
...
</http>
<authentication-manager id="userAuthenticationManager" >
<authentication-provider user-service-ref="publicUserDetailsService"/>
</authentication-manager>
<bean id="publicUserDetailsService" class="com.mucompany.security.PublicUserDetailsService"/>
You can even declare different entry points for each http tag using entry-point-ref attribute.
I need receive two string parameters in loadUserByUsername method. I do not want to use spring security authentication, for this a have my own implementation that needs password too (It´s a integration system).
Is it possible create another method with the same name loadUserByUsername(String username, String password) in the same class, and call that method instead another one ?
I don't understand this requirement but UserDetailsService.loadUserByUsername(String) is just fine. At the time this method is invoked the user is already authenticated and hence the password is not needed anymore. So, if you need a password at that point there's a fair chance you're doing something wrong.
If you want to implement your own authentication mechanism based on username & password you need to provide your own AuthenticationProvider.
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="yourProvider" />
</security:authentication-manager>
<bean id="yourProvider" class="package.yourProviderClass">
<!-- I suppose you need this, too -->
<property name="userDetailsService" ref="yourUserDetailsService" />
</bean>
Have a look at the existing implementations and find the one that most closely offers what you need.
With requestscoped beans managed by JSF (#Managedbean) you can get the value of a request parameter with #ManagedProperty("#{param.id}").
If the request is a GET request, you can get the value of a request parameter with f:viewParam.
Is there a special mechanism to get the value of a request parameter when the bean is CDI managed (#Named) and the request is a POST request? I only know the Java code
FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("id");
The <f:viewParam> works as good in POST requests.
You should only keep in mind that this runs during apply request values phase only, not during render response phase. So, if you're actually navigating on an action method and expecting the parameter to be set as view parameter of the target page, then you're wrong. It will only be set on the view where the POST request is actually submitting to.
As an evidence that the <f:viewParam> works on POST as well, here's a test snippet:
<f:metadata>
<f:viewParam name="foo" />
</f:metadata>
<h:form>
<h:commandButton value="submit">
<f:param name="foo" value="bar" />
</h:commandButton>
</h:form>
<p>foo: #{foo}</p>
Pressing the submit button will show up foo: bar.
You need to solve your concrete functional requirement in a different manner. As you didn't tell anything about the concrete functional requirement in your question, it's not possible to give an elaborate answer on that. Here are at least some hints:
#Inject target bean and set it as property during action method.
Use <f:setPropertyActionListener>.
Use flash scope.
Send a redirect with parameter in query string.
Please note: This question is about CDI scopes as we are using CDI scopes in the app and not JSF scopes.
1) Controller Bean (TestController.java) which is in RequestScoped (enterprise context) is called index_cut.xhtml, when we come for first time on this page.
2) On button “Load”, we load the following method to populate the sapFinancialPeriodList which works fine and displays the data
3) After changing the content on the page and submitting, the sapFinancialPeriodList appears as NULL in the following method –
Any suggestions?
Your bean is request scoped and you're loading the data model on action only instead of on (post)construction. When the HTTP response after the action which loaded the data is finished, then the bean is garbaged. The subsequent request would get a brand new instance of the bean with all properties set to default. However, as the same data model isn't been preserved during (post)construct, it remains empty.
In JSF2 you'd solve this with using #ViewScoped. This way the bean will live as long as you're interacting with the same view by postbacks (which return null or void).
In CDI you'd need to solve this using #ConversationScoped, which in turn requires some additional #Inject Conversation boilerplate, complete with begin() and end() calls at the right moments. For a concrete example, see also What scope to use in JSF 2.0 for Wizard pattern?.
An alternative is to pass the parameters responsible for creating the data model to the subsequent request via <f:param> in the command link/button as follows
<h:commandButton value="save" ...>
<f:param name="period" value="#{bean.period}" />
</h:commandButton>
and then recreate exactly the same data model in (post)constructor of the request scoped bean as follows
String period = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("period");
List<SapFinancialPeriod> sapFinancialPeriodList = someservice.list(period);
(the above is by the way nicer to solve with #ManagedProperty if you were using standard JSF; as far as I know CDI doesn't have an annotation which enables you to set a HTTP request parameter as a bean property)
See also:
How to choose the right bean scope?
Unrelated to the concrete problem, the upcoming JSF 2.2 solves this functional requirement in a nicer way using the new "Faces Flow" feature with the new #FlowScoped annotation and the new xmlns:j="http://java.sun.com/jsf/flow" tags.
Is it possible, that Spring.Net Aspects don't work with Asp.Net Controller?
I want to configure transactions on Action methods of Controllers but the proxy doesn't seem to trigger.
<object id="ControllerClassPointcut" type="Spring.Aop.Support.SdkRegularExpressionMethodPointcut, Spring.Aop">
<property name="patterns">
<list>
<value>xxx.Controllers.CompanyController.*</value>
</list>
</property>
</object>
<aop:config>
<aop:advisor pointcut-ref="ControllerClassPointcut" advice-ref="TxAdvice"/>
<!-- TxAdvice taken from ServiceContext -->
</aop:config>
<tx:advice id="TxAdvice" transaction-manager="TransactionManager">
<tx:attributes>
<tx:method name="*" propagation="Required"/>
</tx:attributes>
</tx:advice>
and the action method of the CompanyController is:
[HttpPost]
public virtual ActionResult Create(Guid id, CompanyonViewModel vm)
{
...
}
but I the advice does not take effect although the pointcut is recognized. If I take an other class than a controller as pointcut it works.
for some methods the advice works. For example for the setter for the repository. But Sprint.Net does not recognize that the action method "Create" is called
Candidate is: 'xxx.Controllers.CompanyController.set_CompanyService'; pattern is 'xxx.Controllers.CompanyController.*'; matched=True
Candidate advisor [DefaultObjectFactoryPointcutAdvisor: pointcut [Spring.Aop.Support.SdkRegularExpressionMethodPointcut]; advice object = 'TxAdvice'] accepted for targetType [xxx.Controllers.CompanyController]
Thanks for your help
Can you try with the configuration
<aop:config proxy-target-type="true">
This will create an inheritance based proxy. you may need to download a recent nightly build of spirng.net for this to work (not 1.3.0).
I had a similar a problem with the [Transaction] attribute (which works using Spring.AOP).
In my case, I called the [Transaction] flagged methods from within the same class and was surprised that the transaction advice didn't fire.
The explanation was, that when calling a [Transaction] marked method from within the class, you hold a reference to the real instance instead of the AOP-proxied instance, therefore the call does not get intercepted.
When a request is made to an MVC app, then from the request url a controller is chosen (from the IControllerFactory instance). On this controller, the Execute method is called, which in turn is responsible for calling the actions. So I think that action methods are always called from within the controller. Which means that by definition action methods will never get intercepted. This would explain why those pointcuts are recognized, but don't fire.
if I take an other class than a
controller as pointcut it works
It also explains why pointcuts on other classes than controllers do fire: they are likely called from a controller, which will hold a AOP-proxied reference to instances of the other classes.
... for some methods the advice works ... For example for the setter for the
repository
I assume that your (for instance) CompanyController.CustomerController has a property CustomerRepository, set using DI. It makes sense that this pointcut fires, because the setter is called from outside the CompanyController.CustomerController, for instance by your DI container (or your ControllerFactory).
A solution could be to introduce service objects, on which you define the transaction advice that you now have on your controllers. From your controllers, you call methods on these service objects - and then the pointcuts will fire.