Archive for October, 2009

Check in Java web app if user is logged in in Rails web app

I have a Rails application where users can log in and do stuff. For one of the actions a user can perform, I actually use a Java web application integrated in the Rails application. Because I don’t want a malicious user that is not logged in to the application to surf directly to the Java application, I need a system where my Java application is only accessible for users logged in to the Rails application. I used a Servlet Filter that contacts the Rails application in the background and asks if the user is logged in. Only then is the user allowed to proceed.

First I built an a controller in Rails with an action that checks if the user is logged in. In my application this is available at the url localhost:3000/session/check.

class SessionController < ApplicationController

def check

if session[‘user’].nil?

logged_in = false

else

logged_in = true

end

render :text => logged_in.to_s #just write true or false to the output

end

end

package be.vrt.medialab.filters;

Now I want my Java web application to first request the Rails session check and when it returns false it should redirect to the login page instead of serving the Java servlets. I used a Java servlet filter for this job. I created the filter in a separate project, here is the source code:

package be.vrt.medialab.filters;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.net.MalformedURLException;

import java.util.ResourceBundle;

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletContext;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.http.Cookie;

import javax.servlet.http.HttpServletRequest;

public class RailsAuthentication implements Filter {

FilterConfig filterConfig = null;

private ResourceBundle resources;

public RailsAuthentication() {

resources = ResourceBundle.getBundle(“config”);

}

public boolean getRailsResponse(String urlString,String cookie) {

// Open a URL connection.

java.net.URL url;

try {

System.out.println(“urlString=”+urlString);

url = new java.net.URL( urlString );

final java.net.URLConnection uconn = url.openConnection( );

if ( !(uconn instanceof java.net.HttpURLConnection) )

throw new java.lang.IllegalArgumentException(

“URL protocol must be HTTP.” );

final java.net.HttpURLConnection conn =

(java.net.HttpURLConnection)uconn;

// Set up a request.

conn.setConnectTimeout( 10000 ); // 10 sec

conn.setReadTimeout( 10000 ); // 10 sec

conn.setInstanceFollowRedirects( true );

conn.setRequestProperty( “User-agent”, “spider” );

conn.setRequestProperty(“Cookie”, “_ifip_rails_session=”+cookie+“;”);

// Send the request.

conn.connect( );

BufferedReader in = new BufferedReader( new InputStreamReader((InputStream) conn.getContent( )));

String inputLine;

inputLine = in.readLine(); // Process each line.

System.out.println(“rails returned: “+inputLine);

conn.disconnect( );

if (inputLine.equals(“true”)) {

//authentication successful: user is logged in

System.out.println(“authentication successful!”);

return true;

} else {

//authentication failed: user is not logged in

System.out.println(“authentication failed!”);

return false;

}

} catch (Exception e) {

e.printStackTrace();

}

return false;

}

public void doFilter(ServletRequest req, ServletResponse response, FilterChain chain) throws IOException,ServletException {

String railsCheck =resources.getString(“RailsCheck”);

String invalidUrl=resources.getString(“InvalidUrl”);

HttpServletRequest request = (HttpServletRequest) req;

Cookie[] cookies = request.getCookies();

String rails_session_id = null;

for(int i=0;i<cookies.length;i++) {

Cookie cookie = cookies[i];

if (cookie.getName().equals(“_ifip_rails_session”)) {

rails_session_id = cookie.getValue();

}

}

if (rails_session_id == null) {

//authentication fails

System.out.println(“Autentication fails, no rails session id!”);

} else {

System.out.println(“Rails session id is “+rails_session_id);

//query rails app if this session id is from a logged in user

boolean valid_user =getRailsResponse(railsCheck,rails_session_id);

if (valid_user) {

// pass the request along the filter chain

chain.doFilter(request, response);

} else {

System.out.println(“valid_user=”+valid_user+“, redirecting to /RedirectServlet”);

ServletContext context =filterConfig.getServletContext();

context.getRequestDispatcher(“/RedirectServlet”).forward(request, response);

}

}

}

public void init(FilterConfig fConfig) throwsServletException {

// TODO Auto-generated method stub

filterConfig = fConfig;

}

}


I couldn’t find how to redirect to an external URL directly from within the servlet filter, so I just forwarded to a second servlet that has the sole job of redirecting to a certain URL (the login page):


package be.vrt.medialab;

import java.io.IOException;

import java.util.ResourceBundle;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


public class RedirectServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

private ResourceBundle resources;

public RedirectServlet() {

super();

resources = ResourceBundle.getBundle(“config”);

}

protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException {

String invalidUrl=resources.getString(“InvalidUrl”);

response.sendRedirect(invalidUrl);

}


protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException {

String invalidUrl=resources.getString(“InvalidUrl”);

response.sendRedirect(invalidUrl);

}

}

import java.io.BufferedReader;

Now the only thing we have to do is place the classes in our web application and change the web.xml as follows:

<?xml version=“1.0” encoding=“UTF-8”?>

<web-appxmlns:xsi=http://www.w3.org/2001/XMLSchema-instance&#8221;xmlns=http://java.sun.com/xml/ns/javaee&#8221;xmlns:web=http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&#8221;xsi:schemaLocation=http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&#8221;id=“WebApp_ID” version=“2.5”>

<display-name>IfipUploader</display-name>

<welcome-file-list>

<welcome-file>TestPage.html</welcome-file>

<welcome-file>FormUpload.html</welcome-file>

<welcome-file>index.jsp</welcome-file>

<welcome-file>default.html</welcome-file>

<welcome-file>default.htm</welcome-file>

<welcome-file>default.jsp</welcome-file>

</welcome-file-list>

<filter>

<filter-name>Rails Authentication</filter-name>

<filter-class>be.vrt.medialab.filters.RailsAuthentication</filter-class>

</filter>

<filter-mapping>

<filter-name>Rails Authentication</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

<servlet>

<servlet-name>RedirectServlet</servlet-name>

<display-name>RedirectServlet</display-name>

<description>redirects to InvalidUrl</description>

<servlet-class>be.vrt.medialab.RedirectServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>RedirectServlet</servlet-name>

<url-pattern>/RedirectServlet</url-pattern>

</servlet-mapping>

<servlet>

<description>Extension of abstract class UploadServlet</description>

<display-name>UploadServletWithQueue</display-name>

<servlet-name>UploadServletWithQueue</servlet-name>

<servlet-class>be.vrt.medialab.upload.UploadServletWithQueue</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>UploadServletWithQueue</servlet-name>

<url-pattern>/UploadServletWithQueue</url-pattern>

</servlet-mapping>

</web-app>

import java.io.IOException;

Below are two logs from the Java web application:

Logged out: (the Rails session id is from a previous session and thus invalid)

Rails session id is BAh7CToQX2NzcmZfdG9rZW4iMVUyeFJWWWVzc1hUZFNPRDR2dkFUb3lONVFaQlJrVmsxR1h0VzVaS3RmUFU9Og9zZXNzaW9uX2lkIiUyOTg2NDc2NzY0N2RlMGU1OWExMTFiOTUwMTk0Zjg2MCIQaW5pdGlhbF91cmkiDS9tYW1taWUvIgpmbGFzaElDOidBY3Rpb25Db250cm9sbGVyOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpAdXNlZHsA--41ae001042b16ee26966fc931d11719bc51d7b71
urlString=http://media.ibbt.be/mammie/session/check
rails returned: false
authentication failed!
valid_user=false, redirecting to /RedirectServlet

Logged in:

Rails session id is BAh7CiIJdXNlcm86CVVzZXIHOhZAYXR0cmlidXRlc19jYWNoZXsAOhBAYXR0cmlidXRlc3sdIg5qb2JfdGl0bGUiF1NpdGUgQWRtaW5pc3RyYXRvciIRb2ZmaWNlX3Bob25lMCIPdXBkYXRlZF9hdCIYMjAwOS0xMC0wOCAxMTo1OToxNiIKdGl0bGUiF3NpdGUgYWRtaW5pc3RyYXRvciIYb3JnYW5pc2F0aW9uX3JlZ2lvbjAiDXVzZXJuYW1lIgphZG1pbiIMY291bnRyeSIHQkUiGW9yZ2FuaXNhdGlvbl9hZGRyZXNzMCIHaWQiBjEiHG9yZ2FuaXNhdGlvbl9kZXBhcnRtZW50MCIWb3JnYW5pc2F0aW9uX2NpdHkwIhRhc3Npc3RhbnRfcGhvbmUwIg9maXJzdF9uYW1lIgphZG1pbiITaGFzaGVkX3Bhc3dvcmQiLWI0NzIwODY3MGU2YmU1ODdhNjE1YTcwZDMzZGRkYmVkNmNhMGNiZjAiD29mZmljZV9mYXgwIhFvcmdhbmlzYXRpb24wIg5sYXN0X25hbWUiFnRoZSBhZG1pbmlzdHJhdG9yIhBhZmZpbGlhdGlvbjAiFm9yZ2FuaXNhdGlvbl90eXBlMCIPY3JlYXRlZF9hdCIYMjAwOS0xMC0wOCAxMTo1OToxNiIKZW1haWwiHmthcmVsLmJyYWVja21hbkBnbWFpbC5jb20iEW1vYmlsZV9waG9uZTAiHW9yZ2FuaXNhdGlvbl9wb3N0YWxfY29kZTAiGW9yZ2FuaXNhdGlvbl9jb3VudHJ5MDoPc2Vzc2lvbl9pZCIlMjk4NjQ3Njc2NDdkZTBlNTlhMTExYjk1MDE5NGY4NjA6EF9jc3JmX3Rva2VuIjFVMnhSVlllc3NYVGRTT0Q0dnZBVG95TjVRWkJSa1ZrMUdYdFc1Wkt0ZlBVPSIQaW5pdGlhbF91cmkiDS9tYW1taWUvIgpmbGFzaElDOidBY3Rpb25Db250cm9sbGVyOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpAdXNlZHsA--9857ba6780010c041df44eabbfa5f3943ecbe218
urlString=http://media.ibbt.be/mammie/session/check
rails returned: true
authentication successful!

October 20, 2009 at 11:56 am 1 comment

Jeditable JQuery plugin on Rails

The Jeditable JQuery plugin is an awesome piece of javascript code that allows the users of your webpage to just click some text and edit it in place. So instead of having an “edit” page for your data, you let the user edit directly from the “show” page.

The usage of the plugin is very easy, as explained on their homepage. You just wrap the editable text in a div with class “edit” and add the folowing piece of javascript code:

$(document).ready(function() {
$(‘.edit’).editable(‘http://www.example.com/save.php&#8217;);
});
$(document).ready(function() {

     $('.edit').editable('http://www.example.com/save.php');

 });

This will make the text clickable. When the user clicks on it, the text changes to an input field with a submit button, which saves the new data to save.php.

edit_in_place

I wanted to use the Jeditable script in my Rails application, but I ran into some difficulties along the way. After some frustrating digging around I came to the following:

I added an update_field action to my controller that allows changing a single value and returns the value of that field:

  # called after editing an item
  # PUT /items/1
  # PUT /items/1.xml
  def update_field
    @item = Item.find(params[:item][:id])
    dc_ds = params[:item][:dc_ds]
    #read and write the DC datastream...
    @dc_ds = DC_datastream.new(:id => params[:item][:id])
    puts 'params update:'
    pp params

    keys = params[:dc_datastream_solr].keys
    k = keys.first
    #params[:dc_datastream_solr].each_key do |k|
      @dc_ds.send k.to_s+'=',params[:dc_datastream_solr][k]
    #end    

    @dc_ds.save_to_fedora

    render :text => params[:dc_datastream_solr][k]
  end



In the layout of the item we set the javascript AUTH_TOKEN variable so we can correctly set the authenticity token in the requests sent to Rails by JQuery:
<%= javascript_tag "var AUTH_TOKEN = #{form_authenticity_token.inspect};" if protect_against_forgery? %>



And this is the javascript that will work on e.g. <div class=”edit_area” id=”theid” name=”thename” />

//the each is needed because we need to read id and name of each item
$('.edit_area').each(function(i) {
  $(this).editable('./update_field/<%=@item.id%>', {
    type	:	'textarea',
    name	:	$(this).attr('name'),
    id		:	$(this).attr('id'),
    cancel	:	'Cancel',
    submit	:	'OK',
    indicator:	'Saving...',
    tooltip	:	'Click to edit...',
    submitdata:	{_method: "put", "item[id]": "<%=@item.id%>",authenticity_token: AUTH_TOKEN},
    rows:		10
  });
});

I iterate explicitly over all the divs on the page with class edit_area so I can set the name and id of this editable object to the name and id attribute of the respective div’s.

The submitdata line does a few things:

submitdata:	{_method: "put", "item[id]": "<%=@item.id%>",authenticity_token: AUTH_TOKEN},

_method: "put" is Rails' way of simulating an HTTP PUT verb via an HTTP POST. 

"item[id]": "<%=@item.id%>" passes the item's id back to Rails.

authenticity_token: AUTH_TOKEN includes the authenticity token in the request that is sent. 



October 13, 2009 at 7:07 pm 2 comments

Webdesign: show content on top of Flash or Silverlight component

I started playing with JQuery last week and used the Boxy plugin to display a dialog window to the user while disabling all other components. In the background it uses CSS’s z-index property to accomplish this. At least.. almost all components, because as you can see in the video below the flash movie kept appearing on top of the Boxy window. In a later test I noticed the same thing happens for Silverlight components.

problem

Here is how to fix it:

Flash

Flash has a “wmode” parameter which you have to set to “opaque” for the z-index style to have an effect. For instance for the Flash JWPlayer:

<script type='text/javascript'> 

	var s1 = new SWFObject('player.swf','IFIPPlayer','400','300','9');

	s1.addParam('allowfullscreen','true');

	s1.addParam('allowscriptaccess','always');

	s1.addParam('flashvars','type=video&file=movie.flv');

	s1.addParam('wmode','opaque');

	s1.write('theplayer');

</script> 

Silverlight

Silverlight has a “windowsless” property which you have to set to ‘true’ for the z-index style to have an effect. For instance for the Silverlight JWPlayer:

<script type=”text/javascript”>
var cnt = document.getElementById(“player_http://ifip.test.ibbt.be/fedora/get/<%=@item.id%>/MAM_lowres”);
var src = ‘<%=ActionController::Base.relative_url_root%>/wmvplayer.xaml’;
var cfg = {
height:'<%=defined?(@flashplayer_height) ? @flashplayer_height : 300%>’,
width:'<%=defined?(@flashplayer_width) ? @flashplayer_width : 400%>’,
windowless:’true’
};
var ply = new jeroenwijering.Player(cnt,src,cfg);
</script>
<script type="text/javascript"> 

	var cnt = document.getElementById("theplayer");

	var src = '/wmvplayer.xaml';

	var cfg = {

		file:'movie.wmv',

		image:'thumb.jpg',

		height:'300',

		width:'400',

		windowless:'true'

	};

	var ply = new jeroenwijering.Player(cnt,src,cfg);	

</script> 

And a screenshot to prove it 🙂

solved

October 6, 2009 at 11:18 am Leave a comment

flash 10 on Ubuntu amd_64

230  sudo apt-get remove flashplugin-nonfree flashplugin-installer
233  tar xvf libflashplayer-10.0.32.18.linux-x86_64.so.tar.gz
234  sudo mv libflashplayer.so /usr/lib/mozilla/plugins/
Flashplayer 10 is not yet supported by Adobe for amd_64 Linux architectures, but they do have an alpha relase in their labs: http://labs.adobe.com/downloads/flashplayer10.html. Here’s how to install it (Thanks to these guys, only the download url has changed. ).
sudo apt-get remove flashplugin-nonfree flashplugin-installer
wget http://download.macromedia.com/pub/labs/flashplayer10/libflashplayer-10.0.32.18.linux-x86_64.so.tar.gz
tar xvf libflashplayer-10.0.32.18.linux-x86_64.so.tar.gz 
sudo mv libflashplayer.so /usr/lib/mozilla/plugins/

October 2, 2009 at 4:59 pm Leave a comment


Feeds

Articles to be written…

Twitter – kr3l

my del.icio.us

RSS Google Reader Shared Stuff

  • An error has occurred; the feed is probably down. Try again later.

RSS Listening to..

  • An error has occurred; the feed is probably down. Try again later.