Monday, July 18, 2011
Resize EBS Volumes , Here is A Link
Sunday, June 19, 2011
Developing and Testing in Android Against Local Web Services
http://denimgroup.posterous.com/android-dns-setup-for-developing-and-testing
Thursday, November 18, 2010
Recommend using Fluent Nhibernate
It is definitely helpful in preventing configuration typos.
There other contrib projects for Nhibernate that I have found extremely useful
including Nhibernate Validator and NHibernate Spatial.
Nhibernate is independent from Hibernate and it doesn't benefit from a large corporate backer. Due to this Nhibernate and contrib projects are spread across multiple websites.
Main Site:
Fluent Nhibernate:
Friday, January 22, 2010
Unit Testing Restful Web Services using Restlet and Jaxb
Here is link to javadoc that discuss this: http://java.sun.com/javase/6/docs/api/javax/xml/bind/JAXBContext.html
@XmlRootElement
public class Sample {
@XmlElement(name = "value")
private String val;
public Sample() {
}
public Sample(String val) {
this.val = val;
}
public String getVal() {
return val;
}
public void setVal(String val) {
this.val = val;
}
@Override
public String toString() {
return "Sample [val=" + val + "]";
}
}
{
JAXBContext context1 = JAXBContext.newInstance(Sample.class);
JAXBContext context2 = JAXBContext.newInstance("com.acme.businessobjects");
Marshaller m = context1.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
Sample sample = new Sample();
sample.setVal("Hello");
final File f = new File("src/test/java/com/endurotracker/gwt/test/rest/api/sample.xml");
m.marshal(sample, new FileOutputStream(f));
Unmarshaller um = context2.createUnmarshaller();
um.setSchema(getSchema("Sample.xsd"));
Object bce = um.unmarshal(f);
m.marshal(bce, System.out);
}
Friday, January 1, 2010
Restful Web Services using Asp.net MVC
Microsoft's new Asp.net MVC framework can also easily support Restful Web Services.
Controller actions can be called from Ajax based based websites using Javascript.
For example if you create a controller named APIController with a method:GetUsers,
then a Restful url would be /API/GetUsers. To implement your Restful Web Services using Asp.net MVC, take a look at these excellent write ups,
create-rest-api-using-asp-net-mvc-that-speaks-both-json-and-plain-xml, and
Creating-a-RESTful-Web-Service-Using-ASPNet-MVC-Part-1-Introduction
Thursday, December 31, 2009
Restful Web Services using Restlet Framework
However, Microsoft has worked with the team behind Restlet and has enabled interoperability between Azure ADO.net and Restlet.
microsoft-selects-restlet-to-show-rest-interoperabilityOther big companies like Google also use the Restlet framework for writing Web Services in a Restful way. I always lean towards projects that are well documented and the Restlet framework has some good documentation including examples, tutorials, and api documents. In addition, if you want to integrate a Spring Web project with Restlet, here is a good write up,
restlet-with-springIf your website leverages ajax via javascript, one of the nice things with Restlets is that you can easily call your Restful Web Services using javascript.
Restlets has implemented lots of extensions, for example if you want to write a smartphone app in android to call Restful Web Services, Restlets has an extension for this.
Restlet is extremely flexible and can be called from either a Web client or Web server code.
Thursday, December 17, 2009
Spring MVC with SiteMesh Decoration Framework and Velocity Templates
Most developers hate to repeat themselves, so they like to reuse as much code as possible. The folks at OpenSymphony.org who also brought you Quartz developed Sitemesh to utilize the Gang of Four pattern composition.
In short, SiteMesh is a web-page layout and decoration framework. It allows you to
reuse your layouts (header and footer for example) throughout your site, so that
you site has a consistent look and feel.
The general documentation at the SiteMesh Site site is quite good but I needed to utilize Sitemesh in the following specific scenario, I am using Spring MVC and Velocity Templates.
Since the general install documentation, installation instructions is very good, I will not repeat it here. Once you have downloaded and setup your web project, you will have 3 xml config that you will be dealing with, web.xml, sitemesh.xml, and decorators.xml. In my case I am using Spring MVC and Velocity, so I need to customize my web.xml configuration to handle this setup. Here is how my web.xml is configured:
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>EnduroTracker</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--SiteMesh-->
<filter>
<filter-name>sitemesh</filter-name>
<filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sitemesh</filter-name>
<url-pattern>*.html</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<!--Used to Enable Spring MVC -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<!--Sitemesh-->
<servlet>
<servlet-name>sitemesh-velocity</servlet-name>
<servlet-class>com.opensymphony.module.sitemesh.velocity.VelocityDecoratorServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>sitemesh-velocity</servlet-name>
<url-pattern>*.vm</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>homeIndex.html</welcome-file>
</welcome-file-list>
<error-page>
<error-code>500</error-code>
<location>/error.html</location>
</error-page>
</web-app>
If you followed the SiteMesh Install steps at their site and then customized your
web.xml for your Spring MVC web project, you should now have SiteMesh configured correctly to use with Spring MVC and Velocity.
Important to note in your decorators.xml since you are using Velocity,
you will be using *.vm decorator files, here is an example decorators.xml file:
<decorators defaultdir="/decorators">
<!-- Any urls that are excluded will never be decorated by Sitemesh -->
<!--<excludes>
<pattern>/exclude.vm</pattern>
<pattern>/exclude/*</pattern>
</excludes>-->
<decorator name="default" page="default.vm">
<pattern>/*</pattern>
</decorator>
</decorators>
Tuesday, November 24, 2009
Using CAS 4 within a Load Balanced Environment
I'm not crazy about acronyms because given the variety of words in the english language they can mean any combination of things.
I have 2 main requirements/constraints when running my website:
1) Always be load balanced for High Availability,redundancy and also allow easy scalability.
2) Allow use Hibernate across multiple databases. I have a separate database for users (user db), and a separate database for the core of the web application.
My website is load balanced using Apache, I have a single load balance server , and 2 web servers also running Apache.
They get load balanced via Apache ProxyReverse or mod_proxy module.
I added a third requirement to my web application, always allow the users to sign in once and sign in with one set of credentials (username/password).
Another words, don't have separate sign up, sign in processes for third party applications like forums that you have tacked onto to your site.
This third requirement is straight forward and may appear easy to some, but it can be complicated and time consuming to implement.
Luckily, the folks at jasig.org , created CAS , Central Authentication Service, which can be implemented into one's website.
It is Java based, but can be integrated with lots of different website technology stacks like .Net, PHP, Perl, ColdFusion, Ruby on Rails, etc.
Combining these 3 requirements means that I need to be able to have CAS load balanced across multiple servers and multiple databases.
The standard implementation of CAS stores a user's credentials in the session. However, when CAS is implemented this way, the web site
ends up losing the credentials on redirects, etc.
To solve this issue CAS 4 (Cas version 4) introduced the concept of Database Session Storage named JpaSessionStorage in CAS.
Due to requirement #2, I had to implement my own Session Storage class that utilizes Spring's JtaTransactionManager rather EntityManager.
This allows for managing transactions over multiple databases.
Here is my code:
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.javalid.annotations.validation.CollectionSize;
import org.javalid.annotations.validation.NotNull;
import org.javalid.annotations.validation.MinValue;
import org.jasig.cas.server.authentication.Authentication;
import org.jasig.cas.server.login.LoginRequest;
import org.jasig.cas.server.util.Cleanable;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import javax.annotation.Resource;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
/***
* Session Storage Implementation that uses Spring's a JtaTransactionManager rather
* than EntityManager. Allows for managing transactions over multiple databases which
* is required in some web application implementations.
* @author David Driscoll
*
*/
@TransactionConfiguration(transactionManager="jtaTransactionManager", defaultRollback=false)
@Transactional
@Repository
/*public class JpaSessionStorageUsingJtaImpl extends AbstractSessionStorageImpl implements Cleanable{*/
public class JpaSessionStorageUsingJtaImpl implements SessionStorage, Cleanable{
@Resource(name="sessionFactory3")
private org.hibernate.SessionFactory sessionFactory;
@NotNull
@CollectionSize(mode=CollectionSize.MODE_MINIMUM, minimumSize = 1)
@Autowired(required=false)
private List
/*@Override
@Autowired
protected void setSessionFactories(List
{
this.sessionFactories = sessionFactories;
}*/
@MinValue(1)
private long purgeTimeOut = 21600000;
@MinValue(1)
private int purgeMaxCount = Integer.MAX_VALUE;
public JpaSessionStorageUsingJtaImpl(){}
@Autowired(required=true)
public JpaSessionStorageUsingJtaImpl(List
this.sessionFactories = sessionFactories;
}
public org.jasig.cas.server.session.Session createSession(
LoginRequest loginRequest, Authentication authentication)
throws InvalidatedSessionException {
try{
if (loginRequest.getOriginalAccess() != null && loginRequest.getOriginalAccess().getParentSession() != null) {
org.jasig.cas.server.session.Session parentSession = loginRequest.getOriginalAccess().getParentSession();
org.jasig.cas.server.session.Session childSession = parentSession.createDelegatedSession(authentication);
addSession(childSession);
return childSession;
}
if(this.sessionFactories != null){
for ( org.jasig.cas.server.session.SessionFactory sessionFactory : this.sessionFactories) {
org.jasig.cas.server.session.Session session = sessionFactory.getSession(authentication);
if (session != null) {
addSession(session);
return session;
}
}
}
throw new IllegalStateException("No SessionFactory configured that can handle this type of Authentication.");
}
catch(Exception ex){
System.out.println("exception in createSession, exception message:" + ex.getMessage());
throw new IllegalStateException("No SessionFactory configured that can handle this type of Authentication.");
}
}
protected void addSession(org.jasig.cas.server.session.Session session) {
Assert.isInstanceOf(JpaSessionImpl.class, session);
this.sessionFactory.getCurrentSession().persist(session);
}
public org.jasig.cas.server.session.Session destroySession(String sessionId) {
try {
Query query = this.sessionFactory.getCurrentSession().createQuery("select s from session s where s.sessionId = :sessionId").setParameter("sessionId", sessionId);
org.jasig.cas.server.session.Session session = (org.jasig.cas.server.session.Session) query.uniqueResult();
this.sessionFactory.getCurrentSession().delete(session);
return session;
} catch (Exception e) {
return null;
}
}
public org.jasig.cas.server.session.Session findSessionBySessionId(String sessionId) {
try {
Query query = this.sessionFactory.getCurrentSession().createQuery("select s from session s where s.sessionId = :sessionId").setParameter("sessionId", sessionId);
org.jasig.cas.server.session.Session session = (org.jasig.cas.server.session.Session) query.uniqueResult();
return session;
} catch ( Exception e) {
return null;
}
}
public org.jasig.cas.server.session.Session updateSession(org.jasig.cas.server.session.Session session) {
this.sessionFactory.getCurrentSession().update(session);
return session;
}
public org.jasig.cas.server.session.Session findSessionByAccessId(String accessId) {
try {
Query query = this.sessionFactory.getCurrentSession().
createQuery("select s from session s, IN(s.casProtocolAccesses) c where c.id = :accessId").setParameter("accessId", accessId);
org.jasig.cas.server.session.Session session = (org.jasig.cas.server.session.Session) query.uniqueResult();
return session;
} catch ( Exception e) {
return null;
}
}
public void purge() {
Query query = this.sessionFactory.getCurrentSession().
createQuery("delete from session s");
query.executeUpdate();
}
public void prune() {
Query query = this.sessionFactory.getCurrentSession().
createQuery("Delete From session s where (s.state.creationTime + :timeOut) >= :currentTime or s.state.count > :maxCount").
setParameter("timeOut", this.purgeTimeOut).setParameter("currentTime", System.currentTimeMillis()).setParameter("maxCount", this.purgeMaxCount);
query.executeUpdate();
}
public void setPurgeTimeOut(long purgeTimeOut) {
this.purgeTimeOut = purgeTimeOut;
}
public void setPurgeMaxCount(int purgeMaxCount) {
this.purgeMaxCount = purgeMaxCount;
}
See my series of blog posts on setting up Spring with Multiple Databases to setup JTA appropriately, here : http://endurotracker.blogspot.com/2009/08/using-spring-with-multiple-databases.html
CAS 4 uses utilizes autowiring annotations, so you only need to reference this new class in your pom.xml for it to be found and used as the session storage mechanism.
Here is a xml snippet from the pom.xml file:
<groupId>org.jasig.cas</groupId>
<artifactId>cas-server-sessionstorage-jpa</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
<type>jar</type>
</dependency>
Single Sign On with CAS Part 2 Integrating with Roller
In part 2, we will go over how to integrate CAS 4 Single Sign On with Roller ( a open source blog engine , see roller.apache.com ).
In this usage scenario we authenticate the user using CAS4 which in this case stores Username/password information in a separate User db from Roller's db.
So we will not be authenticating using Roller's db, however we will use Roller's db to determine what the users role / access rights are within the Roller application. (i.e Are they an editor, administrator, or do they not have a role yet).
Since Roller has implemented SSO for LDAP environment, we can utilize this and Roller will automatically create a role for a user if they do not have one yet. The default role is editor for their own blog.
The workflow for Roller integrating CAS 4 is as follows, user goes to a secured page on the roller application site, the user will get redirected to the
CAS 4 application site and be asked to login. After successful login, the user will be redirect back to where they started on the roller application site.
If they checked the remember me check box , then in the future, they will not have to login again until their remember me cookie expires.
Setting Up Your Development Environment
Roller uses Ant for compiling and deployment.
Depending on which IDE you use and what you development style is you may wish
to create a new empty roller_custom java project with Maven enabled if you want to use Maven dependency management instead using Ant and library references. I typically use Eclipse and Maven, so I created an empty roller_custom java project
and a new pom.xml, then enabled maven. This way I will be able to use Eclispe with Maven. I then built Roller using the ant build file (/roller/apps/weblogger/build.xml) to make sure Roller compiles correctly under ant first. To install Roller's jars into your local Maven Repository , you will need to use the experimental ant build file, /roller/build-poms.xml). You will need to download maven-ant-tasks-2.0.10.jar, and install it to roller/tools/buildtime/maven/maven-ant-tasks-2.0.10.jar and make sure to update it reference location in /roller/build-poms.xml. Next, I referenced the Roller's jars and CAS4 client jar in my roller_custom pom.xml file, like so:
<groupid>org.apache.roller</groupid>
<artifactid>roller-core</artifactid>
<version>4.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupid>org.apache.roller</groupid>
<artifactid>roller-business</artifactid>
<version>4.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupid>org.apache.roller</groupid>
<artifactid>planet-business</artifactid>
<version>4.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupid>org.apache.roller</groupid>
<artifactid>planet-web</artifactid>
<version>4.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupid>org.apache.roller</groupid>
<artifactid>roller-web</artifactid>
<version>4.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupid>org.jasig.cas</groupid>
<artifactid>cas-client-core</artifactid>
<version>3.1.5</version>
</dependency>
But, with all this hard work, you now have Maven goodness, and easy debugging compatibilty using Eclipse with Jetty if you wish.
SSO Implementation
the class: RollerUserDetailsService.java, to include the specific Role Name Prefix that Spring Security looks for.
Specifically, Spring Security looks for the prefix "ROLE_" in every role name.
//Spring Security uses special required rolePrefix, typically ROLE_
private String rolePrefix = "";
public RollerUserDetailsService()
{
}
/**
* Allows a default role prefix to be specified. If this is set to a non-empty value, then it is
* automatically prepended to any roles read in from the db. This may for example be used to add the
* ROLE_ prefix expected to exist in role names (by default) by some other Spring Security
* classes, in the case that the prefix is not already present in the db.
*
* @param rolePrefix the new prefix
*/
public void setRolePrefix(String rolePrefix) {
this.rolePrefix = rolePrefix;
}
protected String getRolePrefix() {
return rolePrefix;
}
public UserDetails loadUserByUsername(String userName)
throws UsernameNotFoundException, DataAccessException {
try {
Weblogger roller = WebloggerFactory.getWeblogger();
UserManager umgr = roller.getUserManager();
User userData = null;
if (userName.startsWith("http://")) {
if (userName.endsWith("/")) {
userName = userName.substring(0, userName.length() -1 );
}
try {
userData = umgr.getUserByAttribute(
UserAttribute.Attributes.OPENID_URL.toString(),
userName);
} catch (WebloggerException ex) {
throw new DataRetrievalFailureException("ERROR in user lookup", ex);
}
String name;
String password;
GrantedAuthority[] authorities;
// We are not throwing UsernameNotFound exception in case of
// openid authentication in order to recieve user SREG attributes
// from the authentication filter and save them
if (userData == null) {
authorities = new GrantedAuthority[1];
GrantedAuthority g = new GrantedAuthorityImpl("openidLogin");
authorities[0] = g;
name = "openid";
password = "openid";
} else {
authorities = getAuthorities(userData, umgr);
name = userData.getUserName();
password = userData.getPassword();
}
UserDetails usr = new org.springframework.security.userdetails.User(name, password, true, authorities);
return usr;
} else {
try {
userData = umgr.getUserByUserName(userName);
} catch (WebloggerException ex) {
throw new DataRetrievalFailureException("ERROR in user lookup", ex);
}
if (userData == null) {
//determine if autoProvisioning is enabled if so create User
if (WebloggerConfig.getBooleanProperty("users.sso.autoProvision.enabled"))
{
AutoProvision provisioner = RollerContext.getAutoProvision();
if(provisioner != null) {
boolean userProvisioned = provisioner.execute(userName);
if(userProvisioned) {
// try lookup again real quick
try{
userData = umgr.getUserByUserName(userName);
}
catch (WebloggerException e) {
throw new UsernameNotFoundException("ERROR no user: " + userName);
}
}
}
}
else
{
throw new UsernameNotFoundException("ERROR no user: " + userName);
}
}
}
GrantedAuthority[] authorities = getAuthorities(userData, umgr);
return new org.springframework.security.userdetails.User(userData.getUserName(), userData.getPassword(), true, authorities);
} catch (WebloggerException ex) {
throw new DataAccessResourceFailureException("ERROR: fetching roles", ex);
}
}
private GrantedAuthority[] getAuthorities(User userData, UserManager umgr) throws WebloggerException {
List
GrantedAuthority[] authorities = new GrantedAuthorityImpl[roles.size()];
if(!rolePrefix.isEmpty())
{
authorities = new GrantedAuthorityImpl[roles.size()*2];
}
int i = 0;
for (String role : roles) {
//add Roller Security Role for use with non-Spring Security Implementations
authorities[i++] = new GrantedAuthorityImpl(role);
//add Spring Security Role
authorities[i++] = new GrantedAuthorityImpl(rolePrefix + role);
}
return authorities;
}
}
Developers will probably need to implement their own custom class, if they created their RememberMe cookie not using the standard Spring Security Remember Me configuration.
Here is a brief code outline (snippet), if you for example you call your class:
}
This method returns UserDetails object, within this method you will need to extract the username from the RememberMe cookie (this will vary depending on what you stored in your cookie value, some people will store username, some will store email, etc).
With the username you can the create a UserDetails object by doing something like this:
Step 1 (optional , only if you wish to use Jetty as your debugging web server),
update your pom.xml file.
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>7.0.0.1beta2</version>
<configuration>
<webAppConfig>
<contextPath>/roller_custom</contextPath>
<tempDirectory>${project.build.directory}/work</tempDirectory>
</webAppConfig>
<connectors>
<connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
<port>8090</port>
</connector>
</connectors>
</configuration>
<!--add dependencies as needed like jdbc drivers and logging-->
<!--sample-->
<!--<dependencies>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>8.4-701.jdbc3</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
</dependencies>-->
</plugin>
Step 2: Updated web.xml (added Spring Security and CAS4):
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Roller Weblogger</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/security.xml,
/WEB-INF/jndi.xml
</param-value>
</context-param>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<!-- This is really strange, but for some reason it's needed to prevent
some problems with the file uploads not working intermittently -->
<filter>
<filter-name>struts2-cleanup</filter-name>
<filter-class>org.apache.struts2.dispatcher.ActionContextCleanUp</filter-class>
</filter>
<!--new-->
<filter>
<filter-name>CAS Single Sign Out Filter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<!--original filter-->
<!--<filter>
<filter-name>securityFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetBeanName</param-name>
<param-value>springSecurityFilterChain</param-value>
</init-param>
</filter>-->
<!--new-->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter>
<filter-name>DebugFilter</filter-name>
<filter-class>org.apache.roller.weblogger.ui.core.filters.DebugFilter</filter-class>
</filter>
<filter>
<filter-name>PersistenceSessionFilter</filter-name>
<filter-class>org.apache.roller.weblogger.ui.core.filters.PersistenceSessionFilter</filter-class>
</filter>
<filter>
<filter-name>BootstrapFilter</filter-name>
<filter-class>org.apache.roller.weblogger.ui.core.filters.BootstrapFilter</filter-class>
</filter>
<!--
Most app servers support compression, if yours doesn't then use this one,
but don't forget to uncomment the mapping below too.
<filter>
<filter-name>CompressionFilter</filter-name>
<filter-class>org.apache.roller.weblogger.ui.core.filters.CompressionFilter</filter-class>
</filter>
-->
<filter>
<filter-name>RequestMappingFilter</filter-name>
<filter-class>org.apache.roller.weblogger.ui.rendering.filters.RequestMappingFilter</filter-class>
</filter>
<filter>
<filter-name>InitFilter</filter-name>
<filter-class>org.apache.roller.weblogger.ui.core.filters.InitFilter</filter-class>
</filter>
<filter>
<filter-name>IPBanFilter</filter-name>
<filter-class>org.apache.roller.weblogger.ui.core.filters.IPBanFilter</filter-class>
</filter>
<filter>
<filter-name>SchemeEnforcementFilter</filter-name>
<filter-class>org.apache.roller.weblogger.ui.core.filters.SchemeEnforcementFilter</filter-class>
</filter>
<filter>
<filter-name>CharEncodingFilter</filter-name>
<filter-class>org.apache.roller.weblogger.ui.core.filters.CharEncodingFilter</filter-class>
</filter>
<!-- ******************************************
Filter mappings - order IS important here.
****************************************** -->
<!--
NOTE: Wherever "dispatcher" elements are specified in the filter mappings, they are
required for Servlet API 2.4 containers, such as Tomcat 5+ and Resin 3+, but should be
commented out for Servlet API 2.3 containers, like Tomcat 4.x and Resin 2.x.
-->
<!-- This filter ensures that the request encoding is set to UTF-8 before any
other processing forces request parsing using a default encoding.
Note: Any filters preceding this one MUST not cause request parsing. -->
<filter-mapping>
<filter-name>CharEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<!-- Ip Banning is mapped for comment and trackbacks only.
Note: this filter does nothing if an ip ban list is not configured. -->
<filter-mapping>
<filter-name>IPBanFilter</filter-name>
<url-pattern>/roller-ui/rendering/comment/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>IPBanFilter</filter-name>
<url-pattern>/roller-ui/rendering/trackback/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<!-- Scheme enforcement. Only here until we get Acegi scheme enforcement working -->
<filter-mapping>
<filter-name>SchemeEnforcementFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>CAS Single Sign Out Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Original Security filters - controls secure access to different parts of Roller -->
<!--<filter-mapping>
<filter-name>securityFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>-->
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>BootstrapFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<!-- Map everything to the PersistenceSessionFilter.
NOTE: Any filters preceding this one MUST NOT use persistence sessions.-->
<filter-mapping>
<filter-name>PersistenceSessionFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<!-- Init filter. performs some initialization on first request -->
<filter-mapping>
<filter-name>InitFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<!-- Request mapping. this is what allows the urls to work -->
<filter-mapping>
<filter-name>RequestMappingFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<!--
Most app servers support compression, if yours doesn't then use this one,
but don't forget to uncomment the filter definition above too.
<filter-mapping>
<filter-name>CompressionFilter</filter-name>
<url-pattern>/roller-ui/rendering/page/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>CompressionFilter</filter-name>
<url-pattern>/roller-ui/rendering/feed/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
-->
<!-- Struts2 -->
<filter-mapping>
<filter-name>struts2-cleanup</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<!-- Context Listeners -->
<!--new-->
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
<listener>
<listener-class>org.apache.roller.weblogger.ui.core.RollerSession</listener-class>
</listener>
<listener>
<listener-class>org.apache.roller.weblogger.ui.core.RollerContext</listener-class>
</listener>
<listener>
<listener-class>org.apache.tiles.web.startup.TilesListener</listener-class>
</listener>
<!-- Servlet Definitions -->
<servlet>
<servlet-name>PageServlet</servlet-name>
<servlet-class>org.apache.roller.weblogger.ui.rendering.servlets.PageServlet</servlet-class>
<load-on-startup>5</load-on-startup>
</servlet>
<servlet>
<servlet-name>FeedServlet</servlet-name>
<servlet-class>org.apache.roller.weblogger.ui.rendering.servlets.FeedServlet</servlet-class>
<load-on-startup>5</load-on-startup>
</servlet>
<servlet>
<servlet-name>ResourceServlet</servlet-name>
<servlet-class>org.apache.roller.weblogger.ui.rendering.servlets.ResourceServlet</servlet-class>
<load-on-startup>5</load-on-startup>
</servlet>
<servlet>
<servlet-name>MediaResourceServlet</servlet-name>
<servlet-class>org.apache.roller.weblogger.ui.rendering.servlets.MediaResourceServlet</servlet-class>
<load-on-startup>5</load-on-startup>
</servlet>
<servlet>
<servlet-name>SearchServlet</servlet-name>
<servlet-class>org.apache.roller.weblogger.ui.rendering.servlets.SearchServlet</servlet-class>
<load-on-startup>5</load-on-startup>
</servlet>
<servlet>
<servlet-name>OpenSearchServlet</servlet-name>
<servlet-class>org.apache.roller.weblogger.webservices.opensearch.OpenSearchServlet</servlet-class>
<load-on-startup>10</load-on-startup>
</servlet>
<servlet>
<servlet-name>CommentServlet</servlet-name>
<servlet-class>org.apache.roller.weblogger.ui.rendering.servlets.CommentServlet</servlet-class>
<load-on-startup>7</load-on-startup>
</servlet>
<servlet>
<servlet-name>TrackbackServlet</servlet-name>
<servlet-class>org.apache.roller.weblogger.ui.rendering.servlets.TrackbackServlet</servlet-class>
<load-on-startup>7</load-on-startup>
</servlet>
<servlet>
<servlet-name>RSDServlet</servlet-name>
<servlet-class>org.apache.roller.weblogger.ui.rendering.servlets.RSDServlet</servlet-class>
<load-on-startup>7</load-on-startup>
</servlet>
<servlet>
<servlet-name>PlanetFeedServlet</servlet-name>
<servlet-class>org.apache.roller.weblogger.ui.rendering.servlets.PlanetFeedServlet</servlet-class>
<load-on-startup>7</load-on-startup>
</servlet>
<servlet>
<servlet-name>CommentAuthenticatorServlet</servlet-name>
<servlet-class>org.apache.roller.weblogger.ui.rendering.servlets.CommentAuthenticatorServlet</servlet-class>
<load-on-startup>7</load-on-startup>
</servlet>
<servlet>
<servlet-name>PreviewServlet</servlet-name>
<servlet-class>org.apache.roller.weblogger.ui.rendering.servlets.PreviewServlet</servlet-class>
<load-on-startup>9</load-on-startup>
</servlet>
<servlet>
<servlet-name>PreviewResourceServlet</servlet-name>
<servlet-class>org.apache.roller.weblogger.ui.rendering.servlets.PreviewResourceServlet</servlet-class>
<load-on-startup>9</load-on-startup>
</servlet>
<servlet>
<servlet-name>PreviewThemeImageServlet</servlet-name>
<servlet-class>org.apache.roller.weblogger.ui.rendering.servlets.PreviewThemeImageServlet</servlet-class>
<load-on-startup>9</load-on-startup>
</servlet>
<servlet>
<servlet-name>RedirectServlet</servlet-name>
<servlet-class>org.apache.roller.weblogger.ui.rendering.velocity.deprecated.RedirectServlet</servlet-class>
<load-on-startup>9</load-on-startup>
</servlet>
<servlet>
<servlet-name>StrutsRedirectServlet</servlet-name>
<servlet-class>org.apache.roller.weblogger.ui.struts2.util.StrutsRedirectServlet</servlet-class>
<load-on-startup>9</load-on-startup>
</servlet>
<servlet>
<servlet-name>AtomServlet</servlet-name>
<servlet-class>com.sun.syndication.propono.atom.server.AtomServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>CommentDataServlet</servlet-name>
<servlet-class>org.apache.roller.weblogger.ui.struts2.ajax.CommentDataServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>UserDataServlet</servlet-name>
<servlet-class>org.apache.roller.weblogger.ui.struts2.ajax.UserDataServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>AdminServlet</servlet-name>
<servlet-class>org.apache.roller.weblogger.webservices.adminprotocol.AdminServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>TagDataServlet</servlet-name>
<servlet-class>org.apache.roller.weblogger.webservices.tagdata.TagDataServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>XmlRpcServlet</servlet-name>
<servlet-class>org.apache.xmlrpc.webserver.XmlRpcServlet</servlet-class>
<init-param>
<description>
Sets, whether the servlet supports vendor extensions for XML-RPC.
</description>
<param-name>enabledForExtensions</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<!-- BEGIN OAUTH -->
<servlet>
<servlet-name>RequestTokenServlet</servlet-name>
<servlet-class>org.apache.roller.weblogger.webservices.oauth.RequestTokenServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>AuthorizationServlet</servlet-name>
<servlet-class>org.apache.roller.weblogger.webservices.oauth.AuthorizationServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>AccessTokenServlet</servlet-name>
<servlet-class>org.apache.roller.weblogger.webservices.oauth.AccessTokenServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RequestTokenServlet</servlet-name>
<url-pattern>/roller-services/oauth/requestToken</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>AuthorizationServlet</servlet-name>
<url-pattern>/roller-services/oauth/authorize</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>AccessTokenServlet</servlet-name>
<url-pattern>/roller-services/oauth/accessToken</url-pattern>
</servlet-mapping>
<!-- END OAUTH -->
<!-- Rendering Servlets -->
<servlet-mapping>
<servlet-name>PageServlet</servlet-name>
<url-pattern>/roller-ui/rendering/page/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>FeedServlet</servlet-name>
<url-pattern>/roller-ui/rendering/feed/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ResourceServlet</servlet-name>
<url-pattern>/roller-ui/rendering/resources/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>MediaResourceServlet</servlet-name>
<url-pattern>/roller-ui/rendering/media-resources/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>CommentServlet</servlet-name>
<url-pattern>/roller-ui/rendering/comment/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>TrackbackServlet</servlet-name>
<url-pattern>/roller-ui/rendering/trackback/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>RSDServlet</servlet-name>
<url-pattern>/roller-ui/rendering/rsd/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>SearchServlet</servlet-name>
<url-pattern>/roller-ui/rendering/search/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>PlanetFeedServlet</servlet-name>
<url-pattern>/planetrss/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>CommentAuthenticatorServlet</servlet-name>
<url-pattern>/CommentAuthenticatorServlet</url-pattern>
</servlet-mapping>
<!-- Preview Servlets -->
<servlet-mapping>
<servlet-name>PreviewServlet</servlet-name>
<url-pattern>/roller-ui/authoring/preview/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>PreviewResourceServlet</servlet-name>
<url-pattern>/roller-ui/authoring/previewresource/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>PreviewThemeImageServlet</servlet-name>
<url-pattern>/roller-ui/authoring/previewtheme</url-pattern>
</servlet-mapping>
<!-- Servlets for supporting Ajax -->
<servlet-mapping>
<servlet-name>CommentDataServlet</servlet-name>
<url-pattern>/roller-ui/authoring/commentdata/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>UserDataServlet</servlet-name>
<url-pattern>/roller-ui/authoring/userdata/*</url-pattern>
</servlet-mapping>
<!-- Web Service Servlets -->
<servlet-mapping>
<servlet-name>XmlRpcServlet</servlet-name>
<url-pattern>/roller-services/xmlrpc</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>AtomServlet</servlet-name>
<url-pattern>/roller-services/app/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>AdminServlet</servlet-name>
<url-pattern>/roller-services/rap/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>TagDataServlet</servlet-name>
<url-pattern>/roller-services/tagdata/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>OpenSearchServlet</servlet-name>
<url-pattern>/roller-services/opensearch/*</url-pattern>
</servlet-mapping>
<!-- Redirect Support for pre-3.0 urls -->
<servlet-mapping>
<servlet-name>RedirectServlet</servlet-name>
<url-pattern>/language/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>RedirectServlet</servlet-name>
<url-pattern>/comments/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>RedirectServlet</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>RedirectServlet</servlet-name>
<url-pattern>/rsd/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>RedirectServlet</servlet-name>
<url-pattern>/flavor/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>RedirectServlet</servlet-name>
<url-pattern>/rss/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>RedirectServlet</servlet-name>
<url-pattern>/atom/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>RedirectServlet</servlet-name>
<url-pattern>/page/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>RedirectServlet</servlet-name>
<url-pattern>/search/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>RedirectServlet</servlet-name>
<url-pattern>/xmlrpc/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>RedirectServlet</servlet-name>
<url-pattern>/editor/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>RedirectServlet</servlet-name>
<url-pattern>/admin/*</url-pattern>
</servlet-mapping>
<!-- Redirect support for some old struts1 urls -->
<servlet-mapping>
<servlet-name>StrutsRedirectServlet</servlet-name>
<url-pattern>/roller-ui/yourWebsites.do</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>StrutsRedirectServlet</servlet-name>
<url-pattern>/roller-ui/authoring/commentManagement.do</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>home.jsp</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/roller-ui/errors/error.jsp</location>
</error-page>
<error-page>
<error-code>403</error-code>
<location>/roller-ui/errors/403.jsp</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/roller-ui/errors/404.jsp</location>
</error-page>
<!-- jndi resources -->
<!--<resource-ref>
<res-ref-name>jdbc/rollerdb</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>-->
<!--<resource-ref>
<res-ref-name>mail/Session</res-ref-name>
<res-type>javax.mail.Session</res-type>
<res-auth>Container</res-auth>
</resource-ref>-->
</web-app>
<!-- BEGIN: example config. for using Container Managed Authentication
<security-constraint>
<web-resource-collection>
<web-resource-name>Weblog admin and editor resources</web-resource-name>
<url-pattern>/roller-ui/createWeblog.rol</url-pattern>
<url-pattern>/roller-ui/authoring/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>weblog-admin</role-name>
<role-name>weblog-user</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Weblog admin and editor HTTPS resources</web-resource-name>
<url-pattern>/roller-ui/login-redirect.jsp</url-pattern>
<url-pattern>/roller-ui/login-redirect.rol</url-pattern>
<url-pattern>/roller-ui/authoring/userdata</url-pattern>
<url-pattern>/roller-ui/authoring/membersInvite.rol</url-pattern>
<url-pattern>/roller-ui/authoring/membersInvite!save.rol</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>weblog-admin</role-name>
<role-name>weblog-user</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Global Admin resources</web-resource-name>
<url-pattern>/roller-ui/admin/*</url-pattern>
<url-pattern>/rewrite-status.rol</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>weblog-admin</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Gobal Admin HTTPS resources</web-resource-name>
<url-pattern>/roller-ui/admin/userAdmin.rol</url-pattern>
<url-pattern>/roller-ui/admin/createUser.rol</url-pattern>
<url-pattern>/roller-ui/admin/createUser!save.rol</url-pattern>
<url-pattern>/roller-ui/admin/modifyUser.rol</url-pattern>
<url-pattern>/roller-ui/admin/modifyUser!save.rol</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>weblog-admin</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>editor res</web-resource-name>
<url-pattern>/roller-ui/menu.rol</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>weblog-user</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Editor HTTPS resources</web-resource-name>
<url-pattern>/roller-ui/profile.rol</url-pattern>
<url-pattern>/roller-ui/profile!save.rol</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>weblog-user</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>HTTPS resources</web-resource-name>
<url-pattern>/roller-ui/login.rol</url-pattern>
<url-pattern>/roller-ui/register.rol</url-pattern>
<url-pattern>/roller-ui/register!save.rol</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>Roller_UserRealm</realm-name>
<form-login-config>
<form-login-page>/roller-ui/login.rol</form-login-page>
<form-error-page>/roller-ui/login.rol?error=true</form-error-page>
</form-login-config>
</login-config>
<security-role>
<role-name>weblog-admin</role-name>
</security-role>
<security-role>
<role-name>weblog-user</role-name>
</security-role>
END: example config. for using Container Managed Authentication -->
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">
<!-- new -->
<!--access roles : ROLE_USER,ROLE_SUPERVISOR -->
<http entry-point-ref="casProcessingFilterEntryPoint">
<intercept-url pattern="/images/**" filters="none"/>
<intercept-url pattern="/scripts/**" filters="none"/>
<intercept-url pattern="/styles/**" filters="none"/>
<intercept-url pattern="/roller-ui/login-redirect**" access="ROLE_admin,ROLE_editor" />
<!--<intercept-url pattern="/roller-ui/login-redirect**" access="IS_AUTHENTICATED_ANONYMOUSLY,ROLE_admin,ROLE_editor"/>-->
<intercept-url pattern="/roller-ui/profile**" access="ROLE_admin,ROLE_editor"/>
<intercept-url pattern="/roller-ui/createWeblog**" access="ROLE_admin,ROLE_editor"/>
<intercept-url pattern="/roller-ui/menu**" access="ROLE_admin,ROLE_editor"/>
<intercept-url pattern="/roller-ui/authoring/**" access="ROLE_admin,ROLE_editor"/>
<intercept-url pattern="/roller-ui/admin/**" access="ROLE_admin"/>
<intercept-url pattern="/rewrite-status*" access="ROLE_admin"/>
<intercept-url pattern="/roller-ui/user.do*" access="ROLE_USER"/>
<anonymous />
<http-basic />
</http>
<!-- ======================== CENTRAL AUTHENTICATION SERVICE (CAS) ======================= -->
<!--new-->
<beans:bean id="casProcessingFilter" class="org.springframework.security.ui.cas.CasProcessingFilter">
<custom-filter after="CAS_PROCESSING_FILTER"/>
<beans:property name="authenticationManager" ref="authenticationManager"/>
<beans:property name="authenticationFailureUrl" value="/roller-ui/login.rol?error=true"/>
<beans:property name="defaultTargetUrl" value="/"/>
<beans:property name="rememberMeServices" ref="rememberMeServices" />
<beans:property name="filterProcessesUrl" value="/j_spring_cas_security_check"/>
</beans:bean>
<beans:bean id="casProcessingFilterEntryPoint" class="org.springframework.security.ui.cas.CasProcessingFilterEntryPoint">
<beans:property name="loginUrl" value="http://localhost:8080/cas/login"/>
<beans:property name="serviceProperties" ref="serviceProperties"/>
</beans:bean>
<!--new-->
<beans:bean id="casAuthenticationProvider" class="org.springframework.security.providers.cas.CasAuthenticationProvider">
<custom-authentication-provider />
<beans:property name="userDetailsService" ref="userRollerService"/>
<beans:property name="serviceProperties" ref="serviceProperties" />
<beans:property name="ticketValidator">
<beans:bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
<beans:constructor-arg index="0" value="http://localhost:8080/cas" />
</beans:bean>
</beans:property>
<beans:property name="key" value="an_id_for_this_auth_provider_only"/>
</beans:bean>
<beans:bean id="proxyGrantingTicketStorage" class="org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl" />
<beans:bean id="serviceProperties" class="org.springframework.security.ui.cas.ServiceProperties">
<beans:property name="service" value="http://localj.endurotracker.com:8090/roller_custom/j_spring_cas_security_check"/>
<beans:property name="sendRenew" value="false"/>
</beans:bean>
<!-- Read users from Roller API -->
<beans:bean id="userRollerService"
class="org.apache.roller.weblogger.ui.core.security.RollerUserDetailsService" >
<beans:property name="rolePrefix" value="ROLE_"/>
</beans:bean>
<!--FOR TESTING/DEBUGGING ONLY-->
<!--<user-service id="userService">
<user name="rod" password="rod" authorities="ROLE_SUPERVISOR,ROLE_USER" />
<user name="dianne" password="dianne" authorities="ROLE_SUPERVISOR,ROLE_USER" />
<user name="scott" password="scott" authorities="ROLE_SUPERVISOR,ROLE_USER" />
</user-service>-->
<!--RememberMe Configurations -->
<beans:bean id="rememberMeProcessingFilter" class="org.springframework.security.ui.rememberme.RememberMeProcessingFilter">
<custom-filter position="REMEMBER_ME_FILTER" />
<beans:property name="authenticationManager" ref="authenticationManager" />
<beans:property name="rememberMeServices" ref="rememberMeServices" />
</beans:bean>
<!-- your customizations -->
<!--
Activates various annotations to be detected in bean classes:
Spring's @Required and @Autowired, as well as JSR 250's @Resource.
-->
<context:annotation-config />
<!--Try adding this-->
<aop:aspectj-autoproxy />
<!-- Turn on @Required -->
<beans:bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />
<beans:bean id="securityService"
class="yourPackage.SecurityService">
<beans:property name="usersDao" ref="usersDao" />
</beans:bean>
<!-- Note: if your usersDao uses sessionFactory you will need to add sessionFactory bean as well, this is just for illustration purposes-->
<beans:bean id="usersDao"
class="yourPackage.UsersDao">
<beans:property name="sessionFactory" ref="sessionFactory"/>
</beans:bean>
<beans:bean id="usersInRolesDao"
class="yourPackage.UsersInRolesDao">
<beans:property name="sessionFactory" ref="sessionFactory"/>
</beans:bean>
<beans:bean id="userService" class="yourPackage.UserService">
<beans:property name="usersDao" ref="usersDao" />
<beans:property name="authMgr" ref="authenticationManager"/>
<beans:property name="userCache" ref="userCache" />
<beans:property name="messageSource" ref="messageSource" />
<beans:property name="userTokenCache" ref="userTokenCache"/>
</beans:bean>
<beans:bean id="rememberMeAuthenticationProvider" class="org.springframework.security.providers.rememberme.RememberMeAuthenticationProvider">
<custom-authentication-provider />
<beans:property name="key" value="CHANGE_THIS_2" />
</beans:bean>
<beans:bean id="authenticationManager" class="org.springframework.security.providers.ProviderManager">
<beans:property name="providers">
<beans:list>
<beans:ref local="casAuthenticationProvider" />
<beans:bean class="org.springframework.security.providers.anonymous.AnonymousAuthenticationProvider">
<beans:property name="key" value="CHANGE_THIS_1" />
</beans:bean>
<beans:ref local="rememberMeAuthenticationProvider" />
</beans:list>
</beans:property>
</beans:bean>
<!--NOTE : Don't forget to implement a RollerRememberMeServices class, unless you use the Plain vanilla Spring Security RemberMeServices class -->
<!--plain vanilla using regular Spring Security-->
<!--<bean id="rememberMeServices" class="org.springframework.security.ui.rememberme.TokenBasedRememberMeServices">
<property name="userDetailsService" ref="usersDao"/>
<property name="key" value="CHANGE_THIS_2"/>
</bean>-->
<beans:bean id="rememberMeServices" class="org.apache.roller.weblogger.business.rememberme.RollerRememberMeServices">
<beans:property name="userDetailsService" ref="userRollerService" />
<beans:property name="userService" ref="userService" />
<beans:property name="key" value="CHANGE_THIS_2" />
<beans:property name="parameter" value="_spring_security_remember_me" />
<beans:property name="cookieName" value="SPRING_SECURITY_REMEMBER_ME_COOKIE" />
<beans:property name="cookieDomain" value=".yourwebsite.com" />
<beans:property name="tokenValiditySeconds" value="1209600" />
</beans:bean>
<beans:bean id="passwordEncoder" class="yourPackage.PasswordEncoder">
<beans:property name="passwordFormatforBean" value="Hashed" />
</beans:bean>
<beans:bean id="userTokenCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<beans:property name="cacheManager" ref="cacheManager" />
<beans:property name="cacheName" value = "yourPackage.UserTokenCache"/>
</beans:bean>
<beans:bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<beans:property name="configLocation" value="classpath:ehcache.xml" />
</beans:bean>
<beans:bean id="userCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<beans:property name="cacheManager" ref="cacheManager" />
<beans:property name="cacheName" value="userCache" />
</beans:bean>
<beans:bean id="userCache" class="org.springframework.security.providers.dao.cache.EhCacheBasedUserCache">
<beans:property name="cache">
<beans:ref local="userCacheBackend" />
</beans:property>
</beans:bean>
</beans:beans>
Wednesday, November 18, 2009
Single Sign On with CAS and RememberMe Part 1
As an avid internet user I have a lot of different sites that I use, for most sites I have a separate user account and password.
With lots of accounts, it can be hard to remember all my different user names and passwords.
With Endurotracker.com, we want to make you user experience as enjoyable as possible. So, unlike some sites where you need to 3 different username and passwords one for main site, one for forum , and one for blog engine, we have made so that you only need a Single Sign On or Username/password combo for all the different applications.
In this series of blog entries, I will discuss how I implement Single Sign across 3 different applications, Roller ( a Open Source Blogging Engine),
JForum ( a Open Source Forum Engine), and our main application Endurotracker.com.
The way we implement Single Sign On (SSO) will be to use CAS 4, Central Authentication System 4 written by www.jasig.org and the
Spring Framework, specifically Spring Security formerly Aegis Security.
At a high level the way SSO works is : if a user is not logged in and they go to a secure area of the Roller application, then they will get prompted
to log in (via a redirect to the CAS 4 application), after successful login they get redirected back to where they where in the Roller application.
SSO will be implemented on 3 applications so this type of workflow will occur for the 3 applications, Roller, JForum, and Endurotracker.
Setting of CAS4
In this section we will go over how CAS4 was setup.
Step 1: Get CAS4 from jasig.org's SVN trunk repository
Step 2: Configure your Eclipse IDE and setup the CAS4 project : cas-server-webapp.
Optional (but good idea for debugging) , pull in all the CAS4 projects (over a dozen projects).
RememberMe Implementation
CAS4 takes advantage of the Open Source framework Spring. Specifically it uses Spring Web Flow and Spring Security.
(see www.springsource.org for full documenation).
In a nutshell, the way we implement RememberMe is by creating a RememberMe cookie and then utilize this cookie to determine
who the user is. If the RememberMe cookie is not found or is expired we force the user to login.
You can use the standard RememberMeServices class from Spring Security or you can create your own RememberMeServices class
if you need a implement things like encrypting your cookies. We implement our own RememberMeServices class to encrypt the values
stored in our cookies. Creating your own RememberMeServices class is optional.
Add this html snippet to promptForCredentials.jsp which will add a remember me check box to the login form:
For Spring Web Flow, to store whether the user has checked rememberMe check box, we need to create a small class, CaptchaRememberMeCredentialImpl.java, here is the source (small class):
@ValidateDefinition
public class CaptchaRememberMeAuthenticationResponsePluginImpl extends CaptchaAuthenticationResponsePluginImpl implements AuthenticationResponsePlugin {
//WARNING: implement all required methods this is just a SNIPPET for illustration purposes, this code will not compile, you will
// need to implement all required methods and add your imports, etc.
public static final String SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY = "SPRING_SECURITY_REMEMBER_ME_COOKIE";
@Override
public void handle(final LoginRequest loginRequest, final AuthenticationResponse response) {
if (response.succeeded()) {
String username ="";
String password ="";
List
if(creds.size() > 0)
{
CaptchaRememberMeCredentialImpl userCred = (CaptchaRememberMeCredentialImpl) creds.get(0);
username = userCred.getUsername();
password = userCred.getPassword();
if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password)) {
return;
}
//if isRememberMe is false then return (don't set rememberme cookie)
if(userCred.isRememberMe()==false)
{
return;
}
//need to implement your own UserDetails Class , see Spring Security's UserDetails javadoc for more info
UserDetails userDetails = getUserDetailsService().loadUserByUsername(username);
if(userDetails != null){
Users user = userDetails .getUser();
RequestContext context = RequestContextHolder.getRequestContext();
ExternalContext externalContext = context.getExternalContext();
//determine what data you wish to store in cookie value
//typically store username or email as the key, or userid possibly
String cookieValue = user.getUserName().toString();
response.getAttributes().put(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, cookieValue);
}
return;
}
else
{
return;
}
}
}
}
CAS4 has implemented a plugin architecture that allows developers to create custom plugins.
Once you create a plugin, to get CAS4 to use it you just reference the plugin in the your deployment configuration file (in CAS3 called deployerConfigContext.xml) or if you utilize annotations will get picked up automagically. (i.e @Component, etc)
In this case our plugin will need to get called during the authentication process, so we will extend the CaptchaAuthenticationResponsePluginImpl
and implement AuthenticationResponsePlugin.
In a nutshell the plugin calculates the Cookie's value and stores it in the HttpResponse.
During the workflow after successful authentication the RememberMeCookieCreater class , extracts the Cookie's value from
the HttpResponse and creates new RememberMe Cookie using this value as input.
@ValidateDefinition
public class CaptchaRememberMeAuthenticationResponsePluginImpl extends CaptchaAuthenticationResponsePluginImpl implements AuthenticationResponsePlugin {
//WARNING: implement all required methods this is just a SNIPPET for illustration purposes, this code will not compile, you will
// need to implement all required methods and add your imports, etc.
public static final String SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY = "SPRING_SECURITY_REMEMBER_ME_COOKIE";
@Override
public void handle(final LoginRequest loginRequest, final AuthenticationResponse response) {
if (response.succeeded()) {
String username ="";
String password ="";
List
if(creds.size() > 0)
{
CaptchaRememberMeCredentialImpl userCred = (CaptchaRememberMeCredentialImpl) creds.get(0);
username = userCred.getUsername();
password = userCred.getPassword();
if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password)) {
return;
}
//if isRememberMe is false then return (don't set rememberme cookie)
if(userCred.isRememberMe()==false)
{
return;
}
//need to implement your own UserDetails Class , see Spring Security's UserDetails javadoc for more info
UserDetails userDetails = getUserDetailsService().loadUserByUsername(username);
if(userDetails != null){
Users user = userDetails .getUser();
RequestContext context = RequestContextHolder.getRequestContext();
ExternalContext externalContext = context.getExternalContext();
//determine what data you wish to store in cookie value
//typically store username or email as the key, or userid possibly
String cookieValue = user.getUserName().toString();
response.getAttributes().put(SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, cookieValue);
}
return;
}
else
{
return;
}
}
}
}
We then have to configure the Spring Web Flow configuration file, login.xml (locate under /webapp/WEB-INF/login/login.xml) to call this class during our workflow.
Here is the xml snippets:
xml snippet 1, update credentials var to use CaptchaRememberMeCredentialsImpl:
<var name="credentials" class="org.jasig.cas.server.authentication.CaptchaRememberMeCredentialImpl" />
xml snippet 2, add rememberme property:
<binding property="username" required="true" />
<binding property="password" required="true" />
<binding property="captchaResponse" required="false" />
<binding property="rememberMe" required="true" />
</binder>
xml snippet 3:
<transition on="submit" to="determineIfSessionCreated">
<evaluate expression="loginRequest.credentials.add(credentials)" />
<evaluate expression="centralAuthenticationService.login(loginRequest)" result="requestScope.loginResponse" result-type="org.jasig.cas.server.login.LoginResponse" />
<evaluate expression="sessionCookieCreater.createSessionCookie(loginResponse, null, externalContext)" />
<!--RememberMe Cookie Logical Step Here-->
<evaluate expression="rememberMeCookieCreater.createSessionCookie(loginResponse, null, externalContext)" />
<evaluate expression="loginRequest.setSessionId(loginResponse.sessionId)" />
</transition>
Editing Configuration:
Step 3: Edit cas-server-webapp's pom.xml to allow for use of jetty (web server used in eclipse for debugging)
pom.xml Snippet:
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>7.0.0.1beta2</version>
<configuration>
<webAppConfig>
<contextPath>/cas</contextPath>
</webAppConfig>
<connectors>
<connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
<port>8080</port>
</connector>
</connectors>
</configuration>
Update the
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
WEB-INF/cas-servlet.xml,
WEB-INF/spring/applicationContext.xml,
WEB-INF/spring/jcaptcha-configuration.xml,
WEB-INF/spring/testAuthenticationHandler-configuration.xml,
WEB-INF/spring/urlCredentialAuthenticationHandler-configuration.xml,
/WEB-INF/deployerConfigContext.xml,
/WEB-INF/jndi.xml
</param-value>
</context-param>
Step 5: Example cas-servlet.xml (if you run into issues):
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:webflow="http://www.springframework.org/schema/webflow-config"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/webflow-config
http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd">
<!-- Web flow 2.0 schema -->
<webflow:flow-registry id="flowRegistry">
<webflow:flow-location path="/WEB-INF/login/login.xml" id="login"/>
</webflow:flow-registry>
<webflow:flow-executor id="flowExecutor" />
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping" >
<property name="order" value="0" />
<property name="flowRegistry" ref="flowRegistry" />
</bean>
<bean class="org.springframework.web.servlet.i18n.CookieLocaleResolver" />
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter" >
<property name="flowExecutor" ref="flowExecutor" />
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" >
<property name="order" value="0" />
</bean>
<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver" >
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
</bean>
<!-- Dispatches requests mapped to POJO @Controllers implementations -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
<!-- Dispatches requests mapped to org.springframework.web.servlet.mvc.Controller implementations -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
</beans>
Step 6: Update spring/applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="org.jasig.cas.server.authentication"/>
<context:component-scan base-package="org.jasig.cas.server.login"/>
<context:component-scan base-package="org.jasig.cas.server.logout"/>
<context:component-scan base-package="org.jasig.cas.server.session"/>
<context:component-scan base-package="org.jasig.cas.server.util"/>
<context:component-scan base-package="org.jasig.cas.server"/>
<context:component-scan base-package="org.jasig.cas.server.login"/>
<context:component-scan base-package="org.jasig.cas.server.session"/>
<context:component-scan base-package="org.jasig.cas.server.web"/>
<context:annotation-config />
<!--Default Auth. Manager, can override default in deployerConfigContext.xml-->
<bean id="authenticationManager" class="org.jasig.cas.server.authentication.DefaultAuthenticationManagerImpl">
</bean>
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>org/javalid/core/validator/jv_messages</value>
<value>messages</value>
<value>org/jasig/cas/server/messages/log</value>
<value>org/jasig/cas/server/session/messages/cas_messages</value>
</list>
</property>
</bean>
<bean id="casMessageSource" class="org.jasig.cas.server.util.CasMessageSourceAccessor" />
</beans>
Step 7: Example spring/jcaptcha-configuration.xml (current trunk version):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean class="com.octo.captcha.service.image.DefaultManageableImageCaptchaService" id="imageCaptchaService" />
<bean
class="org.jasig.cas.server.authentication.DefaultCaptchaStatusImpl" id="captchaStatus"/>
<bean class="org.jasig.cas.server.authentication.DefaultCaptchaStatusImplFactory" id="captchaStatusFactory" >
<property name="numberOfFailures" value="2" />
<property name="numberOfMilliseconds" value="60000" />
</bean>
<bean class="org.jasig.cas.server.authentication.InMemoryCaptchaStatusStorageImpl" id="captchaStatusStorage" />
</beans>
Step 8: Create deployerConfigContext.xml (main customization config file):
<?xml version="1.0" encoding="UTF-8"?>
<!--
| deployerConfigContext.xml centralizes into one file some of the declarative configuration that
| all CAS deployers will need to modify.
|
| This file declares some of the Spring-managed JavaBeans that make up a CAS deployment.
| The beans declared in this file are instantiated at context initialization time by the Spring
| ContextLoaderListener declared in web.xml. It finds this file because this
| file is among those declared in the context parameter "contextConfigLocation".
|
| By far the most common change you will need to make in this file is to change the last bean
| declaration to replace the default SimpleTestUsernamePasswordAuthenticationHandler with
| one implementing your approach for authenticating usernames and passwords.
+-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd">
<!--
| This bean declares our AuthenticationManager. The CentralAuthenticationService service bean
| declared in applicationContext.xml picks up this AuthenticationManager by reference to its id,
| "authenticationManager". Most deployers will be able to use the default AuthenticationManager
| implementation and so do not need to change the class of this bean. We include the whole
| AuthenticationManager here in the deployerConfigContext.xml so that you can see the things you will
| need to change in context.
+-->
<bean class="org.springframework.web.util.CookieGenerator" id="sessionCookieGenerator"
p:cookieName="TGT"
p:cookieSecure="false"/>
<bean class="org.springframework.web.util.CookieGenerator" id="rememberMeCookieGenerator"
p:cookieName="SPRING_SECURITY_REMEMBER_ME_COOKIE"
p:cookieDomain=".endurotracker.com"
p:cookieMaxAge="1209600"
p:cookieSecure="false" />
<!--You Can override Auth. Mgr here if you wish-->
<!--This is just a example to use as template-->
<!--<bean id="authenticationManager"
class="org.jasig.cas.server.authentication.DefaultAuthenticationManagerImpl">
</bean>-->
<!--You Can override CredentialToPrincipalResolver here if you wish-->
<!--This is just a example to use as template-->
<!--<bean class="org.jasig.cas.server.authentication.SimpleUsernamePasswordCredentialToPrincipalResolver" id="usernamePasswordCredentialToPrincipalResolver" />-->
<!--You Can override UsernamePasswordCredentialsAuthenticationHandler here if you wish-->
<!--This is just a example to use as template-->
<!--<bean class="org.jasig.cas.server.authentication.handler.TestUsernamePasswordCredentialsAuthenticationHandler" id="testUsernamePasswordCredentialsAuthenticationHandler"/>-->
<!--your custom AuthenticationHandler bean Here-->
<bean class="yourPackage.YourCustomAuthenticationHandler" >
<property name="securityService" ref="securityService" />
</bean>
<!--Your customizations here-->
<!--
Activates various annotations to be detected in bean classes:
Spring's @Required and @Autowired, as well as JSR 250's @Resource.
-->
<context:annotation-config />
<aop:aspectj-autoproxy />
<!-- Turn on @Required -->
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />
<bean id="securityService"
class="yourpackagename.SecurityService">
<property name="usersDao" ref="usersDao" />
</bean>
<bean id="usersDao"
class="yourpackagename.UsersDao">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!--RememberMe Section -->
<bean id="usersInRolesDao"
class="yourpackagename.UsersInRolesDao">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!--NOTE if you use sessionFactories your will need to configure your sessionFactory bean-->
<bean id="userService" class="yourPackageName.UserService">
<property name="usersDao" ref="usersDao" />
<property name="authMgr" ref="yourCustomAuthenticationManager"/>
<property name="userCache" ref="userCache" />
<property name="messageSource" ref="messageSource" />
<property name="userTokenCache" ref="userTokenCache"/>
</bean>
<bean id="rememberMeAuthenticationProvider" class="org.springframework.security.providers.rememberme.RememberMeAuthenticationProvider">
<security:custom-authentication-provider />
<property name="key" value="CHANGE_THIS_2" />
</bean>
<bean id="yourCustomAuthenticationManager" class="org.springframework.security.providers.ProviderManager">
<property name="providers">
<list>
<ref local="daoAuthenticationProvider" />
<bean class="org.springframework.security.providers.anonymous.AnonymousAuthenticationProvider">
<property name="key" value="CHANGE_THIS_1" />
</bean>
<ref local="rememberMeAuthenticationProvider" />
</list>
</property>
</bean>
<!--plain vanilla using regular Spring Security-->
<bean id="rememberMeServices" class="org.springframework.security.ui.rememberme.TokenBasedRememberMeServices">
<property name="userDetailsService" ref="usersDao"/>
<property name="key" value="CHANGE_THIS_2"/>
</bean>
<!--example of custom rememberMeServices class config-->
<!--<bean id="rememberMeServices" class="yourPackage.YourCustomRememberMeServices">
<property name="userDetailsService" ref="usersDao" />
<property name="userService" ref="userService" />
<property name="usersInRolesDao" ref="usersInRolesDao" />
<property name="key" value="CHANGE_THIS_2" />
<property name="parameter" value="_spring_security_remember_me" />
<property name="cookieName" value="SPRING_SECURITY_REMEMBER_ME_COOKIE" />
<property name="tokenValiditySeconds" value="1209600" /><!-- 14 days -->
<!--<property name="cookieDomain" value="localhost" />-->
<property name="cookieDomain" value=".yourwebsite.com" />
</bean>-->
<bean id="daoAuthenticationProvider" class="org.springframework.security.providers.dao.DaoAuthenticationProvider">
<security:custom-authentication-provider />
<property name="userDetailsService" ref="usersDao" />
<property name="passwordEncoder" ref="passwordEncoder" />
<property name="userCache" ref="userCache" />
</bean>
<bean id="passwordEncoder" class="yourPackage.CustomPasswordEncoder">
<property name="passwordFormatforBean" value="Hashed" />
</bean>
<bean id="userTokenCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager" ref="cacheManager" />
<property name="cacheName" value = "yourPackage.UserTokenCache"/>
</bean>
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml" />
</bean>
<bean id="userCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager" ref="cacheManager" />
<property name="cacheName" value="userCache" />
</bean>
<bean id="userCache" class="org.springframework.security.providers.dao.cache.EhCacheBasedUserCache">
<property name="cache">
<ref local="userCacheBackend" />
</property>
</bean>
</beans>