How can I read SOAP-Headers and add FaultHeaders to a response sent by an AXIS 2 Web Service - soap

I have a WSDL that defines a custom SOAP-header that the client needs to send and a SOAP-Fault header that the server could send as a response.
Now I have a problem. I cannot for the life of me fathom how to set SOAP-Fault-headers on a response generated with AXIS 2 (Version 1.6.1) or read SOAP-Headers that come with a request.
Can anyone point me in the right direction?
Thank you very much in advance.

If is security related you should look to Rampart.
If not, try looking into
ClientSide:
From your stub, retrieve the ServiceClient via _getServiceClient().
enter link description here
ServerSide:
If I recall correctly is done via MessageContext, so from axiscontext opbtain current message context.

Add custom fault to soap response. This can be done in one of two ways.
1) Simply throwing a Java exception with a message will generate a simple Axis2 fault
Example:
throw new java.lang.UnsupportedOperationException("Please implement " +
this.getClass().getName() + "#SomeOperationName");
Also please note: If you generated your service using the Axis2 WSDL2JAVA utility, the line above will be added to the MyServiceName_Skeleton source for each defined WSDL Operation.
Once the .aar is deployed, connectivity to each operation can be verified using a web browser, e.g. https://server:port/axis2/services/MyServiceName?SomeOperationName.
2) Ensure that the WSDL defines an optional (occurs:0) custom Fault structure. This can be sent to client with any other required (and empty) elements.
Example:
com.some.service.operation.SomeOperationNameResponse_Type OPRT = new com.some.service.operation.SomeOperationNameResponse_Type();
com.some.service.SomeOperationNameResponse OPR = new com.some.service.SomeOperationNameResponse();
.
.
.
if ((rcStatusString.equals("Succeeded")) || (rcStatusString.equals("Warning"))) {
<build happy path response>
} else if (rcStatusString.equals("Failed")) {
final MYFault fault = new MYFault();
final MYFault_Type faultType = new MYFault_Type();
final MYFaultList faultList = new MYFaultList();
final MYFaultList_Type faultListType = new MYFaultList_Type();
faultType.setFaultCode("10100");
faultType.setFaultSubcode("9999");
faultType.setFaultType(FaultType_Enum.SYSTEM);
faultType.setFaultReasonText("Some Operation Failed");
faultType.setSeverity(FaultSeverity_Enum.CRITICAL_ERROR);
//fault.setMYFault(faultType);
faultListType.addMYFault(faultType);
OTHRTYPE.setAValue("");
OPRT.setAValueType(OTHRTYPE);
OPRT.setMYFaultList(faultListType);
} else {
throw new java.lang.UnsupportedOperationException(
"MYSERVICE: [Some Operation] Session: "+sessVal+" Request ID: "+rcRequestId+" Unrecognized Completion Status ["+rcStatusString+"]");
}
OPR.setSomeOperationResponse(OPRT);
return OPR;
}

Related

Error 403 - Forbidden on Loading Open Street Map to Win Form with GMap.Net and C#

Trying to load OSM on windows Form using C# and GMap.Net I am getting this error
Exception:The remote server returned an error: (403) Forbidden
private void Form1_Load(object sender, EventArgs e)
{
gMapControl1.DragButton = MouseButtons.Left;
gMapControl1.CanDragMap = true;
gMapControl1.MapProvider = GMapProviders.OpenStreetMap;
gMapControl1.Position = new GMap.NET.PointLatLng(54.6961334816182, 25.2985095977783);
gMapControl1.MinZoom = 0;
gMapControl1.MaxZoom = 24;
gMapControl1.Zoom = 9;
gMapControl1.AutoScroll = true;
}
Can you please let me know why this is happening and how I can fix it?
don't forget to set the instance mode to server/cache and set it to the instance of the open street map provider instead of 'GMapProviders.OpenStreetMap'
GMap.NET.GMaps.Instance.Mode = GMap.NET.AccessMode.ServerAndCache;
gMapControl1.MapProvider = GMap.NET.MapProviders.OpenStreetMapProvider.Instance;
It could also be your web proxy settings, see
https://stackoverflow.com/a/19609539/2368681
"Hi,
All libraries that send a fake user-agent and other faked headers to make the requests appear as if they are coming from web browsers are being blocked. Fix the headers and set a real User-Agent to identify your app and the requests will work again.
Please review our usage policy:
https://operations.osmfoundation.org/policies/tiles/ "
This is verbatim reply from OSM.
https://github.com/judero01col/GMap.NET/pull/45 is being used to track this issue. And hopefully a fix will be merged in a a day or two.
I changed Map Provider from "OpenStreetMapProvider" to "GoogleMapProvider" and the error disappeared.
GMap.NET.GMaps.Instance.Mode = GMap.NET.AccessMode.ServerAndCache;
mapView.MapProvider = GMap.NET.MapProviders.GoogleMapProvider.Instance;

org.keycloak.common.VerificationException: Invalid token issuer

I'm developing an Android app, which uses my REST backend. The backend is running on an JBoss instance, which is secured through Keycloak. Since I've updated my Keycloak from 1.0.7 to 2.1.5 I'm experiencing the following problem.
If I try to call a REST API of my backend, JBoss writes the folowing log:
[org.keycloak.adapters.BearerTokenRequestAuthenticator] (default task-39)
Failed to verify token: org.keycloak.common.VerificationException: Invalid token issuer.
Expected 'http://localhost:8180/auth/realms/myrealm', but was 'http://192.168.178.24:8180/auth/realms/myrealm'
at org.keycloak.TokenVerifier.verify(TokenVerifier.java:156)
at org.keycloak.RSATokenVerifier.verify(RSATokenVerifier.java:89)
192.168.178.24 is the right IP address. It seems to be a configuration issue, but where can I config this address?
Has anybody an idea how to fix this problem?
Very simple solution: Make sure when any of your component contact with Keycloak server, they use the same url.
Detailed explanations:
For your case (same as mine), it seems that your Android app is making http request to http://192.168.178.24:8180/... while your server is requesting (or at least configured to) http://192.168.178.24:8180/.... So change your server such that it will request http://192.168.178.24:8180/....
P.S. The exception seems to be the expected behavior to avoid some attacks.
If you take a look into the implementation, here it throws your Exception.
public static class RealmUrlCheck implements Predicate<JsonWebToken> {
private static final RealmUrlCheck NULL_INSTANCE = new RealmUrlCheck(null);
private final String realmUrl;
public RealmUrlCheck(String realmUrl) {
this.realmUrl = realmUrl;
}
#Override
public boolean test(JsonWebToken t) throws VerificationException {
if (this.realmUrl == null) {
throw new VerificationException("Realm URL not set");
}
if (! this.realmUrl.equals(t.getIssuer())) {
throw new VerificationException("Invalid token issuer. Expected '" + this.realmUrl + "', but was '" + t.getIssuer() + "'");
}
return true;
}
};
I think your Client configuration is not correct. Do you have the same clients as in your Keycloak?

Returning HTTP status 400 from Spring AOP based around Aspect

I have an interesting problem with me (at least it is a problem from my current point of view).
I have a RESTful web service that is exposing an interface. In our environment, we use annotation to decorate the request handlers, e.g. -
#RequiredTokenType("Binary")
public String getRecordInfo(HttpServletRequest request) {
String recordInfo = null;
final String methodName = "getRecordInfo()";
_log.debug("{}: received request", methodName);
// validate the request information
ValidationUtils.validateAcceptHeader(request, MimeConstants.getContentType());
. . .
. . .
return recordInfo;
}
We need to have a CXF interceptor/aspect (spring AOP) to execute before the handler (like the above), and check the HttpServletRequest for token type. If the token type (or any other attribute that is decorating the handler) is not of type specified in the annotation, stop the execution and return HTTP status 400 (bad request). There are about 20 request handlers like the above.
The problem I am facing here is that after writing a spring AOP based around aspect, (like below) I am able to catch the request before getRecordInfo() executes, but when I try to return 400 (or) throw an exception, the HTTP client still sees 200 -
public void validateRequest(ProceedingJoinPoint joinPoint,
HttpServletRequest httpRequest,
RequiredTokenType tokenType) throws Throwable {
final String methodName = "validateRequest()";
_logger.info("{}: Entered, Thread Id: {}", methodName, "" + Thread.currentThread().getId());
// Extract the *REQUIRED* headers from the request ...
final String tokenData = httpRequest.getHeader(HEADER_TOKEN_DATA);
if (tokenData == null || tokenData.trim().length() < MIN_POSSIBLE_TOKEN_SIZE) {
// Error condition .... return (400 Bad Request)
_logger.info("{}: Invalid token. The HTTP request is rejected in lack of a valid token.");
throw new MissingTokenException(HttpStatus.BAD_REQUEST,
ErrorCode.BAD_REQUEST,
"Token is missing from the request.");
}
ValidityToken extractedTokenFromRequest = ValidityToken.initializeFromBase64(tokenData);
// Get the type of the token this request must include ...
String decoratedTokenType = tokenType.value();
_logger.debug("{}: Token Type Required: ", methodName, decoratedTokenType);
if (! extractedTokenFromRequest.getTypeName().equals(decoratedTokenType)) {
// Error condition .... return (400).
_logger.info("{}: {}",
methodName,
"The token in the request mismatches the type specified in RequiredTokenType handler. 400 Bad Request.");
throw new TokenTypeMismatchException(HttpStatus.BAD_REQUEST,
ErrorCode.BAD_REQUEST,
"Token type doesn't match.");
}
// More validations on extractedTokenFromRequest
. . .
. . .
// Continue with the actual business logic if correct token is included ...
joinPoint.proceed();
}
I have checked the log file and I can see the following log entries that confirm that both the request handler and the aspect are being called -
getRecordInfo(): received request
. . .
. . .
validateRequest(): Entered, Thread Id: 792
. . .
. . .
validateRequest(): Invalid token. The HTTP request is rejected in lack of a valid token.
Despite the message, still the client see a 200 and server log shows evidence of other CXF based interceptors executing.
Here is the Spring context XML that is defining the pointcut -
<bean id="vGateKeeper" class="com....core.RequestValidator" />
<aop:config>
<aop:aspect id="methodInvocation" ref="methodInvocationProfiler">
<aop:around method="profileMethodInvocation"
pointcut="execution(* org.springframework.orm.jpa.JpaTransactionManager.commit(..))"/>
<aop:around method="profileMethodInvocation"
pointcut="execution(* org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(..))"/>
</aop:aspect>
<aop:aspect id="gateKeeper" ref="vGateKeeper">
<aop:pointcut expression="execution(* getRecordInfo(..)) and args(httpRequest) and #annotation(modPerms)" id="my"/>
<aop:around pointcut-ref="my" method="validateRequest"/>
</aop:aspect>
</aop:config>
How can Spring AOP aspect can be used to return HTTP 400 in this case, cancelling execution of any other interceptor ?
I was also looking at writing an Apache CXF interceptor to catch the call and return 400 before it reaches the request handler, but then I am not sure, How using an interceptor I can can know which request handler was suppose to execute and what annotation is decorating the request handler. Does CXF interceptor offer any way to know, which request handler will eventually execute ?
I was looking here, (https://cxf.apache.org/docs/interceptors.html) but didn't find anyway.
Any help is appreciated.
Regards,
(*Vipul)() ;
Actually it is rather funny that you ask the community why your advice does not work, but do not post the actual advice code. So all that is left for me to do here is guesswork. I can think of two things:
Your advice returns an int, but the original code returns a String. Actually an #Around advice should return the same type as the wrapped/intercepted method (or Object).
Your advice calls proceed(), but you do not want the original method to be executed and should not call proceed(), but return your own result.
In any case, if my two guesses are wrong, please update your question so maybe I can update my answer or someone else with CXF knowledge (which I have not, I am rather an AOP expert) can find a way for you to do it without AOP.
P.S.: One more question: Have you tested if the advice is actually fired, e.g. by writing log messages inside the advice?

SpringWS - Logging SoapRequest and SoapResponse in a table

I have a SpringWS inplementation with below enpoint implementation
#PayloadRoot(namespace="http://college.com/schema/get_XML_Request/v2",localPart="get_XML_Request")
#ResponsePayload
public JAXBElement<GetStudentResponseType> handleStudentXML(#RequestPayload JAXBElement<GetStudentXMLRequestType> SoapRequest)throws Exception
{
String xmlResponse = "";
com.college.get_student_xml_response.v2.ObjectFactory objectFactory = new com.company.schema.get_student_xml_response.v2.ObjectFactory();
com.college.schema.get_student_xml_response.v2.GetResponseType resType = objectFactory.createGetResponseType();
return objectFactory.createGetStudentResponse(resType);
}
Here my objective is to log the request which coming to my webservice and response which the web service sent back in a table. Is it possible to get the SoapRequest/Soapresponse (In Soapformat) from the above method as a String.Here am able to get the payload, but i need to log with entire SoapRequest(with soapenvelope,body) Please anyone advice on this.
Have a look at the SoapEnvelopeLoggingInterceptor which logs the whole SOAP
Envelope including headers. So basically you can extend it to add the saving to the database functionality.

Invoking REST API for making new component in JIRA

I've to make a new Component in JIRA
I found out the POST url /rest/api/2/component for making new component, but i'm unable to know what type of inputs to be given.
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost postRequest = new HttpPost("http://localhost:8080/rest/api/2/component/");
String authorization = JiraRequestResponseUtil.conversionForAuthorization();
postRequest.setHeader("Authorization", authorization);
StringEntity input = new StringEntity("\"name\":\"Component 1\",\"description\":\"This is a TEST JIRA component\" ,\"leadUserName\":\"fred\",\"assigneeType\":\"PROJECT_LEAD\",\"isAssigneeTypeValid\":\"false\",\"project\":\"TEST\"");
input.setContentType("application/json");
postRequest.setEntity(input);
HttpResponse response = httpClient.execute(postRequest);
this is the code i'm implementing.
Output i'm getting is Failed : HTTP error code : 400
Plz help.
we can't tell you. You need to find documentation on the service you are posting to.
The above code is correct, just add the { & } to the JSON string.