Initial commit.

This commit is contained in:
Ben Alex
2004-03-16 23:57:17 +00:00
commit 35fe1e7b73
267 changed files with 17812 additions and 0 deletions

View File

@@ -0,0 +1,107 @@
/*
* The Acegi Security System for Spring is published under the terms
* of the Apache Software License.
*
* Visit http://acegisecurity.sourceforge.net for further details.
*/
package sample.contact;
/**
* Represents a contact.
*
* <P>
* <code>id</code> and <code>owner</code> are immutable.
* </p>
*
* @author Ben Alex
* @version $Id$
*/
public class Contact {
//~ Instance fields ========================================================
private Integer id;
private String email;
private String name;
private String owner;
//~ Constructors ===========================================================
public Contact(Integer id, String name, String email, String owner) {
this.id = id;
this.name = name;
this.email = email;
this.owner = owner;
}
private Contact() {
super();
}
//~ Methods ================================================================
/**
* DOCUMENT ME!
*
* @param email The email to set.
*/
public void setEmail(String email) {
this.email = email;
}
/**
* DOCUMENT ME!
*
* @return Returns the email.
*/
public String getEmail() {
return email;
}
/**
* DOCUMENT ME!
*
* @return Returns the id.
*/
public Integer getId() {
return id;
}
/**
* DOCUMENT ME!
*
* @param name The name to set.
*/
public void setName(String name) {
this.name = name;
}
/**
* DOCUMENT ME!
*
* @return Returns the name.
*/
public String getName() {
return name;
}
/**
* DOCUMENT ME!
*
* @return Returns the owner.
*/
public String getOwner() {
return owner;
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(super.toString() + ": ");
sb.append("Id: " + this.getId() + "; ");
sb.append("Name: " + this.getName() + "; ");
sb.append("Email: " + this.getEmail() + "; ");
sb.append("Owner: " + this.getOwner());
return sb.toString();
}
}

View File

@@ -0,0 +1,30 @@
/*
* The Acegi Security System for Spring is published under the terms
* of the Apache Software License.
*
* Visit http://acegisecurity.sourceforge.net for further details.
*/
package sample.contact;
/**
* Iterface for the application's business object.
*
* @author Ben Alex
* @version $Id$
*/
public interface ContactManager {
//~ Methods ================================================================
public Contact[] getAllByOwner(String owner);
public Contact getById(Integer id);
public Integer getNextId();
public Contact getRandomContact();
public void delete(Contact contact);
public void save(Contact contact);
}

View File

@@ -0,0 +1,168 @@
/*
* The Acegi Security System for Spring is published under the terms
* of the Apache Software License.
*
* Visit http://acegisecurity.sourceforge.net for further details.
*/
package sample.contact;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Vector;
/**
* Backend business object that manages the contacts.
*
* <P>
* As a backend, it never faces the public callers. It is always accessed via
* the {@link ContactManagerFacade}.
* </p>
*
* <P>
* This facade approach is not really necessary in this application, and is
* done simply to demonstrate granting additional authorities via the
* <code>RunAsManager</code>.
* </p>
*
* @author Ben Alex
* @version $Id$
*/
public class ContactManagerBackend implements ContactManager {
//~ Instance fields ========================================================
private Map contacts;
//~ Constructors ===========================================================
public ContactManagerBackend() {
this.contacts = new HashMap();
save(new Contact(this.getNextId(), "John Smith", "john@somewhere.com",
"marissa"));
save(new Contact(this.getNextId(), "Michael Citizen",
"michael@xyz.com", "marissa"));
save(new Contact(this.getNextId(), "Joe Bloggs", "joe@demo.com",
"marissa"));
save(new Contact(this.getNextId(), "Karen Sutherland",
"karen@sutherland.com", "dianne"));
save(new Contact(this.getNextId(), "Mitchell Howard",
"mitchell@abcdef.com", "dianne"));
save(new Contact(this.getNextId(), "Rose Costas", "rose@xyz.com",
"scott"));
save(new Contact(this.getNextId(), "Amanda Smith", "amanda@abcdef.com",
"scott"));
}
//~ Methods ================================================================
/**
* Security system expects ROLE_RUN_AS_SERVER
*
* @param owner DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public Contact[] getAllByOwner(String owner) {
List list = new Vector();
Iterator iter = this.contacts.keySet().iterator();
while (iter.hasNext()) {
Integer contactId = (Integer) iter.next();
Contact contact = (Contact) this.contacts.get(contactId);
if (contact.getOwner().equals(owner)) {
list.add(contact);
}
}
Contact[] resultType = {new Contact(new Integer(1), "holder", "holder",
"holder")};
if (list.size() == 0) {
return null;
} else {
return (Contact[]) list.toArray(resultType);
}
}
/**
* Security system expects ROLE_RUN_AS_SERVER
*
* @param id DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public Contact getById(Integer id) {
return (Contact) this.contacts.get(id);
}
/**
* Public method
*
* @return DOCUMENT ME!
*/
public Integer getNextId() {
int max = 0;
Iterator iter = this.contacts.keySet().iterator();
while (iter.hasNext()) {
Integer id = (Integer) iter.next();
if (id.intValue() > max) {
max = id.intValue();
}
}
return new Integer(max + 1);
}
/**
* This is a public method, meaning a client could call this method
* directly (ie not via a facade). If this was an issue, the public method
* on the facade should not be public but secure. Quite possibly an
* AnonymousAuthenticationToken and associated provider could be used on a
* secure method, thus allowing a RunAsManager to protect the backend.
*
* @return DOCUMENT ME!
*/
public Contact getRandomContact() {
Random rnd = new Random();
int getNumber = rnd.nextInt(this.contacts.size()) + 1;
Iterator iter = this.contacts.keySet().iterator();
int i = 0;
while (iter.hasNext()) {
i++;
Integer id = (Integer) iter.next();
if (i == getNumber) {
return (Contact) this.contacts.get(id);
}
}
return null;
}
/**
* Security system expects ROLE_RUN_AS_SERVER
*
* @param contact DOCUMENT ME!
*/
public void delete(Contact contact) {
this.contacts.remove(contact.getId());
}
/**
* Security system expects ROLE_RUN_AS_SERVER
*
* @param contact DOCUMENT ME!
*/
public void save(Contact contact) {
this.contacts.put(contact.getId(), contact);
}
}

View File

@@ -0,0 +1,132 @@
/*
* The Acegi Security System for Spring is published under the terms
* of the Apache Software License.
*
* Visit http://acegisecurity.sourceforge.net for further details.
*/
package sample.contact;
import net.sf.acegisecurity.AccessDeniedException;
import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContext;
import org.springframework.beans.factory.InitializingBean;
/**
* This is the public facade to the application's main business object.
*
* <p>
* Used to demonstrate security configuration in a multi-tier application. Most
* methods of this class are secured via standard security definitions in the
* bean context. There is one method that supplements these security checks.
* All methods delegate to a "backend" object. The "backend" object relies on
* the facade's <code>RunAsManager</code> assigning an additional
* <code>GrantedAuthority</code> that is required to call its methods.
* </p>
*
* @author Ben Alex
* @version $Id$
*/
public class ContactManagerFacade implements ContactManager, InitializingBean {
//~ Instance fields ========================================================
private ContactManager backend;
//~ Methods ================================================================
/**
* Security system will ensure the owner parameter equals the currently
* logged in user.
*
* @param owner DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public Contact[] getAllByOwner(String owner) {
return backend.getAllByOwner(owner);
}
public void setBackend(ContactManager backend) {
this.backend = backend;
}
public ContactManager getBackend() {
return backend;
}
/**
* Security system will ensure logged in user has ROLE_TELLER.
*
* <p>
* Security system cannot ensure that only the owner can get the contact,
* as doing so would require it to specifically open the contact. Whilst
* possible, this would be expensive as the operation would be performed
* both by the security system as well as the implementation. Instead the
* facade will confirm the contact.getOwner() matches what is on the
* ContextHolder.
* </p>
*
* @param id DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws AccessDeniedException DOCUMENT ME!
*/
public Contact getById(Integer id) {
Contact result = backend.getById(id);
Authentication auth = ((SecureContext) ContextHolder.getContext())
.getAuthentication();
if (auth.getPrincipal().toString().equals(result.getOwner())) {
return result;
} else {
throw new AccessDeniedException("The requested id is not owned by the currently logged in user");
}
}
/**
* Public method.
*
* @return DOCUMENT ME!
*/
public Integer getNextId() {
return backend.getNextId();
}
/**
* Public method.
*
* @return DOCUMENT ME!
*/
public Contact getRandomContact() {
return backend.getRandomContact();
}
public void afterPropertiesSet() throws Exception {
if (backend == null) {
throw new IllegalArgumentException("A backend ContactManager implementation is required");
}
}
/**
* Security system will ensure logged in user has ROLE_SUPERVISOR.
*
* @param contact DOCUMENT ME!
*/
public void delete(Contact contact) {
backend.delete(contact);
}
/**
* Security system will ensure the owner specified via contact.getOwner()
* equals the currently logged in user.
*
* @param contact DOCUMENT ME!
*/
public void save(Contact contact) {
backend.save(contact);
}
}

View File

@@ -0,0 +1,87 @@
/*
* The Acegi Security System for Spring is published under the terms
* of the Apache Software License.
*
* Visit http://acegisecurity.sourceforge.net for further details.
*/
package sample.contact;
import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.ConfigAttribute;
import net.sf.acegisecurity.ConfigAttributeDefinition;
import net.sf.acegisecurity.vote.AccessDecisionVoter;
import org.aopalliance.intercept.MethodInvocation;
import java.util.Iterator;
/**
* Implementation of an {@link AccessDecisionVoter} that provides
* application-specific security for the Contact application.
*
* <p>
* If the {@link ConfigAttribute#getAttribute()} has a value of
* <code>CONTACT_OWNED_BY_CURRENT_USER</code>, the String or the
* Contact.getOwner() associated with the method call is compared with the
* Authentication.getPrincipal().toString() result. If it matches, the voter
* votes to grant access. If they do not match, it votes to deny access.
* </p>
*
* <p>
* All comparisons are case sensitive.
* </p>
*
* @author Ben Alex
* @version $Id$
*/
public class ContactSecurityVoter implements AccessDecisionVoter {
//~ Methods ================================================================
public boolean supports(ConfigAttribute attribute) {
if ("CONTACT_OWNED_BY_CURRENT_USER".equals(attribute.getAttribute())) {
return true;
} else {
return false;
}
}
public int vote(Authentication authentication, MethodInvocation invocation,
ConfigAttributeDefinition config) {
int result = ACCESS_ABSTAIN;
Iterator iter = config.getConfigAttributes();
while (iter.hasNext()) {
ConfigAttribute attribute = (ConfigAttribute) iter.next();
if (this.supports(attribute)) {
result = ACCESS_DENIED;
// Lookup the account number being passed
String passedOwner = null;
for (int i = 0; i < invocation.getArgumentCount(); i++) {
Class argClass = invocation.getArgument(i).getClass();
if (String.class.isAssignableFrom(argClass)) {
passedOwner = (String) invocation.getArgument(i);
} else if (Contact.class.isAssignableFrom(argClass)) {
passedOwner = ((Contact) invocation.getArgument(i))
.getOwner();
}
}
if (passedOwner != null) {
// Check the authentication principal matches the passed owner
if (passedOwner.equals(authentication.getPrincipal()
.toString())) {
return ACCESS_GRANTED;
}
}
}
}
return result;
}
}

View File

@@ -0,0 +1,58 @@
/*
* The Acegi Security System for Spring is published under the terms
* of the Apache Software License.
*
* Visit http://acegisecurity.sourceforge.net for further details.
*/
package sample.contact;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Controller to delete a contact page.
*
* @author Ben Alex
* @version $Id$
*/
public class DeleteController implements Controller, InitializingBean {
//~ Instance fields ========================================================
private ContactManager contactManager;
//~ Methods ================================================================
public void setContactManager(ContactManager contact) {
this.contactManager = contact;
}
public ContactManager getContactManager() {
return contactManager;
}
public void afterPropertiesSet() throws Exception {
if (contactManager == null) {
throw new IllegalArgumentException("A ContactManager implementation is required");
}
}
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
Integer id = new Integer(request.getParameter("id"));
Contact contact = contactManager.getById(id);
contactManager.delete(contact);
return new ModelAndView("deleted", "contact", contact);
}
}

View File

@@ -0,0 +1,56 @@
/*
* The Acegi Security System for Spring is published under the terms
* of the Apache Software License.
*
* Visit http://acegisecurity.sourceforge.net for further details.
*/
package sample.contact;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Controller for public index page (default web app home page).
*
* @author Ben Alex
* @version $Id$
*/
public class PublicIndexController implements Controller, InitializingBean {
//~ Instance fields ========================================================
private ContactManager contactManager;
//~ Methods ================================================================
public void setContactManager(ContactManager contact) {
this.contactManager = contact;
}
public ContactManager getContactManager() {
return contactManager;
}
public void afterPropertiesSet() throws Exception {
if (contactManager == null) {
throw new IllegalArgumentException("A ContactManager implementation is required");
}
}
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
Contact rnd = contactManager.getRandomContact();
return new ModelAndView("hello", "contact", rnd);
}
}

View File

@@ -0,0 +1,82 @@
/*
* The Acegi Security System for Spring is published under the terms
* of the Apache Software License.
*
* Visit http://acegisecurity.sourceforge.net for further details.
*/
package sample.contact;
import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContext;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Controller for secure index page.
*
* @author Ben Alex
* @version $Id$
*/
public class SecureIndexController implements Controller, InitializingBean {
//~ Instance fields ========================================================
private ContactManager contactManager;
//~ Methods ================================================================
public void setContactManager(ContactManager contact) {
this.contactManager = contact;
}
public ContactManager getContactManager() {
return contactManager;
}
public void afterPropertiesSet() throws Exception {
if (contactManager == null) {
throw new IllegalArgumentException("A ContactManager implementation is required");
}
}
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
Authentication currentUser = ((SecureContext) ContextHolder.getContext())
.getAuthentication();
boolean supervisor = false;
GrantedAuthority[] granted = currentUser.getAuthorities();
for (int i = 0; i < granted.length; i++) {
if (granted[i].getAuthority().equals("ROLE_SUPERVISOR")) {
supervisor = true;
}
}
Contact[] myContacts = contactManager.getAllByOwner(currentUser.getPrincipal()
.toString());
Map model = new HashMap();
model.put("contacts", myContacts);
model.put("supervisor", new Boolean(supervisor));
model.put("user", currentUser.getPrincipal().toString());
return new ModelAndView("index", "model", model);
}
}

View File

@@ -0,0 +1,39 @@
/*
* The Acegi Security System for Spring is published under the terms
* of the Apache Software License.
*
* Visit http://acegisecurity.sourceforge.net for further details.
*/
package sample.contact;
/**
* An object that represents user-editable sections of a {@link Contact}.
*
* @author Ben Alex
* @version $Id$
*/
public class WebContact {
//~ Instance fields ========================================================
private String email;
private String name;
//~ Methods ================================================================
public void setEmail(String email) {
this.email = email;
}
public String getEmail() {
return email;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}

View File

@@ -0,0 +1,68 @@
/*
* The Acegi Security System for Spring is published under the terms
* of the Apache Software License.
*
* Visit http://acegisecurity.sourceforge.net for further details.
*/
package sample.contact;
import net.sf.acegisecurity.context.ContextHolder;
import net.sf.acegisecurity.context.SecureContext;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;
import org.springframework.web.servlet.view.RedirectView;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
/**
* Controller for adding a new contact.
*
* @author Ben Alex
* @version $Id$
*/
public class WebContactAddController extends SimpleFormController {
//~ Instance fields ========================================================
private ContactManager contactManager;
//~ Methods ================================================================
public void setContactManager(ContactManager contactManager) {
this.contactManager = contactManager;
}
public ContactManager getContactManager() {
return contactManager;
}
public ModelAndView onSubmit(Object command) throws ServletException {
String name = ((WebContact) command).getName();
String email = ((WebContact) command).getEmail();
String owner = ((SecureContext) ContextHolder.getContext()).getAuthentication()
.getPrincipal().toString();
Contact contact = new Contact(contactManager.getNextId(), name, email,
owner);
contactManager.save(contact);
Map myModel = new HashMap();
myModel.put("now", new Date());
return new ModelAndView(new RedirectView(getSuccessView()));
}
protected Object formBackingObject(HttpServletRequest request)
throws ServletException {
WebContact wc = new WebContact();
return wc;
}
}

View File

@@ -0,0 +1,38 @@
/*
* The Acegi Security System for Spring is published under the terms
* of the Apache Software License.
*
* Visit http://acegisecurity.sourceforge.net for further details.
*/
package sample.contact;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
/**
* Validates {@link WebContact}.
*
* @author Ben Alex
* @version $Id$
*/
public class WebContactValidator implements Validator {
//~ Methods ================================================================
public boolean supports(Class clazz) {
return clazz.equals(WebContact.class);
}
public void validate(Object obj, Errors errors) {
WebContact wc = (WebContact) obj;
if ((wc.getName() == null) || (wc.getName().length() < 3)) {
errors.rejectValue("name", "not-used", null, "Name is required.");
}
if ((wc.getEmail() == null) || (wc.getEmail().length() < 3)) {
errors.rejectValue("email", "not-used", null, "Email is required.");
}
}
}