I'd like to ask how can I handle (e.g. catch, log and redirect flow ) AccessDeniedException that comes from 'security annotation' (#PreAuthorize, #Secured, etc...)?
I tried setting my own AccessDeniedHandler:
<http auto-config="true" use-expressions="true">
...
<access-denied-handler ref="myAccessDeniedHandler" />
</http>
but it seems, that it intercepts only exceptions that are raised when I try to get to unauthorized resource.
But exception that comes from
#PreAuthorize("hasRole('ROLE_ADMIN')")
public void myMethod(){
System.out.println("Secret Method");
}
is not handled that way.
This post is a bit old, so i guess you don't need an answer anymore. Still answering this for other people:
First: You are right: <access-denied-handler ref="myAccessDeniedHandler" /> only handles requests for resources, so you need something different for handling AccessDeniedExceptions thrown by your own code or by Spring-Security because of #PreAuthorize.
What you can do is using Spring-AOP/AspectJ to write an around-aspect with a pointcut referencing all methods that are annotated with a specific annotation (in your case #PreAuthorize)
see JSF2 with SpringSecurity: handle AccessDeniedException of #Secured-Annotation for an example of handling #Secured-annotations
Related
We are facing an issue while exception is encountered in transformer.
Below is the scenario:
We have a router and a transformer with the below configuration
<bean id="commonMapper"
class="com.example.commonMapper"></bean>
<int:router input-channel="channelA" ref="commonMapper"
method="methodA" />
<int:transformer input-channel="channel_2"
ref="commonMapper" method="methodB"
output-channel="channelC"></int:transformer>
CommonMapper.java :
public String methodA(SomeBean someBean) {
if (<some business condition example someBean.getXValue()>) {
return "channel_1";
} else if(<some condition>) {
return "channel_2"; // Assuming it enters this condition, based on this the above transformer with input-channel="channel_2" gets called
}else if (<some condition>) {
return "channel_3";
} else {
return "channel_4";
}
}
public SomeBean methodB(Message<SomeBean> message)
throws Exception{
SomeBean someBean = message.getPayload();
someBean.setY(10/0); // Purposely introducing an exception
}
While debugging the application, we found that whenever an exception is encountered in methodB(), the control goes back to router reference method i.e. methodA() and again satisfy the condition and calls the transformer (with input-channel="channel_2"). This repeats for certain iteration. And then exception is logged via AnnotationMethodHandlerExceptionResolver -> resolveException.
Below are the queries:
Why does the router gets called again when it encounters an exception in transformer?
Is it the bug or the normal behavior?
How to tackle this issue?
Please let me know if you need any more details around it.
The Spring Integration flow is just a plain Java methods chain call. So, just looks at this like you call something like: foo() -> bar() -> baz(). So, when exception happens in the last one, without any try...catch in the call stack, the control will come back to the foo() and if there is some retry logic, it is going to call the same flow again.
I'm not sure what is your AnnotationMethodHandlerExceptionResolver, but looks like your talk about this one:
Deprecated.
as of Spring 3.2, in favor of ExceptionHandlerExceptionResolver
#Deprecated
public class AnnotationMethodHandlerExceptionResolver
extends AbstractHandlerExceptionResolver
Implementation of the HandlerExceptionResolver interface that handles exceptions through the ExceptionHandler annotation.
This exception resolver is enabled by default in the DispatcherServlet.
This means that you use pretty old Spring. I don't think that it is related though, but your top of the call stack is Spring MVC. You need to take a look there what's going on with the retry.
And answering to all you question at once: yes, this is a normal behavior - see Java call explanation above. You need to debug Spring code from the IDE to figure out what is going on the MVC level
i have a code
<int-jpa:updating-outbound-gateway
auto-startup="true"
native-query="update Transactions t set t.transaction_Status = :transactionStatus
where t.bank_Reference_Number = :bankReferenceNumber "
entity-manager="entityManager" persist-mode="PERSIST"
use-payload-as-parameter-source="false">
<int-jpa:transactional />
<int-jpa:parameter name="transactionStatus" expression="payload['transactionStatus']" />
<int-jpa:parameter name="bankReferenceNumber" expression="payload['bankReferenceNumber']" />
</int-jpa:updating-outbound-gateway>
i want to add error channel , so that if some exception occurs i can see that.
The error-channel is for flows which works independently of the user: Message Driven Channel Adapter, e.g. <int-jms:message-driven-channel-adapter>, where an Listener Container is started in the infinite loop and does its work actively.
Another sample is Polling Consumer, which runs the polling task periodically, e.g. <int-file:inbound-channel-adapter>, or anyone as a consumer on the QueueChannel. And again: it does that actively, independently of your existence.
The <int-jpa:updating-outbound-gateway> is passive component, therefore it can't do anything until you send a message. Therefore any error caused in this kind of components are thrown to the caller, like it is done in the raw Java method invocation.
Read more about error handling in the Reference Manual.
For your use-case you should consider to add error-channel in the upstream poller if that.
Another case is ExpressionEvaluatingRequestHandlerAdvice, which with its failureChannel may play some kind of error handling for the particular MessageHandler.
The error channel goes on some upstream component (usually whatever starts the flow).
An alternative is to add and ExpressionEvaluatingAdvice to the gateway; see the reference manual.
I am making a page in which I call a PrettyFaces page-load action method:
<url-mapping id="informes-perfil">
<pattern value="/informes/#{informesPerfilMB.codigo}" />
<view-id value="/faces/informes_perfil.xhtml" />
<action onPostback="false">#{informesPerfilMB.load()}</action>
</url-mapping>
For some reason, the informesPerfilMB.load() action is called twice, and the parameter value in the second call is 'null' or 'RES_NOT_FOUND'.
Here is my load method:
public void load() {
if (isPostBack) {
isPostBack = false;
try {
System.out.println(codigo);
informe = informeEJBServiceLocal.getByCodigo(codigo);
this.buscarInformeIngreso();
this.buscarInformeOtroIngreso();
} catch (EJBServiceException e) {
e.printStackTrace();
}
}
}
The isPostBack variable is initialized to false, so this should prevent the method from being called again, but for some reason it is.
This code first prints String: dcc509a6f75849b.
Then when the load is repeated, it prints this: RES_NOT_FOUND
I hope this code helps explain what is happening enough to solve my problem, Thanks.
I've seen this happen on my similar system in the past. I think it's an interaction between faces and prettyfaces with missing files. The RES_NOT_FOUND part comes from the network traffic. There's some likely faces resource (or stylesheet) that it's trying to find in libraries and when it can't, it essentially causes the browser to go to the URL /informes/RES_NOT_FOUND. For some reason, it would often find that resource if I refreshed the page and wouldn't issue a RES_NOT_FOUND URL.
First, I'd open up the page source, and you'll find RES_NOT_FOUND, likely along with the stylesheets. Given the position of it, you might be able to correlate it to the resources loaded in your xhtml files and see which one's missing. If that doesn't help, try the developer tools and see which resources are loaded and which are not. Then make sure the resource is present, deployed, and is in the correct location.
If it's not something that you can control (like a library resource), you can always make sure your setCodigo function ignores values of "RES_NOT_FOUND".
public void setCodigo(String value) {
if (!"RES_NOT_FOUND".equals(value)) {
this.codigo = value;
}
}
You may be able to modify your security or servlet-mapping settings (in WEB.XML) to prevent URLs ending in RES_NOT_FOUND from getting to the prettyfaces pages, but I don't know enough about it to do that.
First, the reason your isPostBack variable is called twice is most likely because you have two instances of the bean, not one singleton instance. There are a few reasons this could be happening:
Your bean is request scoped and multiple requests are being made to the page.
Your bean is being created multiple times by parts of your application that use it and call the load() method.
I also believe it is possible your method is being called twice because of the way you have written your EL expression (I'm not 100% sure):
<action onPostback="false">#{informesPerfilMB.load()}</action>
^^
Note the parenthesis at the end of your method expression. I believe this will force EL to evaluate the method when the expression is evaluated. Your method expression should look like this:
<action onPostback="false">#{informesPerfilMB.load}</action>
You should also check for other places in your application where this method might be called.
Please let me know if this helps.
I tried to create a single bean which combined the release strategy method and the aggregator method:
public class POJOSingleAggregatorStrategy{
#Aggregator
public Message spliceMessage(List<Message<?>> messages) {
...
}
#ReleaseStrategy
public boolean canRelease(MessageGroup messageGroup) {
...
}
}
<channel id="inputChannel"/>
<channel id="outputChannel"/>
<bean id="aggregatorStrategyBean" class="sample.POJOSingleAggregatorStrategy"/>
<aggregator id="completelyDefinedAggregator" input-channel="inputChannel" output-channel="outputChannel" send-partial-result-on-expiry="false" ref="aggregatorStrategyBean" method="spliceMessage"/>
Without config release-strategy-method, the program works well but it repors a warning:
No annotated method found; falling back to SequenceSizeReleaseStrategy, target:sample.POJOSingleAggregatorStrategy, methodName:null
After configured release-strategy-method="canRelease", the program doesn't work and it reports an exception: java.lang.IllegalStateException: Failed to process message list
Anybody knows how to avoid this warning? (Except for rewrite ReleaseStrategyFactoryBean)
Strange indeed; we have a test case here and here that does the same thing and it works fine.
If you can post a simple test case that reproduces the issue, we can take a look.
You also need to provide the full stack trace for the IllegalStateException.
I'm completely at a loss with my knowledge gap.
Mule 3.3.1 CE. I must use that version for now.
I have a flow which works fine until I try to use a security filter with valid credentials.
The Mule code follows. It won't make much business sense as I've pared it down to the minimum that produces the problem. Normally the outbound call is in a separate flow, but I pulled it into the Main flow for the example.
If I have the security filter on the inbound endpoint commented out and execute this, I get the expected response of the logger message and the "foo" return payload.
<https:connector name="HTTPSConnector" validateConnections="true" sendBufferSize="0" receiveBufferSize="0" receiveBacklog="0" clientSoTimeout="10000" serverSoTimeout="10000" socketSoLinger="0" doc:name="HTTP\HTTPS">
<https:tls-key-store path="/opt/eai/common/keystore/EAIKeystore.jks" keyPassword="${key.password}" storePassword="${store.password}"/>
</https:connector>
<spring:beans>
<ss:authentication-manager alias="authManager">
<ss:authentication-provider>
<ss:user-service id="userService">
<ss:user name="PortalUser" password="password" authorities="ROLE_USER"/>
</ss:user-service>
</ss:authentication-provider>
</ss:authentication-manager>
</spring:beans>
<mule-ss:security-manager>
<mule-ss:delegate-security-provider name="memory-provider" delegate-ref="authManager"/>
</mule-ss:security-manager>
<flow name="Main" doc:name="Main">
<https:inbound-endpoint exchange-pattern="request-response" host="localhost" port="10029" path="sites/r.v1" mimeType="text/xml" encoding="UTF-8" connector-ref="HTTPSConnector">
<mule-ss:http-security-filter realm="mule-realm"/>
</https:inbound-endpoint>
<custom-transformer class="com.ca.eai.esb.transformer.site.StrategySplittingTransformer" doc:name="Split"/>
<collection-splitter/>
<https:outbound-endpoint exchange-pattern="request-response"
address="${https.outbound.account.sap-nameaddress}"
connector-ref="HTTPSConnector"
mimeType="text/xml" responseTimeout="${https.outbound.timeout}"/>
<logger level="INFO" message="GOT HERE"/>
<set-payload value="foo"/>
</flow>
The custom transformer is also pared down to the minimum:
#Override
public Object transformMessage( MuleMessage message, String outputEncoding )
{
MuleMessageCollection collection = new DefaultMessageCollection( message.getMuleContext() );
collection.addMessage( message );
return collection;
}
If I uncomment the security filter and pass in bad credentials, I get the expected security exception.
If, however, I pass in valid credentials, I get an exception that it can't serialize.
Root Exception stack trace:
java.io.NotSerializableException: org.apache.commons.httpclient.ContentLengthInputStream
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1180)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346)
at java.util.concurrent.CopyOnWriteArrayList.writeObject(CopyOnWriteArrayList.java:857)
+ 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
Can someone tell me why adding a security filter causes this?
This is a bug that has been fixed in 3.4.x.
See this answer https://stackoverflow.com/a/17930063/387927 and the comments below it.