Google is going to offer Sun's Star Office for free as a part of Google Pack. Also, Sun will now be traded under the Symbol JAVA replacing the old symbol SUNW.
Thursday, August 23, 2007
Monday, August 20, 2007
Handling Security with Ajax, DWR and Acegi
This is an extension of a previous post that described how to secure your method calls using Acegi security. Here, I will go through how to secure your Asynchronous calls, using the same example with some modifications to include Ajax calls using Direct Web Remoting (DWR).
- Create the example project as shown in "Spring security with Acegi Security Framework". This will be the starting point.
- Create the SecureDAO object.
package test;
public class SecureDAO {
public String create() {
System.out.println("Create");
return "create";
}
public String read() {
System.out.println("read");
return "read";
}
public String update() {
System.out.println("update");
return "update";
}
} - Update the applicationContext.xml file to include the security definitions by adding the following bean definitions as shown below
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
</value>
</property>
</bean>
<bean id="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"/>
<bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
<constructor-arg value="/index.jsp"/>
<constructor-arg>
<list>
<ref bean="rememberMeServices"/>
<bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
</list>
</constructor-arg>
</bean>
<bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationFailureUrl" value="/login.jsp?errorId=1"/>
<property name="defaultTargetUrl" value="/"/>
<property name="filterProcessesUrl" value="/j_acegi_security_check"/>
<property name="rememberMeServices" ref="rememberMeServices"/>
</bean>
<bean id="securityContextHolderAwareRequestFilter" class="org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter"/>
<bean id="rememberMeProcessingFilter" class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="rememberMeServices" ref="rememberMeServices"/>
</bean>
<bean id="anonymousProcessingFilter" class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter">
<property name="key" value="changeThis"/>
<property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
</bean>
<bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
<property name="authenticationEntryPoint">
<bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl" value="/login.jsp"/>
<property name="forceHttps" value="false"/>
</bean>
</property>
<property name="accessDeniedHandler">
<bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
<property name="errorPage" value="/denied.jsp"/>
</bean>
</property>
</bean>
<bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager">
<bean class="org.acegisecurity.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions" value="false"/>
<property name="decisionVoters">
<list>
<bean class="org.acegisecurity.vote.RoleVoter"/>
<bean class="org.acegisecurity.vote.AuthenticatedVoter"/>
</list>
</property>
</bean>
</property>
<property name="objectDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/secure/admin/**=ROLE_ADMIN
/secure/**=IS_AUTHENTICATED_REMEMBERED
/**=IS_AUTHENTICATED_ANONYMOUSLY
</value>
</property>
</bean>
<bean id="rememberMeServices" class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
<property name="userDetailsService" ref="userDetailsService"/>
<property name="tokenValiditySeconds" value="1800"></property>
<property name="key" value="changeThis"/>
</bean>
<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
<list>
<ref local="daoAuthenticationProvider"/>
<bean class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
<property name="key" value="changeThis"/>
</bean>
<bean class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
<property name="key" value="changeThis"/>
</bean>
</list>
</property>
</bean>
<bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="userDetailsService"/>
<property name="userCache">
<bean class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache">
<property name="cache">
<bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager">
<bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>
</property>
<property name="cacheName" value="userCache"/>
</bean>
</property>
</bean>
</property>
</bean>
<bean id="userDetailsService" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">
<property name="userProperties">
<bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="/WEB-INF/users.properties"/>
</bean>
</property>
</bean>
<bean id="loggerListener" class="org.acegisecurity.event.authentication.LoggerListener"/>
<bean id="methodSecurityInterceptor" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
<property name="authenticationManager">
<ref bean="authenticationManager" />
</property>
<property name="accessDecisionManager">
<bean class="org.acegisecurity.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions" value="false" />
<property name="decisionVoters">
<list>
<bean class="org.acegisecurity.vote.RoleVoter" />
<bean class="org.acegisecurity.vote.AuthenticatedVoter" />
</list>
</property>
</bean>
</property>
<property name="objectDefinitionSource">
<value>
test.SecureDAO.*=IS_AUTHENTICATED_REMEMBERED
test.SecureDAO.u=ROLE_ADMIN
</value>
</property>
</bean>
<bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="interceptorNames">
<list>
<value>methodSecurityInterceptor</value>
</list>
</property>
<property name="beanNames">
<list>
<value>secureDAO</value>
</list>
</property>
</bean>
<bean id="secureDAO" class="test.SecureDAO" />
</beans> - Update the Web deployment descriptor to forward DWR requests to the DWR Servlet
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>DWRSpring</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<display-name>SpringListener</display-name>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>Acegi Filter Chain Proxy</filter-name>
<filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
<init-param>
<param-name>targetClass</param-name>
<param-value>org.acegisecurity.util.FilterChainProxy</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Acegi Filter Chain Proxy</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app> - In the DWR configuration file, set the creator to Spring
<!DOCTYPE dwr PUBLIC
Note:
"-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN"
"http://www.getahead.ltd.uk/dwr/dwr10.dtd">
<dwr>
<allow>
<convert match="java.lang.Exception" converter="exception"/>
<create creator="spring" javascript="secureDAO">
<param name="beanName" value="secureDAO"/>
</create>
</allow>
</dwr>- The converter is used to convert the Java exception to Javascript exception.
- The main change will be made to the secure/authenticatedusers.jsp file. This will use DWR to make Ajax requests. Here is the code for the file
<%@ page import="org.acegisecurity.context.SecurityContextHolder"%>
Note:
<html>
<head>
<script type='text/javascript' src='/DWRSpring/dwr/interface/secureDAO.js'></script>
<script type="text/javascript" src="../dwr/engine.js"> </script>
<script type="text/javascript" src="../dwr/util.js"> </script>
<script>
dwr.engine.setErrorHandler(errorHandlerFn);
function update() {
var name = dwr.util.getValue("method");
switch(name) {
case "create":
secureDAO.create(callBackFn)
break;
case "read":
secureDAO.read(callBackFn);
break;
case "update":
secureDAO.update(callBackFn);
break;
}
}
function callBackFn(str) {
dwr.util.setValue("selectedAction","Server Returned : " + str);
}
function errorHandlerFn(message, exception) {
dwr.util.setValue("selectedAction", "Error : " + message);
}
</script>
</head>
<body>
<h1>Welcome: <%=SecurityContextHolder.getContext().getAuthentication().getName()%></h1>
<p><a href="../">Home</a>
<form name="testForm" action=""><select name="method" onchange="update()">
<option value=""></option>
<option value="create">create</option>
<option value="read">read</option>
<option value="update">update</option>
</select></form>
<div id="selectedAction"></div>
<p><a href="../j_acegi_logout">Logout</a></p>
</body>
</html>- The classes that are exposed through DWR will be available through the /WEB_APP_NAME/dwr/interface/JAVASCRIPT_NAME.js files.
<script type='text/javascript' src='/DWRSpring/dwr/interface/secureDAO.js'></script>
- The setErrorhandler call sets the global error handling function.
dwr.engine.setErrorHandler(errorHandlerFn);
Alternatively, the error handling function can be set for individual method calls (as described in DWR documentationaRemote.method(params, {
callback:function(data) { ... },
errorHandler:function(errorString, exception) { ... }
}); - util.js file contains utility functions for getting and setting values for the document elements.
- The classes that are exposed through DWR will be available through the /WEB_APP_NAME/dwr/interface/JAVASCRIPT_NAME.js files.
- Make sure you have the following Jar files in your classpath:
- acegi-security-1.0.3.jar
- ant-junit.jar
- cglib-nodep-2.1_3.jar
- commons-codec-1.3.jar
- commons-logging.jar
- dwr.jar
- ehcache-1.2.3.jar
- jstl.jar
- spring.jar
- standard.jar
Subscribe to:
Posts (Atom)
Popular Posts
-
In a previous post, I described how to use Quartz scheduler for scheduling . In this post, I describe the configuration changes required for...
-
In this post we will see how to do an offline install Jenkins and required plugins on a Red Hat Enterprise Linux Server release 7.3. This is...
-
WebLogic Server does not support or certify any particular LDAP servers. Any LDAP v2 or v3 compliant LDAP server should work with WebLogic ...
-
Roller is a Java based blog server. It is in Apache incubator as of now. Roller drives Sun Microsystem's blogs.sun.com employee bloggi...
-
In the previous post, I described the use of Displaytag to implement paging in a simple JSP. In this example, I describe the use of Displayt...
-
In the past, I wrote a post on how to implement Web Services using JAX-WS on Glassfish, and Apache Axis. In this post I will describe how to...
-
Last week, I described how to implement JMS, using a stand-alone client and a Message Driven Bean . In this post and the next, I will descr...
-
Displaytag is an opensource tag library that can be used to display tables on JSPs. Apart from being able to display tables, the displaytag...
-
A good article that describes websphere classloading policies ... PARENT_FIRST, PARENT_LAST etc... J2EE Class Loading Demystified A Look At ...
-
In a Spring application, when a singleton bean uses another singleton bean, or a non-singleton bean uses another non-singleton bean, setting...