I am getting an error while trying to get an BackBlaze Authorization token. It was working fine before, and suddenly I started getting this error message -
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "allowed" (class au.com.polonious.cloud.node.backblaze.BackBlazeTokenResponse), not marked as ignorable (7 known properties: "authorizationToken", "minimumPartSize", "apiUrl", "downloadUrl", "accountId", "absoluteMinimumPartSize", "recommendedPartSize"])
at [Source: {
"absoluteMinimumPartSize": 5000000,
"accountId": "b0c893f558bc",
"allowed": {
"bucketId": null,
"capabilities": [
"all"
],
"namePrefix": null
},
"apiUrl": "https://api001.backblazeb2.com",
"authorizationToken": "4_001b0c893f558bc0000000000_01851d94_6e8e3e_acct_yxmSYWYVETByLq8bwW8HMQSEjlM=",
"downloadUrl": "https://f001.backblazeb2.com",
"minimumPartSize": 100000000,
"recommendedPartSize": 100000000
}
; line: 4, column: 15] (through reference chain: au.com.polonious.cloud.node.backblaze.BackBlazeTokenResponse["allowed"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:62)
at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:834)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1093)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1489)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1467)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:282)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:140)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3814)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2858)
Here is my code-
private BackBlazeTokenResponse getBackBlazeAuth(String accountId, String applicationKey)
throws Exception{
HttpURLConnection connection = null;
String headerForAuthorizeAccount = "Basic " + Base64.getEncoder().encodeToString((accountId + ":" + applicationKey).getBytes());
log.info("getBackBlaze Auth - headerForAuthorizeAccount - "+headerForAuthorizeAccount);
BackBlazeTokenResponse backBlazeTokenResponse = new BackBlazeTokenResponse();
String tokenJson="";
try {
URL url = new URL("https://api.backblazeb2.com/b2api/v1/b2_authorize_account");
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Authorization", headerForAuthorizeAccount);
InputStream in = new BufferedInputStream(connection.getInputStream());
tokenJson = myInputStreamReader(in);
} catch (Exception e) {
e.printStackTrace();
} finally {
connection.disconnect();
//log.info("Output JSON:"+tokenJson);
ObjectMapper mapper = new ObjectMapper();
//JSON from file to Object
log.info("tokenJson- "+ tokenJson);
backBlazeTokenResponse = mapper.readValue(tokenJson, BackBlazeTokenResponse.class);
log.info("getAuthorizationToken:"+backBlazeTokenResponse.getAuthorizationToken());
return backBlazeTokenResponse;
}
}
The error is in this line -
backBlazeTokenResponse = mapper.readValue(tokenJson, BackBlazeTokenResponse.class);
Not sure why it suddenly started throwing this error, probably something was changed in BackBlaze API. Please help.
This has solved my issue
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
mapper.setVisibilityChecker(VisibilityChecker.Std.defaultInstance().withFieldVisibility(JsonAutoDetect.Visibility.ANY));
Related
We want to get the UserName from the ServiceStack session, but we find that the backslashes in the UserName are not deserialized as expected. The UserName has this format 'domainname\username' and serialized in a jwt token this looks like:
{
"typ": "JWT",
"alg": "HS256"
}.{
"iss": "ssjwt",
"iat": 1635952233,
"exp": 1635955833,
"name": "Robin Doe",
"preferred_username": "domainname\\robindoe"
}.[Signature]
After calling:
var sessionFromJwt = JwtAuthProviderReader.CreateSessionFromJwt(req);
userName = sessionFromJwt.UserName;
The userName variable contains the value 'domainname\\robindoe' instead of 'domainname\robindoe'.
After digging in the ServiceStack code, we pin this down to the PopulateFromMap() method in https://github.com/ServiceStack/ServiceStack/blob/36df74a8b1ba7bf06f85262c1155e1425c082906/src/ServiceStack/Auth/UserAuth.cs#L388.
To demonstrate this problem we have written a small program to prove the point:
class Program
{
static void Main(string[] args)
{
var jwtPayload = JsonObject.Parse(#"{
""iss"": ""ssjwt"",
""iat"": 1635952233,
""exp"": 1635955833,
""name"": ""John Doe"",
""preferred_username"": ""domainname\\username""
}");
var session = new AuthUserSession();
// The PopulateFromMap implementation does not deserialize the json values according to json standards
UserAuthExtensions.PopulateFromMap(session, jwtPayload);
// Notice that the session.UserName still has the escape character 'domainname\\username' instead of the expected 'domainname\username'
Console.WriteLine(session.UserName);
// The PopulateFromMap should deserialize also the values, like in test Can_dynamically_parse_JSON_with_escape_chars()
Can_dynamically_parse_JSON_with_escape_chars();
}
private const string JsonCentroid = #"{""place"":{ ""woeid"":12345, ""placeTypeName"":""St\\a\/te"" } }";
// Source: https://github.com/ServiceStack/ServiceStack.Text/blob/master/tests/ServiceStack.Text.Tests/JsonObjectTests.cs
public static void Can_dynamically_parse_JSON_with_escape_chars()
{
var placeTypeName = JsonObject.Parse(JsonCentroid).Object("place").Get("placeTypeName");
if (placeTypeName != "St\\a/te")
throw new InvalidCastException(placeTypeName + " != St\\a/te");
placeTypeName = JsonObject.Parse(JsonCentroid).Object("place").Get<string>("placeTypeName");
if (placeTypeName != "St\\a/te")
throw new InvalidCastException(placeTypeName + " != St\\a/te");
}
}
Why does UserAuthExtensions.PopulateFromMap(session, jwtPayload) does not deserialize json values with escape correctly in ServiceStack.Auth?
The issue is due to enumerating a JsonObject didn't return the same escaped string value as indexing it which has been resolved from this commit.
This change is available from v5.12.1+ that's now available on MyGet.
This is the json response format that I have and need to read the first node value "html". I have tried to few ways to get the value but unable to get it
[
{
"html": "<!DOCTYPE html>\n <html>\n <head>\n <\/html>\n \n",
<\/html>\n \n",
"headers": {},
"subject": "Register new account",
"messageId": "475603953.247.1565607800153#dfrsbdd201.abc.com.au",
"priority": "normal",
"from": [],
"to": [],
"date": "2019-08-12T11:03:20.000Z",
"receivedDate": "2019-08-12T11:09:42.000Z",
"receivedAt": "2019-08-12T11:09:44.900Z"
},
{+},
{+}
]
I tried couple of things
RequestSpecification emailReq = given().with().pathParam("email",emailName);
Response emailResp = emailReq.contentType("application/json").get("https://restmail.net/mail/{email}");
JSONObject value = new JSONObject(emailResp.asString());
I got this error
org.json.JSONException: A JSONObject text must begin with '{' at 1 [character 2 line 1]
at org.json.JSONTokener.syntaxError(JSONTokener.java:505)
and then I removed this last line to use But this does not gives me error. pls refer screenshot for this
JSONArray responseJson = new JSONArray(emailResp.asString());
Tried this as well
List<HashMap<String, Object>> jsonObjectsInArray = emailResp.jsonPath().getList("$");
for (HashMap<String, Object> singleLeg : jsonObjectsInArray) {
String value = (String) singleLeg.get("html");
}
But again array size is 0
Need some suggestion of how to get the value of node - "html". Pls suggest. what mistake am I doing here?
Thanks in advance
RequestSpecification emailReq = given().with().pathParam("email",emailName);
int retries = 5;
List<HashMap<String, Object>> emails = Arrays.asList();
. . .
emailResp = emailReq.get("restmail.net/mail{email}");
if (emailResp.getStatusCode() == 200) { emails = emailResp.jsonPath().getList("$");
String email = emails.get(0).get("html").toString();
I am trying to download pdf file from server using http client using ntlm Auth Scheme.
but I am getting below error when. The file is getting downloaded when I used wget with username and password as parameters but if I use same username and password it fails with 401 using java code. I am using httpclient 4.2.2
Authentication error: No valid credentials provided (Mechanism level: No valid credentials provided
(Mechanism level: Failed to find any Kerberos tgt))
Below is my code to download pdf using auth.
public ByteArrayOutputStream getFile1(String resourceURL) throws CRMBusinessException {
DefaultHttpClient httpclient = new DefaultHttpClient();
ByteArrayOutputStream tmpOut = null;
try {
ICRMConfigCache cache = CacheUtil.getCRMConfigCache();
String host = cache.getConfigValue(ConfigEnum.DOCUMENT_SOURCE_HOST_NAME.toString());
String user = cache.getConfigValue(ConfigEnum.HTTP_USER_NAME.toString());
String password = cache.getConfigValue(ConfigEnum.HTTP_PASSWORD.toString());
String workstation = cache.getConfigValue(ConfigEnum.CLIENT_HOST_NAME.toString());
// Prerequisites
PreCondition.checkEmptyString(resourceURL, "'resourceURL' cannot be empty or null");
PreCondition.checkEmptyString(host, ConfigEnum.DOCUMENT_SOURCE_HOST_NAME + " property is not set in database");
PreCondition.checkEmptyString(user, ConfigEnum.HTTP_USER_NAME + " property is not set in database");
PreCondition.checkEmptyString(password, ConfigEnum.HTTP_PASSWORD + " property is not set in database");
PreCondition.checkEmptyString(workstation, ConfigEnum.CLIENT_HOST_NAME + " property is not set in database");
// NTLM authentication across all hosts and ports
httpclient.getCredentialsProvider().setCredentials(
new AuthScope(host, AuthScope.ANY_PORT, AuthScope.ANY_HOST),
new NTCredentials(user, password, workstation, MY_DOMAIN));
httpclient.getAuthSchemes().register("ntlm", new NTLMSchemeFactory());
// Execute the GET request
HttpGet httpget = new HttpGet(resourceURL);
HttpResponse httpresponse = httpclient.execute(httpget);
if (httpresponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
tmpOut = new ByteArrayOutputStream();
InputStream in = httpresponse.getEntity().getContent();
byte[] buf = new byte[1024];
int len;
while (true) {
len = in.read(buf);
if (len == -1) {
break;
}
tmpOut.write(buf, 0, len);
}
tmpOut.close();
}
aLog.debug( "IntranetFileDownloaderImpl - getFile - End - " + resourceURL);
return tmpOut;
} catch (Exception e) {
aLog.error("IntranetFileDownloaderImpl - getFile - Error while downloading " + resourceURL + "[" + e.getMessage() + "]", e);
throw new CRMBusinessException(e);
} finally {
httpclient.getConnectionManager().shutdown();
}
}
Has anyone faced this kind of issue before while using httpclient?
What does "Failed to find any Kerberos tgt" mean?
Anybody has any clue on it?
Using kotlin and httpclient version 4.5.8:
val credentialsProvider = BasicCredentialsProvider().apply {
setCredentials(
AuthScope(AuthScope.ANY),
NTCredentials(user, password, null, domain))
}
val requestConfig = RequestConfig.custom().setTargetPreferredAuthSchemes(listOf(AuthSchemes.NTLM)).build()
return HttpClients.custom()
.setDefaultCredentialsProvider(credentialsProvider)
.setDefaultRequestConfig(requestConfig)
.build()
Below code worked for me with http client version 4.2.2.
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpGet httpget = new HttpGet("url");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY,
new NTCredentials("username", "pwd", "", "domain"));
List<String> authtypes = new ArrayList<String>();
authtypes.add(AuthPolicy.NTLM);
httpclient.getParams().setParameter(AuthPNames.TARGET_AUTH_PREF,authtypes);
localContext.setAttribute(ClientContext.CREDS_PROVIDER, credsProvider);
HttpResponse response = httpclient.execute(httpget, localContext);
HttpEntity entity=response.getEntity();
The Nancy documentation seems to say that Pipelines.OnError should return null - as opposed to BeforeResponse which allows both null and a Response object.
All the examples like this one and many code samples here on StackOverflow show a Response being returned in the OnError, just like in the BeforeRequest.
When I attempt to return an HTTPStatus string for the Pipelines.OnError, everything works OK!
But when I attempt to return a Response, I get a compiler error:
Operator '+=' cannot be applied to operands of type 'Nancy.ErrorPipeline' and 'lambda expression'
I'm emulating almost exactly the code in the Nancy example, except for the fact that mine is a TinyIocContainer while the example's is using a StructureMap container and a StructureMap derived bootstrapper
Here's my code:
const string errKey = "My proj error";
const string creationProblem = "Message creation (HTTP-POST)";
const string retrievalProblem = "Message retrieval (HTTP-GET)";
public void Initialize(IPipelines pipelines)
{
string jsonContentType = "application/json";
byte[] jsonFailedCreate = toJsonByteArray(creationProblem);
byte[] jsonFailedRetrieve = toJsonByteArray(retrievalProblem);
Response responseFailedCreate = new Response
{
StatusCode = HttpStatusCode.NotModified,
ContentType = jsonContentType,
Contents = (stream) =>
stream.Write(jsonFailedCreate, 0, jsonFailedCreate.Length)
};
Response responseFailedRetrieve = new Response
{
StatusCode = HttpStatusCode.NotFound,
ContentType = jsonContentType,
Contents = (stream) =>
stream.Write(jsonFailedRetrieve, 0, jsonFailedRetrieve.Length)
};
// POST - error in Create call
pipelines.OnError += (context, exception) =>
{
// POST - error during Create call
if (context.Request.Method == "POST")
return responsefailedCreate;
// GET - error during Retrieve call
else if (context.Request.Method == "GET")
return responseFailedRetrieve;
// All other cases - not supported
else
return HttpStatusCode.InternalServerError;
};
}
private byte[] toJsonByteArray(string plainString)
{
string jsonString = new JObject { { errKey, plainString } }.ToString();
byte[] result = Encoding.UTF8.GetBytes(jsonString);
return result;
}
I had the same problem and I found a nice approach to the problem: http://paulstovell.com/blog/consistent-error-handling-with-nancy.
you should override RequestStartup on the Bootstrapper, here my test code:
protected override void RequestStartup(TinyIoCContainer container, IPipelines pipelines, NancyContext context)
{
pipelines.OnError.AddItemToEndOfPipeline((ctx, ex) =>
{
DefaultJsonSerializer serializer = new DefaultJsonSerializer();
Response error = new JsonResponse(ex.Message,serializer);
error.StatusCode = HttpStatusCode.InternalServerError;
return error;
});
base.RequestStartup(container, pipelines, context);
}
I am facing problem in saving data on google map engine data source. Error : buffer length is greater than 1 : { "error": { "errors": [ { "domain": "global", "reason": "invalid", "message": "This value is invalid." } ], "code": 400, "message": "This value is invalid." }}
where "buffer length is greater than 1 " is a custom message.
Feature :
{"features":[{"properties":{"Name":"Vijay Tr","Work_Email":"vijay.tomar#lovly.com","Job_Title":"Lead r","Reporting_Location":"Ind ","Total_Experience":9,"Mobile_Phone":"9313432451","Department":"LINT","gx_id":"","Reporting_To":"Ashish Gupta"},"type":"Feature","geometry":{"type":"Point","coordinates":[77.02190399169922,28.455472946166992]}}]}
Feature is a Valid Json.
try {
mapDataURL = new URL(url);
if (mapDataURL != null) {
urlConnection = mapDataURL.openConnection();
urlConnection.setConnectTimeout(600000);
urlConnection.setDoOutput(true);
urlConnection.setRequestProperty("Content-Type","application/json");
String gmeToken = saa.getOAuthTokenForMapsEngine();
if (gmeToken != null && gmeToken.length() > 0) {
urlConnection.setRequestProperty("Authorization", "Bearer " + gmeToken);
}
OutputStreamWriter wr = new OutputStreamWriter(urlConnection.getOutputStream());
JSONArray latLngAry = new JSONArray();
latLngAry.put(Float.parseFloat(lng));
latLngAry.put(Float.parseFloat(lat));
JSONObject geometry=new JSONObject();
geometry.put("type","Point");
geometry.put("coordinates",latLngAry);
JSONObject jsonProperties=new JSONObject();
jsonProperties.put("Name",name.trim());
jsonProperties.put("Job_Title",jobTitle.trim());
jsonProperties.put("Reporting_To",reportingTo.trim());
jsonProperties.put("Department",department.trim());
jsonProperties.put("Work_Email",email.trim());
jsonProperties.put("Mobile_Phone",mobilePhone.trim());
jsonProperties.put("Reporting_Location",reportingLocation.trim());
jsonProperties.put("Total_Experience",Float.parseFloat(experience.trim()));
jsonProperties.put("gx_id", "" + gx_id + "");
JSONObject jsonFeature=new JSONObject();
jsonFeature.put("properties", jsonProperties);
jsonFeature.put("type", "Feature");
jsonFeature.put("geometry", geometry);
String jsonStr = "{\"features\":[" + jsonFeature + "]}";
log.info("jsonStr : "+jsonStr);
wr.write(jsonStr);
log.info(" writing String Success : "+wr.toString());
wr.flush();
log.info("Url : "+mapDataURL);
// Get the response
BufferedReader rd = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
String line;
while ((line = rd.readLine()) != null) {
buffer.append(line);
}
wr.close();
rd.close();
}
} catch (MalformedURLException e) {
buffer = new StringBuffer("MalformedURLException : "+ e.getMessage() );
} catch (IOException e) {
buffer = new StringBuffer("IOException : " +e.getMessage());
} catch (Exception e) {
buffer = new StringBuffer("Generic Exception : "+e.getMessage());
} finally {
if (buffer.length() < 1) {
return true;
} else {
log.info("buffer length is greater than 1 : "+buffer.toString());
return false;
}
}
Did you intend to return true here? With buffer.length() < 1, any value that is greater than an empty buffer will cause it to return false. So, if buffer.append(line) is expected to be called, you will always return false.
I suggest changing the buffer.length() < 1 condition.