Websphere App Server 7.0.0.43 - IBM Java 1.6, Apache Wink, Rest Client TLSv1.2 - rest

Recently upgraded websphere app server to TLSv1.2. Prior, with TLSv1, was able to interface with REST client using combination of javax.ws.rs, org.glassfish.jersey and javax.net.ssl. Wasn't able to get working once app server upgraded TLS. IBM instructed to apply Feature Pack Web 2.0 and interface with REST client using Apache Wink. Haven't been able to get this solution to work. Previously, Keystore and Truststore were set on SSLContext.
private static String getClient(String servicePath){
try {
javax.ws.rs.client.Client client = null;
org.glassfish.jersey.client.ClientConfig clientConfig = new org.glassfish.jersey.client.ClientConfig();
int readTimeOut = Integer.parseInt(commonProp.getProperty(READ_TIMEOUT));
int connTimeout = Integer.parseInt(commonProp.getProperty(CONNECTION_TIMEOUT));
clientConfig.property(ClientProperties.CONNECT_TIMEOUT, connTimeout);
clientConfig.property(ClientProperties.READ_TIMEOUT, readTimeOut);
org.glassfish.jersey.SslConfigurator sslConfig;
String trustStoreName = commonProp.getProperty(TRUSTSTORE_NAME);
File file1 = new File("\\"+PROJECT_FILE_DIR+ "/ISB"+trustStoreName.trim());
String keyStoreName = commonProp.getProperty(KEYSTORE_NAME);
File file2 = new File("\\"+PROJECT_FILE_DIR+ "/ISB"+keyStoreName.trim());
FileInputStream fis1 = new FileInputStream(file1);
FileInputStream fis2 = new FileInputStream(file2);
String trustStorePassword = commonProp.getProperty(TRUSTSTORE_PASSWORD);
String keyStorePassword = commonProp.getProperty(KETSTORE_PASSWORD);
sslConfig = org.glassfish.jersey.SslConfigurator.newInstance().trustStoreBytes(ByteStreams.toByteArray(fis1))
.trustStorePassword(trustStorePassword).keyStoreBytes(ByteStreams.toByteArray(fis2))
.keyPassword(keyStorePassword);
javax.net.ssl.SSLContext sslContext = sslConfig.createSSLContext();
client = javax.ws.rs.client.ClientBuilder.newBuilder().sslContext(sslContext).withConfig(clientConfig).build();
String url = commonProp.getProperty(ENDPOINT_URL)+servicePath;
Response response =
client.target(url)
.request(MediaType.APPLICATION_JSON)
.get();
String responseAsString = "";
if(response != null){
responseAsString = response.readEntity(String.class);
}
return responseAsString;
} catch (Throwable e) {
logger.severe(e.getMessage() + e.getLocalizedMessage());
e.printStackTrace();
throw new RuntimeException(e);
}
}
With Installed Feature Pack and use of JSSEHELPER, retrieved SSL alias
information from WAS. Seem to make client connection now, but still have
authentication issue
Blockquote
response statusCode: 200
called close()
called closeInternal(true)
WebContainer : 0, SEND TLSv1.2 ALERT: warning, description = close_notify
An attempt to authenticate with a client certificate failed. A valid client
certificate is required to make this connection.
Blockquote
Believe issue may be that previously the KEYSTORE and TRUSTSTORE information
was read from file. Whereas the JSSEHELPER is simply putting file name.
com.ibm.ssl.clientAuthenticationSupported = false
com.ibm.ssl.keyStoreClientAlias = isbgatewaytst
com.ibm.ssl.contextProvider = IBMJSSE2
com.ibm.ssl.trustStoreProvider = IBMJCE
com.ibm.ssl.protocol = TLSv1.2
com.ibm.ssl.keyStoreReadOnly = false
com.ibm.ssl.alias = ISBGatewaySSL
com.ibm.ssl.keyStoreCreateCMSStash = false
com.ibm.ssl.securityLevel = CUSTOM
com.ibm.ssl.trustStoreName = ISBGatewayTrust
com.ibm.ssl.configURLLoadedFrom = security.xml
com.ibm.ssl.trustStorePassword = ********
com.ibm.ssl.keyStoreUseForAcceleration = false
com.ibm.ssl.trustManager = PKIX
com.ibm.ssl.validationEnabled = false
com.ibm.ssl.trustStoreInitializeAtStartup = false
com.ibm.ssl.keyManager = IbmX509
com.ibm.ssl.keyStoreFileBased = true
com.ibm.ssl.keyStoreType = JKS
com.ibm.ssl.trustStoreFileBased = true
com.ibm.ssl.trustStoreCreateCMSStash = false
com.ibm.ssl.trustStoreScope = (cell):ESB_DEV
com.ibm.ssl.trustStore = E:/IBM/content/resources/dev_projectfiles_dir/ISB/isb-truststore.jks
com.ibm.ssl.keyStoreProvider = IBMJCE
com.ibm.ssl.enabledCipherSuites = SSL_ECDHE_RSA_WITH_AES_128_GCM_SHA256 SSL_ECDHE_RSA_WITH_AES_128_CBC_SHA256 SSL_ECDHE_RSA_WITH_AES_128_CBC_SHA
com.ibm.ssl.daysBeforeExpireWarning = 60
com.ibm.ssl.keyStoreServerAlias = isbgatewaytst
com.ibm.ssl.clientAuthentication = false
com.ibm.ssl.keyStore = E:/IBM/content/resources/dev_projectfiles_dir/ISB/isb-keystore-tst.jks
com.ibm.ssl.trustStoreUseForAcceleration = false
com.ibm.ssl.trustStoreReadOnly = false
com.ibm.ssl.keyStoreScope = (cell):ESB_DEV
com.ibm.ssl.tokenEnabled = false
com.ibm.ssl.keyStoreName = ISBGatewayPrivatekey
com.ibm.ssl.keyStorePassword = ********
com.ibm.ssl.keyStoreInitializeAtStartup = false
com.ibm.ssl.trustStoreType = JKS
My issue is how to put the KEYSTORE and TRUSTSTORE information on the org.apache.wink.client.ClientConfig or else where, similar to previously setting the javax.net.ssl.SSLContext? Did set the WAS SSL alias information on the ClientConfig properties, but believe that is just adding the Store's file location which isn't of use for the REST Client.
public static String getPPLUResponseString(String servicePath) {
String responseAsString = "";
com.ibm.websphere.ssl.JSSEHelper jsseHelper = com.ibm.websphere.ssl.JSSEHelper.getInstance();
try {
Properties sslProps = null;
String alias = "ISBGatewaySSL";
sslProps = jsseHelper.getProperties(alias, getConnectionInfo(), null);
org.apache.wink.client.ClientConfig clientConfig = new org.apache.wink.client.ClientConfig();
clientConfig.readTimeout(Integer.parseInt(commonProp.getProperty(READ_TIMEOUT)));
clientConfig.connectTimeout(Integer.parseInt(commonProp.getProperty(CONNECTION_TIMEOUT)));
clientConfig.setProperties(sslProps);
Enumeration keys = clientConfig.getProperties().keys();
while (keys.hasMoreElements()) {
String key = (String) keys.nextElement();
String value = (String) clientConfig.getProperties().get(key);
System.out.println(" clientConfig.getProperties(): " + key + ": " + value);
}
org.apache.wink.client.RestClient restClient = new org.apache.wink.client.RestClient(clientConfig);
String url = commonProp.getProperty(ENDPOINT_URL) + servicePath;
System.out.println(" url: " + url);
org.apache.wink.client.Resource restResource = restClient.resource(url);
System.out.println(" before client response");
org.apache.wink.client.ClientResponse clientResponse = restResource.accept(MediaType.APPLICATION_JSON_TYPE).get();
int statusCode = clientResponse.getStatusCode();
System.out.println(" response statusCode: " + statusCode);
String responseEntity = clientResponse.getEntity(String.class);
System.out.println(" responseEntity start: " + responseEntity);
System.out.println(" responseEntity end: ");
if (responseEntity != null) {
responseAsString = responseEntity;
}
} catch (com.ibm.websphere.ssl.SSLException e) {
System.out.println(" com.ibm.websphere.ssl.SSLException");
e.printStackTrace();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return responseAsString;
}

Related

HttpWebRequest 500 internal error but SOAPUI Works

I got an error "The remote server returned an error: (500) Internal Server Error." with status code "ProtocolError"
HttpWebRequest webRequest = null;
XmlDocument soapEnvelopeXml = new XmlDocument();
string requestEnvelopeString = SerializerHelper.ToRequestEnvelopeString(request);
soapEnvelopeXml.LoadXml(requestEnvelopeString);
webRequest = (HttpWebRequest)WebRequest.Create(<<endpointUrl>>);
webRequest.ContentType = "text/xml;charset=\"utf-8\"";
webRequest.Accept = "text/xml";
webRequest.Method = "POST";
webRequest.KeepAlive = true;
webRequest.ProtocolVersion = HttpVersion.Version11;
using (Stream stream = webRequest.GetRequestStream())
{
soapEnvelopeXml.Save(stream);
}
try
{
using (WebResponse webResponse = webRequest.GetResponse())
{
using (StreamReader reader = new StreamReader(webResponse.GetResponseStream()))
{
string responseEnvelopeString = reader.ReadToEnd();
}
}
}
catch (WebException ex)
{
string exMessage = ex.Message;
}
When I send the requestEnvelopeString directly through SOAPUI, it works, could anyone suggest how to troubleshoot this?
Found out that the problem is SOAP-ACTION header missing, SOAPUI will auto add to the request.
Thanks
mintssoul

VSTS Web Api gives 403 unauthoratative response

I have created a native app in Azure using App Registration and added required permissions for VSTS Agent
Now, I am able to login using oauth authentication with "ADAL" and able to get the token but when trying to access the web api request it gives Http 403 Response
Here is the code example below
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri(vstsCollectionUrl);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("X-TFS-FedAuthRedirect", "Suppress");
client.DefaultRequestHeaders.Authorization = authHeader;
HttpResponseMessage res = client.GetAsync(webapiURL).Result;
}
Please let me know what i am missing
thanks in advance
Seems it's an authentication issue, Just check the value of authHeader.
You can reference below samples for the authentication with header:
Sample 1- auth-samples here ;
Sample 2 - REST API
Post the auth sample as reference here:
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
namespace DeviceProfileSample
{
public class Program
{
//============= Config [Edit these with your settings] =====================
internal const string vstsCollectionUrl = "https://myaccount.visualstudio.com"; //change to the URL of your VSTS account; NOTE: This must use HTTPS
internal const string clientId = "872cd9fa-d31f-45e0-9eab-6e460a02d1f1"; //update this with your Application ID from step 2.6 (do not change this if you have an MSA backed account)
//==========================================================================
internal const string VSTSResourceId = "499b84ac-1321-427f-aa17-267ca6975798"; //Static value to target VSTS. Do not change
public static void Main(string[] args)
{
AuthenticationContext ctx = GetAuthenticationContext(null);
AuthenticationResult result = null;
try
{
DeviceCodeResult codeResult = ctx.AcquireDeviceCodeAsync(VSTSResourceId, clientId).Result;
Console.WriteLine("You need to sign in.");
Console.WriteLine("Message: " + codeResult.Message + "\n");
result = ctx.AcquireTokenByDeviceCodeAsync(codeResult).Result;
var bearerAuthHeader = new AuthenticationHeaderValue("Bearer", result.AccessToken);
ListProjects(bearerAuthHeader);
}
catch (Exception ex)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Something went wrong.");
Console.WriteLine("Message: " + ex.Message + "\n");
}
}
private static AuthenticationContext GetAuthenticationContext(string tenant)
{
AuthenticationContext ctx = null;
if (tenant != null)
ctx = new AuthenticationContext("https://login.microsoftonline.com/" + tenant);
else
{
ctx = new AuthenticationContext("https://login.windows.net/common");
if (ctx.TokenCache.Count > 0)
{
string homeTenant = ctx.TokenCache.ReadItems().First().TenantId;
ctx = new AuthenticationContext("https://login.microsoftonline.com/" + homeTenant);
}
}
return ctx;
}
private static void ListProjects(AuthenticationHeaderValue authHeader)
{
// use the httpclient
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(vstsCollectionUrl);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("User-Agent", "VstsRestApiSamples");
client.DefaultRequestHeaders.Add("X-TFS-FedAuthRedirect", "Suppress");
client.DefaultRequestHeaders.Authorization = authHeader;
// connect to the REST endpoint
HttpResponseMessage response = client.GetAsync("_apis/projects?stateFilter=All&api-version=2.2").Result;
// check to see if we have a succesfull respond
if (response.IsSuccessStatusCode)
{
Console.WriteLine("\tSuccesful REST call");
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
}
else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
{
throw new UnauthorizedAccessException();
}
else
{
Console.WriteLine("{0}:{1}", response.StatusCode, response.ReasonPhrase);
}
}
}
}
}
Aren't you missing what authentication,
string credentials = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "", token)));
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri(vstsCollectionUrl);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new
System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials)
HttpResponseMessage response = client.GetAsync(uri).Result;
response.EnsureSuccessStatusCode();
var responseStream = await response.Content.ReadAsStreamAsync();
}
I hope this helps.

How to intergrate cas restful in Web application?

I'm using CAS build SSO, I want to implement login/logout by using CAS RESTful API in my own Web Application.
and the api like this http://sso.cvs.cn:9990/cas-server-webapp/v1/tickets
i test it by test case, and it succesful. here is the code:
public static void main(String... args) throws Exception {
String username = "123";
String password = "123";
validateFromCAS(username, password);
}
public static boolean validateFromCAS(String username, String password) throws Exception {
String url = "http://sso.cvs.cn:9990/cas-server-webapp/v1/tickets";
try {
HttpURLConnection hsu = (HttpURLConnection) openConn(url);
String s = URLEncoder.encode("username", "UTF-8") + "=" + URLEncoder.encode(username, "UTF-8");
s += "&" + URLEncoder.encode("password", "UTF-8") + "=" + URLEncoder.encode(password, "UTF-8");
System.out.println(s);
OutputStreamWriter out = new OutputStreamWriter(hsu.getOutputStream());
BufferedWriter bwr = new BufferedWriter(out);
bwr.write(s);
bwr.flush();
bwr.close();
out.close();
String tgt = hsu.getHeaderField("location");
System.out.println(hsu.getResponseCode());
if (tgt != null && hsu.getResponseCode() == 201) {
System.out.println(tgt);
System.out.println("Tgt is : " + tgt.substring(tgt.lastIndexOf("/") + 1));
tgt = tgt.substring(tgt.lastIndexOf("/") + 1);
bwr.close();
closeConn(hsu);
String serviceURL = "http://sso.cvs.cn:7070/cas-simple-site-alpha/";
String encodedServiceURL = URLEncoder.encode("service", "utf-8") + "=" + URLEncoder.encode(serviceURL, "utf-8");
System.out.println("Service url is : " + encodedServiceURL);
String myURL = url + "/" + tgt;
System.out.println(myURL);
hsu = (HttpURLConnection) openConn(myURL);
out = new OutputStreamWriter(hsu.getOutputStream());
bwr = new BufferedWriter(out);
bwr.write(encodedServiceURL);
bwr.flush();
bwr.close();
out.close();
System.out.println("Response code is: " + hsu.getResponseCode());
BufferedReader isr = new BufferedReader(new InputStreamReader(hsu.getInputStream()));
String line;
System.out.println(hsu.getResponseCode());
while ((line = isr.readLine()) != null) {
System.out.println(line);
}
isr.close();
hsu.disconnect();
return true;
} else {
return false;
}
} catch (MalformedURLException mue) {
mue.printStackTrace();
throw mue;
} catch (IOException ioe) {
ioe.printStackTrace();
throw ioe;
}
}
but how i can use the api in my web application?
If i understand correctly your question is how the api would be usefull for you in general.
So if this is the case, with restful api enabled on cas, when a user gets authenticated by CAS server, he would be allowed to access other applications (cas enabled services) which are configured to have SSO with the same CAS server. Also you can do requests for tickets with POST as the documentation suggests.
Also another reason is that applications need to programmatically access CAS. Say one casified application can invoke other casified application’s REST APIs on behalf of an authenticated user. For this purpose CAS Rest protocol will do the job

cannot instantiate the type httpclient in android

Am getting an error with the following line of code
HttpClient Client= new HttpClient.
I have tried rewriting it as HttpClient Client= new DefaultHttpClient. but it solves the problem and creates a new error with other methods
.
Here is a glimpse of my code
protected static MDSResult doExecute(Context ctx, HttpMethod method){
HttpClient client = new HttpClient();
SharedPreferences preferences =
PreferenceManager.getDefaultSharedPreferences(ctx);
MDSResult response = null;
// If there's a proxy enabled, use it.
String proxyHost = preferences.getString(
Constants.PREFERENCE_PROXY_HOST, "");
String sProxyPort = preferences.getString(
Constants.PREFERENCE_PROXY_PORT, "0");
boolean useSecure = preferences.getBoolean(
Constants.PREFERENCE_SECURE_TRANSMISSION, false);
int proxyPort = 0;
try {
if (!"".equals(sProxyPort))
proxyPort = Integer.parseInt(sProxyPort);
} catch(NumberFormatException e) {
Log.w(TAG, "Invalid proxy port: " + sProxyPort);
}
if (!"".equals(proxyHost) && proxyPort != 0) {
Log.i(TAG, "Setting proxy to " + proxyHost + ":" + proxyPort);
HostConfiguration hc = new HostConfiguration();
hc.setProxy(proxyHost, (int)proxyPort);
client.setHostConfiguration(hc);
}
// execute the Http/https method
try {
if(useSecure){
ProtocolSocketFactory ssl = new SimpleSSLProtocolSocketFactory();
Protocol https = new Protocol("https", ssl, 443);
Protocol.registerProtocol("https", https);
}
int status = client.executeMethod(method);
Log.d(TAG, "postResponses got response code " + status);
char buf[] = new char[20560];
Reader reader = new InputStreamReader(
method.getResponseBodyAsStream());
int total = reader.read(buf, 0, 20560);
String responseString = new String(buf);
Log.d(TAG, "Received from MDS:" + responseString.length()+" chars");
Gson gson = new Gson();
response = gson.fromJson(responseString, MDSResult.class);
}
You want DefaultHttpClient, not HttpClient like you mentioned. HttpClient is abstract so cannot be instantiated.
HttpClient client = new DefaultHttpClient();
What is the error with the other methods when you use that ?
Also why not use HttpURLConnection ? I find it much more reliable.

Using .NET to get results from an API

I wanted to use the Rapidshare API in my .NET app, but I am confused on how you send the request and bring back the result. Do you use Winsock or another method?
URLs are like this:
http://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=checkfiles_v1&files=288725357&filenames=my_upload.txt
Thanks.
Check out the System.Net namespace, specifically System.Net.WebClient.
http://msdn.microsoft.com/en-us/library/system.net.webclient(VS.80).aspx
Use the WebClient Class.
http://msdn.microsoft.com/en-us/library/system.net.webclient%28VS.80%29.aspx
You can use this class to programatically interact with webpage. Here's some example code to log into a website. You can adapt this to interact with their web API:
HttpWebRequest request;
HttpWebResponse response;
CookieContainer cookies;
string url = "http://www.jaxtr.com/user/login.jsp";
try
{
request = (HttpWebRequest)WebRequest.Create(url);
request.AllowAutoRedirect = true;
request.CookieContainer = new CookieContainer();
response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
StringBuilder sb = new StringBuilder();
StreamReader reader = new StreamReader(response.GetResponseStream());
while (!reader.EndOfStream)
{
sb.AppendLine(reader.ReadLine());
}
//Get the hidden value out of the form.
String fp = Regex.Match(sb.ToString(), "\"__fp\"\\svalue=\"(([A-Za-z0-9+/=]){4}){1,19}\"", RegexOptions.None).Value;
fp = fp.Substring(14);
fp = fp.Replace("\"", String.Empty);
cookies = request.CookieContainer;
//response.Close();
String requestString = "http://www.jaxtr.com/user/Login.action?tzOffset=6&navigateURL=&refPage=&jaxtrId=" + HttpUtility.UrlEncode(credentials.Username) + "&password=" + HttpUtility.UrlEncode(credentials.Password) + "&Login=Login&_sourcePage=%2Flogin.jsp&__fp="+HttpUtility.UrlEncode(fp);
request = (HttpWebRequest)WebRequest.Create(requestString);
request.CookieContainer = cookies; //added by myself
response = (HttpWebResponse)request.GetResponse();
Console.WriteLine("Response from login:" + response.StatusCode);
String messageText = (message.TruncateMessage && message.MessageText.Length > JaxtrSmsMessage.MAX_MESSAGE_LENGTH ? message.MessageText.Substring(JaxtrSmsMessage.MAX_MESSAGE_LENGTH) : message.MessageText);
String messageURL = "http://www.jaxtr.com/user/sendsms?CountryName=" + HttpUtility.UrlEncode(message.CountryName) + "&phone=" + HttpUtility.UrlEncode(message.DestinationPhoneNumber) + "&message=" + HttpUtility.UrlEncode(messageText) + "&bySMS=" + HttpUtility.UrlEncode(message.BySMS.ToString().ToLower());
request = (HttpWebRequest)WebRequest.Create(messageURL);
request.CookieContainer = cookies;
response = (HttpWebResponse)request.GetResponse();
Console.WriteLine("Response from send SMS command=" + response.StatusCode);
StringBuilder output = new StringBuilder();
using (Stream s = response.GetResponseStream())
{
StreamReader sr = new StreamReader(s);
while (!sr.EndOfStream)
{
output.AppendLine(sr.ReadLine());
}
}
response.Close();
}
else
{
Console.WriteLine("Client was unable to connect!");
}
}
catch (System.Exception e)
{
throw new SMSDeliveryException("Unable to deliver SMS message because "+e.Message, e);
}
This particular code logs into Jaxtr, a SMS messaging service, and sends an SMS message.