- 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
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).
Labels:
ajax,
example/sample code,
security,
spring
Subscribe to:
Post Comments (Atom)
Popular Posts
-
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...
-
Displaytag is an opensource tag library that can be used to display tables on JSPs. Apart from being able to display tables, the displaytag...
-
In a previous post, I described how to use Quartz scheduler for scheduling . In this post, I describe the configuration changes required for...
-
JUnit 4 introduces a completely different API to the older versions. JUnit 4 uses Java 5 annotations to describe tests instead of using in...
-
This post will describe how to create and deploy a Java Web Application war to Heroku using Heroku CLI. You will need a basic understanding ...
-
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...
-
This is an example code for a simple PDF merge using iText 5. We use three InputStream s in a List as input and merged file is written to th...
-
The example here demonstrates the use of an anonymous PL/SQL block to return data to a calling Java program. It also shows how to use nested...
-
New posts with iText 5.5.12 Following are two new posts for PDF Merge with iText 5.5.12 Merge PDF files using iText 5 Merge and Paginate PDF...
-
JFreeChart is a free Java chart library that can be used to display charts from Java applications. It features: A wide range of chart types ...
Have you thought about how to use DWR to cause a user to become logged in as far as ACEGI is concerned? This seems to be more complex than I first thought.
ReplyDeleteA.
Wonderful job!!!
ReplyDeleteI have few questions-
1)How to avoid a code from decompiling?
2)how to handle the exceptions, when we have onload functions in jsp?
Thanks in advance.