- 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 "-//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>
Note:- 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"%> <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>
Note:- 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
Home » spring » Handling Security with Ajax, DWR and Acegi
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).
{ 0 comments... Views All / Send Comment! }
Post a Comment