Secure WS client with UsernameToken(SOAP security header) - java

I'm trying to secure my WS client to be able to call the WS.
My code looks like this:
SendSmsService smsService = new SendSmsService();
SendSms sendSMS = smsService.getSendSms();
BindingProvider stub = (BindingProvider)sendSMS;
//Override endpoint with local copy of wsdl.
String URL ="";//here is the wsdl url
Map<String,Object> requestContext = stub.getRequestContext();
requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, URL);
//Set usernametoken
URL fileURL = loader.getResource("client-config.xml");
File file = new File(fileURL.getFile());
FileInputStream clientConfig = null;
try {
clientConfig = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
XWSSecurityConfiguration config = null;
try {
config = SecurityConfigurationFactory.newXWSSecurityConfiguration(clientConfig);
} catch (Exception e) {
e.printStackTrace();
log.warn("Exception: "+e.getMessage());
}
requestContext.put(XWSSecurityConfiguration.MESSAGE_SECURITY_CONFIGURATION, config);
//Invoke the web service
String requestId = null;
try {
requestId = sendSMS.sendSms(addresses, senderName, charging, message, receiptRequest);
} catch (PolicyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ServiceException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
and the config file looks like this:
<xwss:JAXRPCSecurity xmlns:xwss="http://java.sun.com/xml/ns/xwss/config" optimize="true">
<xwss:Service>
<xwss:SecurityConfiguration dumpMessages="true"
xmlns:xwss="http://java.sun.com/xml/ns/xwss/config">
<xwss:UsernameToken name="username" password="password>
</xwss:SecurityConfiguration>
</xwss:Service>
<xwss:SecurityEnvironmentHandler>
util.SecurityEnvironmentHandler
</xwss:SecurityEnvironmentHandler>
</xwss:JAXRPCSecurity>
The SecurityEnviromentHandler is a dummy class that implements javax.security.auth.callback.CallbackHandler.
Authentication must be in compliance with Oasis Web Services Security Username Token Profile 1.0.
But I'm constantly getting "Security header not valid" error.
Where am I going wrong, can anyone tell me.
I used wsimport(JAX_WS 2.1 to generate classes for my client)
Note:Only thing I know about this WS is WSDL URL and user&pass for authentication

SOLUTION
I solved the problem. The thing that was going wrong is that client-config.xml file cause I didn't know how to set it properly. I ran into this example and used it:
http://www.javadb.com/using-a-message-handler-to-alter-the-soap-header-in-a-web-service-client
Just copied those 2 classes on the link into my projects structure and called them, something like this:
SendSmsService smsService = new SendSmsService();
HeaderHandlerResolver handlerResolver = new HeaderHandlerResolver();
smsService.setHandlerResolver(handlerResolver);
SendSms sendSMS = smsService.getSendSms();
Now it works perfectly!

Related

How do I create an Alfresco site programmatically from a repository webscript?

I've implemented an Alfresco repository webscript (in Java) to programmatically create a new site.
I notice that there's a SiteService interface which I thought could be used to do this -
SiteInfo site = siteService.createSite("site-dashboard", "mySite",
"mySite", "", SiteVisibility.PUBLIC);
However, this results in the creation of a non-functional site, and although it's visible within the Alfresco Share dashboard, I'm not able to use it.
I then came across this code sample, which is doing exactly what I want. BUT the code includes a section to do authentication, involving sending the user's login and password details to a dologin web service. Don't really want to do this.
But as the user has already logged in via Alfresco Share, they should already be authenticated.
If I call the create-site webscript from my code, as shown in the example (without the initial call to dologin), I'm getting a 401 (unauthorised) return code.
So my question is, how do I tell the create-site webscript about my authentication?
I read about using an authentication ticket here. Is this ticket stored in the session, and if so, how do I access it within my Java code? If I could get the ticket, then this would be sufficient to invoke the create-site webscript.
Update: I've added the alf_ticket parameter as suggested by the comment, but I'm still getting a 401 response.
My current code is:
public NodeRef createServiceChange(String serviceChangeName) {
HttpClient client = new HttpClient();
String ticket = authService.getCurrentTicket();
PostMethod createSitePost = new PostMethod("http://localhost:8081/share/service/modules/create-site");
JSONObject siteObject = new JSONObject();
try {
siteObject.put("shortName", serviceChangeName);
siteObject.put("visiblity", "Public");
siteObject.put("sitePreset", "site-dashboard");
siteObject.put("title", serviceChangeName);
siteObject.put("description", serviceChangeName);
siteObject.put("alf_ticket", ticket);
createSitePost.setRequestHeader("Content-Type", "application/json");
createSitePost.setRequestHeader("Accept", "application/json");
createSitePost.setRequestEntity(new StringRequestEntity(siteObject.toString(), "application/json", "UTF-8"));
int status = client.executeMethod(createSitePost);
System.out.println("create a site script status :: " + status);
if (status == HttpStatus.SC_OK) {
System.out.println("Site created OK");
}
else{
System.out.println("There is error in site creation");
}
} catch (JSONException err) {
err.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (HttpException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
So I've managed to successfully create a site, programmatically, and here's what I did:
First, forget about writing a repository (platform) webscript. Creation of sites in Alfresco is done by invoking a Share module, so you'll need to implement either a page, or custom menu item to create a site. I was also getting a lot of problems with authentication, but if you log in to the system via Alfresco Share, and in your Javascript, use the provided Alfresco Ajax request, then authentication shouldn't be a problem.
Here are the components I used:-
Create a Share page to create your site. In the Freemarker template (.ftl) add a form to collect the site details.
Attach a button on the form to the following Javascript function. Note that I cobbled this together from various code fragments on the web, so it could use some cleaning up. But it basically works for me -
function create_site()
{
var sc_form = document.forms.namedItem('sc_form');
var name = sc_form.elements.namedItem('name').value;
var url = Alfresco.constants.URL_CONTEXT + "service/modules/create-site";
Alfresco.util.Ajax.request({
method : Alfresco.util.Ajax.POST,
url : url,
dataObj: {
sitePreset: "site-dashboard",
visibility: "PUBLIC",
title: name,
shortName: name,
description: name
},
requestContentType: Alfresco.util.Ajax.JSON,
successCallback:
{
fn: function(res){
alert("success");
alert(res.responseText);
},
scope: this
},
failureCallback:
{
fn: function(response)
{
Alfresco.util.PopupManager.displayPrompt(
{
title: Alfresco.util.message("message.failure", this.name),
text: "search failed"
});
},
scope: this
}
});
}

GWT Java how to convert List<File> to something the client side can use?

EDITED
This is probably a stupid question but I can't figure it out. I am using Java with GWT in Eclipse to create a RPC application to get google drive metadata. All is working (I am getting back the metadata on the server side) but I can't figure out how to pass this data over to the client side so that I can display it.
I am getting a list of metadata for google drive docs as follows:
public List<File> getFromRemoteServer()
throws HowToListingException {
List<File> lista = null;
try {
lista = retrieveAllFiles(getDriveService("email#xxxx.org"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (GeneralSecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return lista;
}
My question is, how do I change the List type to something that the client side can use? i.e what do I put here (fill in the blank)? And how would I convert lista to that type?
asyncSvc.getFromRemoteServer( {
new AsyncCallback<____________>() {
}
A bit more hopefully clarifying information:
I know to make this work I have to serialize the File object. I'm just not sure if I can or where to put this.
http://www.gwtproject.org/doc/latest/tutorial/RPC.html#serialize
In the server side implementation, I am using this File:
import com.google.api.services.drive.model.File;
Which I need to use to have this code work properly:
public static Drive getDriveService(String userEmail) throws GeneralSecurityException,
IOException, URISyntaxException {
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(Arrays.asList(DriveScopes.DRIVE))
.setServiceAccountUser(userEmail)
.setServiceAccountPrivateKeyFromP12File(
new java.io.File(SERVICE_ACCOUNT_PKCS12_FILE_PATH))
.build();
Drive service = new Drive.Builder(httpTransport, jsonFactory, null)
.setHttpRequestInitializer(credential).build();
return service;
}
private static List<File> retrieveAllFiles(Drive service) throws IOException {
List<File> result = new ArrayList<File>();
Files.List request = null;
try {
request = service.files().list();
FileList files = request.setQ("'"+"0B9lpwZZfxxxxxxxxVeEJFR3M"+"' in parents and trashed=false").execute();
result.addAll(files.getItems());
request.setPageToken(files.getNextPageToken());
}
catch (IOException e)
{
System.out.println("An error occurred: " + e);
request.setPageToken(null);
}
for(File f:result)
{
System.out.println(f.getTitle());
System.out.println(f.getOwners());
System.out.println(f.getModifiedDate());
}
return result;
}
The problem comes when I try to use
import com.google.api.services.drive.model.File;
on the client side in the synchronous and asynchronous interfaces and the client code (entry point). I get the error message about "did you forget to inherit a required module - no code found for this import." I am assuming that means I can't use this on the client side. I've tried to import java.io.File instead but then I get messages that I can't convert between the two types.
I feel like I am close, I just need a push in the right direction. Any help appreciated.
You can only pass classes that implement Serializable. I don't know what File class is, but if it's not serializable, you cannot pass it using RPC.
If File implements Serializable, you can pass ArrayList<File> to AsyncCallback. Note that with GWT it is always better to use a specific implementation (ArrayList instead of List) in order to reduce the compiled code.
Design your own class that contains the info you need to display. And maybe a unique path. Send that class, which should be Serializable to the client.

URLConnection created through OkHttp has useCache set to false

I am using the Kohsuke GitHub-API to connect to the GitHub from my Java (server-side) application and I wanted to use the OkHttp's ability to cache responses from the GitHub. This worked perfectly when I wrote a test for it, but it doesn't work in the application itself and I don't have a clue why that is. I have managed to trace the problem back to the creation of the URLConnection object that is created with its useCache variable set to false, but I cannot figure out why. Does it maybe have something to do with the server configuration or something like that?
I would appreciate any ideas or even a nudge in any direction, because frankly I don't have any ideas left... Thanks
Provider:
public class GitHubProvider implements Provider<GitHub> {
#Override
public GitHub get() {
GitHub gitHub = null;
HttpResponseCache cache = null;
OkHttpClient okHttpClient = new OkHttpClient();
File cacheDir = new File(System.getProperty("java.io.tmpdir"), UUID.randomUUID().toString());
try {
cache = new HttpResponseCache(cacheDir, 10L * 1024 * 1024);
} catch (IOException e) {
// NOTHING
}
okHttpClient.setResponseCache(cache);
try {
gitHub = GitHub.connectUsingPassword("user", "password");
} catch (Exception e) {
// NOTHING
}
gitHub.setConnector(new OkHttpConnector(okHttpClient));
return gitHub;
}
}
Test (works):
#RunWith(JukitoRunner.class)
public class SoftwareComponentServiceTest {
public static class Module extends TestModule {
#Override
protected void configureTest() {
bind(GitHub.class).toProvider(GitHubProvider.class);
}
}
#Inject
GitHub gitHub;
#Test
public void testInjectedGitHubResponseCache() {
try {
GHUser ghUser = gitHub.getUser("user");
GHRepository repository = ghUser.getRepository("repository");
int limit = gitHub.getRateLimit().remaining;
repository.getFileContent("README.md");
assertEquals(limit - 1, gitHub.getRateLimit().remaining);
repository.getFileContent("README.md");
assertEquals(limit - 1, gitHub.getRateLimit().remaining);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Service that is used in the application (doesn't work):
#Singleton
#RequiresAuthentication
public class SoftwareComponentService {
#Inject
GitHub gitHub;
public List<SoftwareComponent> findAll() {
List<SoftwareComponent> softwareComponentList = new ArrayList<SoftwareComponent>();
try {
GHUser ghUser = gitHub.getUser("user");
List<GHRepository> repositories = ghUser.listRepositories().asList();
for (int i = 0; i < repositories.size(); i++) {
GHRepository repository = repositories.get(i);
if (!repository.getName().startsWith("sc_")) {
continue;
}
softwareComponentList.add(new SoftwareComponent(repository.getName(), repository.getDescription()));
}
} catch (IOException e) {
// NOTHING
}
return softwareComponentList;
}
}
The reason
The URLConnection object is created with its useCache variable set to false because its defaultUseCaches variable is also set to false by the Tomcat server at the time of initialization. Tomcat does this through its JreMemoryLeakPreventionListener class because reading resources from JAR files using java.net.URLConnections can sometimes result in the JAR file being locked (urlCacheProtection variable). The workaround they implemented to solve this problem was to disable URLConnection caching by default (!?!?).
The solution
The workaround to this workaround is to create a dummy URLConnection and use its setDefaultUseCaches() method to change the default value of every subsequently created URLConnection (as suggested by Jesse Wilson).
URL url = new URL("jar:file://dummy.jar!/");
URLConnection uConn = url.openConnection();
uConn.setDefaultUseCaches(true);
Big thanks to Jesse Wilson for pointing me in the right direction!
There's an insane method called URLConnection.setDefaultUseCaches() that could be doing it globally. That's an instance method that works like a static method: it sets the property for everyone.

Java Google Youtube Data API:: Unauthorized

I wanted to upload a video on youtube using Java Google Data API. I got the following cod from the Google Data Api documentation to upload a video.The only thing i need to change in this code in Client ID and Porduct key. i am using followinf method to authenticate
YouTubeService service = new YouTubeService(clientID, developer_key);
Client key is my Google Email id , tried with with wasy,
only provided Username e,g. "sampleuser"
or complete Gmail id e.g. "sampleuser#gmail.com" or "smapleuser#googlemail.com"
i got developer key by logging my Google mail id as mentioned "smapleuser#googlemail.com"
but i always got following exception
com.google.gdata.util.AuthenticationException: Unauthorized
at com.google.gdata.client.http.HttpGDataRequest.handleErrorResponse(HttpGDataRequest.java:600)
at com.google.gdata.client.http.GoogleGDataRequest.handleErrorResponse(GoogleGDataRequest.java:563)
at com.google.gdata.client.http.HttpGDataRequest.checkResponse(HttpGDataRequest.java:552)
at com.google.gdata.client.http.HttpGDataRequest.execute(HttpGDataRequest.java:530)
at com.google.gdata.client.http.GoogleGDataRequest.execute(GoogleGDataRequest.java:535)
at com.google.gdata.client.media.MediaService.insert(MediaService.java:400)
at YouTube.videoUpload(YouTube.java:115)
at YouTube.main(YouTube.java:43)
here is my code for video Upload
YouTubeService service = new YouTubeService("sampleuser#gmail.com",
"fakegoogleapplicationidjsuttoshowthatimgivingidhere");
// YouTubeService service = new YouTubeService("My Application");
VideoEntry newEntry = new VideoEntry();
YouTubeMediaGroup mg = newEntry.getOrCreateMediaGroup();
mg.setTitle(new MediaTitle());
mg.getTitle().setPlainTextContent("My Test Movie");
mg.addCategory(new MediaCategory(YouTubeNamespace.CATEGORY_SCHEME, "Autos"));
mg.setKeywords(new MediaKeywords());
mg.getKeywords().addKeyword("cars");
mg.getKeywords().addKeyword("funny");
mg.setDescription(new MediaDescription());
mg.getDescription().setPlainTextContent("My description");
mg.setPrivate(false);
mg.addCategory(new MediaCategory(YouTubeNamespace.DEVELOPER_TAG_SCHEME, "mydevtag"));
mg.addCategory(new MediaCategory(YouTubeNamespace.DEVELOPER_TAG_SCHEME, "anotherdevtag"));
newEntry.setGeoCoordinates(new GeoRssWhere(37.0,-122.0));
// alternatively, one could specify just a descriptive string
// newEntry.setLocation("Mountain View, CA");
MediaFileSource ms = new MediaFileSource(new File("D:\\maths.mp4")
, "video/quicktime");
newEntry.setMediaSource(ms);
// "http://uploads.gdata.youtube.com/feeds/api/users/default/uploads";
String uploadUrl =
"http://uploads.gdata.youtube.com/feeds/api/users/default/uploads";
try {
VideoEntry createdEntry = service.insert(new URL(uploadUrl), newEntry);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ServiceException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
please help , unable to find solution. thank you so much..looking for response
Try to add
service.setUserCredentials("email_here", "password_here");

Using the content handler API (JSR 211) to open applications

I want to be able to launch native and J2ME applications through my application using the content handler API (JSR 211) on a Nokia 6212.
At the moment, I am unable to do so, as it always states that there is "No Content Handler Found" and throws a javax.microedition.content.ContentHandlerException.
At the moment, I am trying to get the phone to launch its browser and go to a certain website, just to test that I can use the framework. I have tried many different Invocation objects:
//throw exceptions
new Invocation("http://www.somesite.com/index.html",
"application/internet-shortcut");
new Invocation("http://www.google.co.uk","text/html");
// a long shot, I know
new Invocation("http://www.somesite.com/text.txt","text/plain");
// massive long shot
new Invocation("http://www.google.co.uk","application/browser");
//appears to download the link and content (and definitely does in the Nokia
// emulator) and then throws an exception
new Invocation("http://www.google.co.uk");
new Invocation("http://www.somesite.com/index.html");
Below is the code that I have been using, please bear in mind the parameters often changed to generate the different Invocation objects.
/*
* Invokes an application using the Content Handler API
*/
public void doInvoke(String url, String mime, String payload){
Registry register = Registry.getRegistry(this.getClass().getName());
Invocation invoke = new Invocation(url, mime, null, false,
ContentHandler.ACTION_OPEN);
boolean mustQuit = false;
try {
mustQuit = register.invoke(invoke);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (ContentHandlerException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if(mustQuit){
this.quit();
}
}
Try this:
Registry register = Registry.getRegistry(this.getClass().getName());
You must call Registry.getRegistry for the MIDlet inheritor. Just use your MIDlet for getting the class name.

Categories