Refactor Contacts Sample to use new ACL security.
This commit is contained in:
parent
bc9a599bf7
commit
6e687d47d4
|
@ -2,6 +2,7 @@ Changes in version 0.7 (2004-xx-xx)
|
|||
-----------------------------------
|
||||
|
||||
* Major CVS repository restructure to support Maven and eliminate libraries
|
||||
* Major improvements to Contacts sample application (now demos ACL security)
|
||||
* Added AspectJ support (especially useful for instance-level security)
|
||||
* Added MethodDefinitionSourceAdvisor for performance and autoproxying
|
||||
* Added MethodDefinitionMap querying of interfaces defined by secure objects
|
||||
|
@ -11,7 +12,8 @@ Changes in version 0.7 (2004-xx-xx)
|
|||
* Improved BasicAclProvider to only respond to specified ACL object requests
|
||||
* Refactored MethodDefinitionSource to work with Method, not MethodInvocation
|
||||
* Refactored AbstractSecurityInterceptor to better support other AOP libraries
|
||||
* Fixed AbstractProcessingFitler to use removeAttribute (JRun compatibility)
|
||||
* Fixed AbstractProcessingFilter to use removeAttribute (JRun compatibility)
|
||||
* Fixed GrantedAuthorityEffectiveAclResolver support of UserDetails principals
|
||||
* Moved MethodSecurityInterceptor to ...intercept.method.aopalliance package
|
||||
* Documentation improvements
|
||||
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sample.contact;
|
||||
|
||||
import net.sf.acegisecurity.acl.basic.SimpleAclEntry;
|
||||
|
||||
|
||||
/**
|
||||
* Model object for add permission use case.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AddPermission {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
public Contact contact;
|
||||
public Integer permission = new Integer(SimpleAclEntry.NOTHING);
|
||||
public String recipient;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void setContact(Contact contact) {
|
||||
this.contact = contact;
|
||||
}
|
||||
|
||||
public Contact getContact() {
|
||||
return contact;
|
||||
}
|
||||
|
||||
public void setPermission(Integer permission) {
|
||||
this.permission = permission;
|
||||
}
|
||||
|
||||
public Integer getPermission() {
|
||||
return permission;
|
||||
}
|
||||
|
||||
public void setRecipient(String recipient) {
|
||||
this.recipient = recipient;
|
||||
}
|
||||
|
||||
public String getRecipient() {
|
||||
return recipient;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sample.contact;
|
||||
|
||||
import net.sf.acegisecurity.acl.basic.SimpleAclEntry;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
import org.springframework.validation.BindException;
|
||||
|
||||
import org.springframework.web.bind.RequestUtils;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.mvc.SimpleFormController;
|
||||
import org.springframework.web.servlet.view.RedirectView;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
||||
/**
|
||||
* Controller for adding an ACL permission.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AddPermissionController extends SimpleFormController
|
||||
implements 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");
|
||||
}
|
||||
}
|
||||
|
||||
protected ModelAndView disallowDuplicateFormSubmission(
|
||||
HttpServletRequest request, HttpServletResponse response)
|
||||
throws Exception {
|
||||
BindException errors = new BindException(formBackingObject(request),
|
||||
getCommandName());
|
||||
errors.reject("err.duplicateFormSubmission",
|
||||
"Duplicate form submission.");
|
||||
|
||||
return showForm(request, response, errors);
|
||||
}
|
||||
|
||||
protected Object formBackingObject(HttpServletRequest request)
|
||||
throws Exception {
|
||||
int contactId = RequestUtils.getRequiredIntParameter(request,
|
||||
"contactId");
|
||||
|
||||
Contact contact = contactManager.getById(new Integer(contactId));
|
||||
|
||||
AddPermission addPermission = new AddPermission();
|
||||
addPermission.setContact(contact);
|
||||
|
||||
return addPermission;
|
||||
}
|
||||
|
||||
protected ModelAndView handleInvalidSubmit(HttpServletRequest request,
|
||||
HttpServletResponse response) throws Exception {
|
||||
return disallowDuplicateFormSubmission(request, response);
|
||||
}
|
||||
|
||||
protected ModelAndView onSubmit(HttpServletRequest request,
|
||||
HttpServletResponse response, Object command, BindException errors)
|
||||
throws Exception {
|
||||
AddPermission addPermission = (AddPermission) command;
|
||||
|
||||
try {
|
||||
contactManager.addPermission(addPermission.getContact(),
|
||||
addPermission.getRecipient(), addPermission.getPermission());
|
||||
} catch (DataAccessException existingPermission) {
|
||||
existingPermission.printStackTrace();
|
||||
errors.rejectValue("recipient", "err.recipientExistsForContact",
|
||||
"This recipient already has permissions to this contact.");
|
||||
|
||||
return showForm(request, response, errors);
|
||||
}
|
||||
|
||||
return new ModelAndView(new RedirectView(getSuccessView()));
|
||||
}
|
||||
|
||||
protected Map referenceData(HttpServletRequest request)
|
||||
throws Exception {
|
||||
Map model = new HashMap();
|
||||
model.put("recipients", listRecipients(request));
|
||||
model.put("permissions", listPermissions(request));
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
private Map listPermissions(HttpServletRequest request) {
|
||||
Map map = new LinkedHashMap();
|
||||
map.put(new Integer(SimpleAclEntry.NOTHING),
|
||||
getApplicationContext().getMessage("select.none", null, "None",
|
||||
request.getLocale()));
|
||||
map.put(new Integer(SimpleAclEntry.ADMINISTRATION),
|
||||
getApplicationContext().getMessage("select.administer", null,
|
||||
"Administer", request.getLocale()));
|
||||
map.put(new Integer(SimpleAclEntry.READ),
|
||||
getApplicationContext().getMessage("select.read", null, "Read",
|
||||
request.getLocale()));
|
||||
map.put(new Integer(SimpleAclEntry.DELETE),
|
||||
getApplicationContext().getMessage("select.delete", null, "Delete",
|
||||
request.getLocale()));
|
||||
map.put(new Integer(SimpleAclEntry.READ_WRITE_DELETE),
|
||||
getApplicationContext().getMessage("select.readWriteDelete", null,
|
||||
"Read+Write+Delete", request.getLocale()));
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
private Map listRecipients(HttpServletRequest request) {
|
||||
Map map = new LinkedHashMap();
|
||||
map.put("",
|
||||
getApplicationContext().getMessage("select.pleaseSelect", null,
|
||||
"-- please select --", request.getLocale()));
|
||||
|
||||
Iterator recipientsIter = contactManager.getAllRecipients().iterator();
|
||||
|
||||
while (recipientsIter.hasNext()) {
|
||||
String recipient = (String) recipientsIter.next();
|
||||
map.put(recipient, recipient);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sample.contact;
|
||||
|
||||
import net.sf.acegisecurity.acl.basic.SimpleAclEntry;
|
||||
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.validation.ValidationUtils;
|
||||
import org.springframework.validation.Validator;
|
||||
|
||||
|
||||
/**
|
||||
* Validates {@link AddPermission}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AddPermissionValidator implements Validator {
|
||||
//~ Methods ================================================================
|
||||
|
||||
public boolean supports(Class clazz) {
|
||||
return clazz.equals(AddPermission.class);
|
||||
}
|
||||
|
||||
public void validate(Object obj, Errors errors) {
|
||||
AddPermission addPermission = (AddPermission) obj;
|
||||
|
||||
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "permission",
|
||||
"err.permission", "Permission is required");
|
||||
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "recipient",
|
||||
"err.recipient", "Recipient is required");
|
||||
|
||||
if (addPermission.getPermission() != null) {
|
||||
int permission = addPermission.getPermission().intValue();
|
||||
|
||||
if ((permission != SimpleAclEntry.NOTHING)
|
||||
&& (permission != SimpleAclEntry.ADMINISTRATION)
|
||||
&& (permission != SimpleAclEntry.READ)
|
||||
&& (permission != SimpleAclEntry.DELETE)
|
||||
&& (permission != SimpleAclEntry.READ_WRITE_DELETE)) {
|
||||
errors.rejectValue("permission", "err.permission.invalid",
|
||||
"The indicated permission is invalid.");
|
||||
}
|
||||
}
|
||||
|
||||
if (addPermission.getRecipient() != null) {
|
||||
if (addPermission.getRecipient().length() > 100) {
|
||||
errors.rejectValue("recipient", "err.recipient.length",
|
||||
"The recipient is too long (maximum 100 characters).");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sample.contact;
|
||||
|
||||
import net.sf.acegisecurity.acl.AclEntry;
|
||||
import net.sf.acegisecurity.acl.AclManager;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.web.bind.RequestUtils;
|
||||
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 "administer" index page.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AdminPermissionController implements Controller, InitializingBean {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private AclManager aclManager;
|
||||
private ContactManager contactManager;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void setAclManager(AclManager aclManager) {
|
||||
this.aclManager = aclManager;
|
||||
}
|
||||
|
||||
public AclManager getAclManager() {
|
||||
return aclManager;
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
if (aclManager == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"An aclManager implementation is required");
|
||||
}
|
||||
}
|
||||
|
||||
public ModelAndView handleRequest(HttpServletRequest request,
|
||||
HttpServletResponse response) throws ServletException, IOException {
|
||||
int id = RequestUtils.getRequiredIntParameter(request, "contactId");
|
||||
|
||||
Contact contact = contactManager.getById(new Integer(id));
|
||||
AclEntry[] acls = aclManager.getAcls(contact);
|
||||
|
||||
Map model = new HashMap();
|
||||
model.put("contact", contact);
|
||||
model.put("acls", acls);
|
||||
|
||||
return new ModelAndView("adminPermission", "model", model);
|
||||
}
|
||||
}
|
|
@ -25,12 +25,13 @@ import java.lang.reflect.InvocationTargetException;
|
|||
import java.lang.reflect.Method;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* Demonstrates accessing the {@link ContactManager} via remoting protocols.
|
||||
*
|
||||
*
|
||||
* <P>
|
||||
* Based on Spring's JPetStore sample, written by Juergen Hoeller.
|
||||
* </p>
|
||||
|
@ -92,32 +93,34 @@ public class ClientApplication {
|
|||
System.out.println("Found; Trying to setPassword(String) to "
|
||||
+ password);
|
||||
} catch (NoSuchMethodException ignored) {}
|
||||
catch (IllegalAccessException ignored) {}
|
||||
catch (InvocationTargetException ignored) {}
|
||||
catch (IllegalAccessException ignored) {}
|
||||
catch (InvocationTargetException ignored) {}
|
||||
|
||||
stopWatch.start(beanName);
|
||||
|
||||
Contact[] contacts = null;
|
||||
List contacts = null;
|
||||
|
||||
for (int i = 0; i < nrOfCalls; i++) {
|
||||
contacts = remoteContactManager.getAllByOwner(forOwner);
|
||||
contacts = remoteContactManager.getAll();
|
||||
}
|
||||
|
||||
stopWatch.stop();
|
||||
|
||||
if (contacts.length != 0) {
|
||||
for (int i = 0; i < contacts.length; i++) {
|
||||
System.out.println("Contact " + i + ": "
|
||||
+ contacts[i].toString());
|
||||
if (contacts.size() == 0) {
|
||||
Iterator listIterator = contacts.iterator();
|
||||
|
||||
while (listIterator.hasNext()) {
|
||||
Contact contact = (Contact) listIterator.next();
|
||||
System.out.println("Contact: " + contact.toString());
|
||||
}
|
||||
} else {
|
||||
System.out.println("No contacts found belonging to owner");
|
||||
System.out.println(
|
||||
"No contacts found which this user has permission to");
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println(stopWatch.prettyPrint());
|
||||
}
|
||||
|
||||
System.out.println(stopWatch.prettyPrint());
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
|
|
@ -17,10 +17,6 @@ package sample.contact;
|
|||
|
||||
/**
|
||||
* Represents a contact.
|
||||
*
|
||||
* <P>
|
||||
* <code>id</code> and <code>owner</code> are immutable.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
|
@ -31,20 +27,15 @@ public class Contact {
|
|||
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;
|
||||
public Contact(String name, String email) {
|
||||
this.name = name;
|
||||
this.email = email;
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
private Contact() {
|
||||
super();
|
||||
}
|
||||
public Contact() {}
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
|
@ -66,6 +57,10 @@ public class Contact {
|
|||
return email;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
|
@ -93,22 +88,12 @@ public class Contact {
|
|||
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());
|
||||
sb.append("Email: " + this.getEmail());
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sample.contact;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Provides access to the application's persistence layer.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface ContactDao {
|
||||
//~ Methods ================================================================
|
||||
|
||||
public Contact getById(Integer id);
|
||||
|
||||
public void create(Contact contact);
|
||||
|
||||
/**
|
||||
* Creates an acl_object_identity for the specified Contact.
|
||||
*
|
||||
* @param contact to create an entry for
|
||||
*
|
||||
* @return the acl_object_identity identifier
|
||||
*/
|
||||
public Integer createAclObjectIdentity(Contact contact);
|
||||
|
||||
/**
|
||||
* Given an acl_object_identitiy identifier, grant the specified recipient
|
||||
* read access to the object identified.
|
||||
*
|
||||
* @param aclObjectIdentity to assign the read permission against
|
||||
* @param recipient receiving the permission
|
||||
* @param permission to assign
|
||||
*/
|
||||
public void createPermission(Integer aclObjectIdentity, String recipient,
|
||||
int permission);
|
||||
|
||||
public void delete(Integer contactId);
|
||||
|
||||
public void deletePermission(Integer aclObjectIdentity, String recipient);
|
||||
|
||||
public List findAll();
|
||||
|
||||
public List findAllPrincipals();
|
||||
|
||||
public List findAllRoles();
|
||||
|
||||
/**
|
||||
* Obtains the acl_object_identity for the specified Contact.
|
||||
*
|
||||
* @param contact to locate an acl_object_identity for
|
||||
*
|
||||
* @return the acl_object_identity identifier or <code>null</code> if not
|
||||
* found
|
||||
*/
|
||||
public Integer lookupAclObjectIdentity(Contact contact);
|
||||
|
||||
public void update(Contact contact);
|
||||
}
|
|
@ -0,0 +1,309 @@
|
|||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sample.contact;
|
||||
|
||||
import net.sf.acegisecurity.acl.basic.SimpleAclEntry;
|
||||
|
||||
import org.springframework.jdbc.core.SqlParameter;
|
||||
import org.springframework.jdbc.core.support.JdbcDaoSupport;
|
||||
import org.springframework.jdbc.object.MappingSqlQuery;
|
||||
import org.springframework.jdbc.object.SqlUpdate;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
|
||||
/**
|
||||
* Base implementation of {@link ContactDao} that uses Spring JDBC services.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ContactDaoSpring extends JdbcDaoSupport implements ContactDao {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private AclObjectIdentityByObjectIdentityQuery aclObjectIdentityByObjectIdentityQuery;
|
||||
private AclObjectIdentityInsert aclObjectIdentityInsert;
|
||||
private ContactDelete contactDelete;
|
||||
private ContactInsert contactInsert;
|
||||
private ContactUpdate contactUpdate;
|
||||
private ContactsAllQuery contactsAllQuery;
|
||||
private ContactsByIdQuery contactsByIdQuery;
|
||||
private PermissionDelete permissionDelete;
|
||||
private PermissionInsert permissionInsert;
|
||||
private PrincipalsAllQuery principalsAllQuery;
|
||||
private RolesAllQuery rolesAllQuery;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public Contact getById(Integer id) {
|
||||
List list = contactsByIdQuery.execute(id.intValue());
|
||||
|
||||
if (list.size() == 0) {
|
||||
return null;
|
||||
} else {
|
||||
return (Contact) list.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void create(Contact contact) {
|
||||
contactInsert.insert(contact);
|
||||
}
|
||||
|
||||
public Integer createAclObjectIdentity(Contact contact) {
|
||||
return new Integer(aclObjectIdentityInsert.insert(makeObjectIdentity(
|
||||
contact), null, SimpleAclEntry.class.getName()));
|
||||
}
|
||||
|
||||
public void createPermission(Integer aclObjectIdentity, String recipient,
|
||||
int permission) {
|
||||
permissionInsert.insert(aclObjectIdentity, recipient,
|
||||
new Integer(permission));
|
||||
}
|
||||
|
||||
public void delete(Integer contactId) {
|
||||
contactDelete.delete(contactId);
|
||||
}
|
||||
|
||||
public void deletePermission(Integer aclObjectIdentity, String recipient) {
|
||||
permissionDelete.delete(aclObjectIdentity, recipient);
|
||||
}
|
||||
|
||||
public List findAll() {
|
||||
return contactsAllQuery.execute();
|
||||
}
|
||||
|
||||
public List findAllPrincipals() {
|
||||
return principalsAllQuery.execute();
|
||||
}
|
||||
|
||||
public List findAllRoles() {
|
||||
return rolesAllQuery.execute();
|
||||
}
|
||||
|
||||
public Integer lookupAclObjectIdentity(Contact contact) {
|
||||
List list = aclObjectIdentityByObjectIdentityQuery.execute(makeObjectIdentity(
|
||||
contact));
|
||||
|
||||
if (list.size() == 0) {
|
||||
return null;
|
||||
} else {
|
||||
return (Integer) list.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void update(Contact contact) {
|
||||
contactUpdate.update(contact);
|
||||
}
|
||||
|
||||
protected void initDao() throws Exception {
|
||||
contactInsert = new ContactInsert(getDataSource());
|
||||
contactUpdate = new ContactUpdate(getDataSource());
|
||||
contactDelete = new ContactDelete(getDataSource());
|
||||
aclObjectIdentityInsert = new AclObjectIdentityInsert(getDataSource());
|
||||
permissionInsert = new PermissionInsert(getDataSource());
|
||||
permissionDelete = new PermissionDelete(getDataSource());
|
||||
contactsAllQuery = new ContactsAllQuery(getDataSource());
|
||||
principalsAllQuery = new PrincipalsAllQuery(getDataSource());
|
||||
rolesAllQuery = new RolesAllQuery(getDataSource());
|
||||
contactsByIdQuery = new ContactsByIdQuery(getDataSource());
|
||||
aclObjectIdentityByObjectIdentityQuery = new AclObjectIdentityByObjectIdentityQuery(getDataSource());
|
||||
}
|
||||
|
||||
private String makeObjectIdentity(Contact contact) {
|
||||
return contact.getClass().getName() + ":" + contact.getId();
|
||||
}
|
||||
|
||||
//~ Inner Classes ==========================================================
|
||||
|
||||
protected class AclObjectIdentityByObjectIdentityQuery
|
||||
extends MappingSqlQuery {
|
||||
protected AclObjectIdentityByObjectIdentityQuery(DataSource ds) {
|
||||
super(ds,
|
||||
"SELECT id FROM acl_object_identity WHERE object_identity = ?");
|
||||
declareParameter(new SqlParameter(Types.VARCHAR));
|
||||
compile();
|
||||
}
|
||||
|
||||
protected Object mapRow(ResultSet rs, int rownum)
|
||||
throws SQLException {
|
||||
return new Integer(rs.getInt("id"));
|
||||
}
|
||||
}
|
||||
|
||||
protected class AclObjectIdentityInsert extends SqlUpdate {
|
||||
protected AclObjectIdentityInsert(DataSource ds) {
|
||||
super(ds, "INSERT INTO acl_object_identity VALUES (?, ?, ?, ?)");
|
||||
declareParameter(new SqlParameter(Types.INTEGER));
|
||||
declareParameter(new SqlParameter(Types.VARCHAR));
|
||||
declareParameter(new SqlParameter(Types.INTEGER));
|
||||
declareParameter(new SqlParameter(Types.VARCHAR));
|
||||
compile();
|
||||
}
|
||||
|
||||
protected int insert(String objectIdentity,
|
||||
Integer parentAclObjectIdentity, String aclClass) {
|
||||
Object[] objs = new Object[] {null, objectIdentity, parentAclObjectIdentity, aclClass};
|
||||
super.update(objs);
|
||||
|
||||
return getJdbcTemplate().queryForInt("call identity()");
|
||||
}
|
||||
}
|
||||
|
||||
protected class ContactDelete extends SqlUpdate {
|
||||
protected ContactDelete(DataSource ds) {
|
||||
super(ds, "DELETE FROM contacts WHERE id = ?");
|
||||
declareParameter(new SqlParameter(Types.INTEGER));
|
||||
compile();
|
||||
}
|
||||
|
||||
protected void delete(Integer contactId) {
|
||||
super.update(contactId.intValue());
|
||||
}
|
||||
}
|
||||
|
||||
protected class ContactInsert extends SqlUpdate {
|
||||
protected ContactInsert(DataSource ds) {
|
||||
super(ds, "INSERT INTO contacts VALUES (?, ?, ?)");
|
||||
declareParameter(new SqlParameter(Types.INTEGER));
|
||||
declareParameter(new SqlParameter(Types.VARCHAR));
|
||||
declareParameter(new SqlParameter(Types.VARCHAR));
|
||||
compile();
|
||||
}
|
||||
|
||||
protected void insert(Contact contact) {
|
||||
Object[] objs = new Object[] {contact.getId(), contact.getName(), contact
|
||||
.getEmail()};
|
||||
super.update(objs);
|
||||
}
|
||||
}
|
||||
|
||||
protected class ContactUpdate extends SqlUpdate {
|
||||
protected ContactUpdate(DataSource ds) {
|
||||
super(ds,
|
||||
"UPDATE contacts SET contact_name = ?, address = ? WHERE id = ?");
|
||||
declareParameter(new SqlParameter(Types.VARCHAR));
|
||||
declareParameter(new SqlParameter(Types.VARCHAR));
|
||||
declareParameter(new SqlParameter(Types.INTEGER));
|
||||
compile();
|
||||
}
|
||||
|
||||
protected void update(Contact contact) {
|
||||
Object[] objs = new Object[] {contact.getName(), contact.getEmail(), contact
|
||||
.getId()};
|
||||
super.update(objs);
|
||||
}
|
||||
}
|
||||
|
||||
protected class ContactsAllQuery extends MappingSqlQuery {
|
||||
protected ContactsAllQuery(DataSource ds) {
|
||||
super(ds, "SELECT id, contact_name, email FROM contacts ORDER BY id");
|
||||
compile();
|
||||
}
|
||||
|
||||
protected Object mapRow(ResultSet rs, int rownum)
|
||||
throws SQLException {
|
||||
Contact contact = new Contact();
|
||||
contact.setId(new Integer(rs.getInt("id")));
|
||||
contact.setName(rs.getString("contact_name"));
|
||||
contact.setEmail(rs.getString("email"));
|
||||
|
||||
return contact;
|
||||
}
|
||||
}
|
||||
|
||||
protected class ContactsByIdQuery extends MappingSqlQuery {
|
||||
protected ContactsByIdQuery(DataSource ds) {
|
||||
super(ds,
|
||||
"SELECT id, contact_name, email FROM contacts WHERE id = ? ORDER BY id");
|
||||
declareParameter(new SqlParameter(Types.INTEGER));
|
||||
compile();
|
||||
}
|
||||
|
||||
protected Object mapRow(ResultSet rs, int rownum)
|
||||
throws SQLException {
|
||||
Contact contact = new Contact();
|
||||
contact.setId(new Integer(rs.getInt("id")));
|
||||
contact.setName(rs.getString("contact_name"));
|
||||
contact.setEmail(rs.getString("email"));
|
||||
|
||||
return contact;
|
||||
}
|
||||
}
|
||||
|
||||
protected class PermissionDelete extends SqlUpdate {
|
||||
protected PermissionDelete(DataSource ds) {
|
||||
super(ds,
|
||||
"DELETE FROM acl_permission WHERE ACL_OBJECT_IDENTITY = ? AND RECIPIENT = ?");
|
||||
declareParameter(new SqlParameter(Types.INTEGER));
|
||||
declareParameter(new SqlParameter(Types.VARCHAR));
|
||||
compile();
|
||||
}
|
||||
|
||||
protected void delete(Integer aclObjectIdentity, String recipient) {
|
||||
super.update(new Object[] {aclObjectIdentity, recipient});
|
||||
}
|
||||
}
|
||||
|
||||
protected class PermissionInsert extends SqlUpdate {
|
||||
protected PermissionInsert(DataSource ds) {
|
||||
super(ds, "INSERT INTO acl_permission VALUES (?, ?, ?, ?);");
|
||||
declareParameter(new SqlParameter(Types.INTEGER));
|
||||
declareParameter(new SqlParameter(Types.INTEGER));
|
||||
declareParameter(new SqlParameter(Types.VARCHAR));
|
||||
declareParameter(new SqlParameter(Types.INTEGER));
|
||||
compile();
|
||||
}
|
||||
|
||||
protected int insert(Integer aclObjectIdentity, String recipient,
|
||||
Integer mask) {
|
||||
Object[] objs = new Object[] {null, aclObjectIdentity, recipient, mask};
|
||||
super.update(objs);
|
||||
|
||||
return getJdbcTemplate().queryForInt("call identity()");
|
||||
}
|
||||
}
|
||||
|
||||
protected class PrincipalsAllQuery extends MappingSqlQuery {
|
||||
protected PrincipalsAllQuery(DataSource ds) {
|
||||
super(ds, "SELECT username FROM users ORDER BY username");
|
||||
compile();
|
||||
}
|
||||
|
||||
protected Object mapRow(ResultSet rs, int rownum)
|
||||
throws SQLException {
|
||||
return rs.getString("username");
|
||||
}
|
||||
}
|
||||
|
||||
protected class RolesAllQuery extends MappingSqlQuery {
|
||||
protected RolesAllQuery(DataSource ds) {
|
||||
super(ds,
|
||||
"SELECT DISTINCT authority FROM authorities ORDER BY authority");
|
||||
compile();
|
||||
}
|
||||
|
||||
protected Object mapRow(ResultSet rs, int rownum)
|
||||
throws SQLException {
|
||||
return rs.getString("authority");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,8 +15,11 @@
|
|||
|
||||
package sample.contact;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Iterface for the application's business object.
|
||||
* Interface for the application's services layer.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
|
@ -24,15 +27,20 @@ package sample.contact;
|
|||
public interface ContactManager {
|
||||
//~ Methods ================================================================
|
||||
|
||||
public Contact[] getAllByOwner(String owner);
|
||||
public List getAll();
|
||||
|
||||
public List getAllRecipients();
|
||||
|
||||
public Contact getById(Integer id);
|
||||
|
||||
public Integer getNextId();
|
||||
|
||||
public Contact getRandomContact();
|
||||
|
||||
public void addPermission(Contact contact, String recipient,
|
||||
Integer permission);
|
||||
|
||||
public void create(Contact contact);
|
||||
|
||||
public void delete(Contact contact);
|
||||
|
||||
public void save(Contact contact);
|
||||
public void deletePermission(Contact contact, String recipient);
|
||||
}
|
||||
|
|
|
@ -15,159 +15,105 @@
|
|||
|
||||
package sample.contact;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import net.sf.acegisecurity.acl.basic.SimpleAclEntry;
|
||||
import net.sf.acegisecurity.context.ContextHolder;
|
||||
import net.sf.acegisecurity.context.SecureContext;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
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>
|
||||
* Concrete implementation of {@link ContactManager}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ContactManagerBackend implements ContactManager {
|
||||
public class ContactManagerBackend implements ContactManager, InitializingBean {
|
||||
//~ 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"));
|
||||
}
|
||||
private ContactDao contactDao;
|
||||
private int counter = 100;
|
||||
|
||||
//~ 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);
|
||||
}
|
||||
}
|
||||
|
||||
if (list.size() == 0) {
|
||||
return null;
|
||||
} else {
|
||||
return (Contact[]) list.toArray(new Contact[list.size()]);
|
||||
}
|
||||
public List getAll() {
|
||||
return contactDao.findAll();
|
||||
}
|
||||
|
||||
public List getAllRecipients() {
|
||||
List list = contactDao.findAllPrincipals();
|
||||
list.addAll(contactDao.findAllRoles());
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
return contactDao.getById(id);
|
||||
}
|
||||
|
||||
public void setContactDao(ContactDao contactDao) {
|
||||
this.contactDao = contactDao;
|
||||
}
|
||||
|
||||
public ContactDao getContactDao() {
|
||||
return contactDao;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* This is a public method.
|
||||
*
|
||||
* @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;
|
||||
List contacts = contactDao.findAll();
|
||||
int getNumber = rnd.nextInt(contacts.size());
|
||||
|
||||
while (iter.hasNext()) {
|
||||
i++;
|
||||
return (Contact) contacts.get(getNumber);
|
||||
}
|
||||
|
||||
Integer id = (Integer) iter.next();
|
||||
public void addPermission(Contact contact, String recipient,
|
||||
Integer permission) {
|
||||
Integer aclObjectIdentity = contactDao.lookupAclObjectIdentity(contact);
|
||||
contactDao.createPermission(aclObjectIdentity, recipient,
|
||||
permission.intValue());
|
||||
}
|
||||
|
||||
if (i == getNumber) {
|
||||
return (Contact) this.contacts.get(id);
|
||||
}
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (contactDao == null) {
|
||||
throw new IllegalArgumentException("contactDao required");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Security system expects ROLE_RUN_AS_SERVER
|
||||
*
|
||||
* @param contact DOCUMENT ME!
|
||||
*/
|
||||
public void create(Contact contact) {
|
||||
// Create the Contact itself
|
||||
contact.setId(new Integer(counter++));
|
||||
contactDao.create(contact);
|
||||
|
||||
// Grant the current principal access to the contact
|
||||
Integer aclObjectIdentity = contactDao.createAclObjectIdentity(contact);
|
||||
contactDao.createPermission(aclObjectIdentity, getUsername(),
|
||||
SimpleAclEntry.ADMINISTRATION);
|
||||
}
|
||||
|
||||
public void delete(Contact contact) {
|
||||
this.contacts.remove(contact.getId());
|
||||
contactDao.delete(contact.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Security system expects ROLE_RUN_AS_SERVER
|
||||
*
|
||||
* @param contact DOCUMENT ME!
|
||||
*/
|
||||
public void save(Contact contact) {
|
||||
this.contacts.put(contact.getId(), contact);
|
||||
public void deletePermission(Contact contact, String recipient) {
|
||||
Integer aclObjectIdentity = contactDao.lookupAclObjectIdentity(contact);
|
||||
contactDao.deletePermission(aclObjectIdentity, recipient);
|
||||
}
|
||||
|
||||
public void update(Contact contact) {
|
||||
contactDao.update(contact);
|
||||
}
|
||||
|
||||
protected String getUsername() {
|
||||
return ((SecureContext) ContextHolder.getContext()).getAuthentication()
|
||||
.getPrincipal().toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,149 +0,0 @@
|
|||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sample.contact;
|
||||
|
||||
import net.sf.acegisecurity.AccessDeniedException;
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.UserDetails;
|
||||
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();
|
||||
|
||||
String username = auth.getPrincipal().toString();
|
||||
|
||||
if (auth.getPrincipal() instanceof UserDetails) {
|
||||
username = ((UserDetails) auth.getPrincipal()).getUsername();
|
||||
}
|
||||
|
||||
if (username.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);
|
||||
}
|
||||
}
|
|
@ -1,117 +0,0 @@
|
|||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sample.contact;
|
||||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.ConfigAttribute;
|
||||
import net.sf.acegisecurity.ConfigAttributeDefinition;
|
||||
import net.sf.acegisecurity.UserDetails;
|
||||
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 boolean supports(Class clazz) {
|
||||
if (MethodInvocation.class.isAssignableFrom(clazz)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int vote(Authentication authentication, Object object,
|
||||
ConfigAttributeDefinition config) {
|
||||
if ((object == null) || !this.supports(object.getClass())) {
|
||||
throw new IllegalArgumentException(
|
||||
"Does not support the presented Object type");
|
||||
}
|
||||
|
||||
MethodInvocation invocation = (MethodInvocation) object;
|
||||
|
||||
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.getArguments().length; i++) {
|
||||
Class argClass = invocation.getArguments()[i].getClass();
|
||||
|
||||
if (String.class.isAssignableFrom(argClass)) {
|
||||
passedOwner = (String) invocation.getArguments()[i];
|
||||
} else if (Contact.class.isAssignableFrom(argClass)) {
|
||||
passedOwner = ((Contact) invocation.getArguments()[i])
|
||||
.getOwner();
|
||||
}
|
||||
}
|
||||
|
||||
if (passedOwner != null) {
|
||||
String username = authentication.getPrincipal().toString();
|
||||
|
||||
if (authentication.getPrincipal() instanceof UserDetails) {
|
||||
username = ((UserDetails) authentication.getPrincipal())
|
||||
.getUsername();
|
||||
}
|
||||
|
||||
// Check the authentication principal matches the passed owner
|
||||
if (passedOwner.equals(username)) {
|
||||
return ACCESS_GRANTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sample.contact;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
|
||||
/**
|
||||
* Populates the Contacts in-memory database with contact and ACL information.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class DataSourcePopulator implements InitializingBean {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private DataSource dataSource;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void setDataSource(DataSource dataSource) {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
public DataSource getDataSource() {
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (dataSource == null) {
|
||||
throw new IllegalArgumentException("dataSource required");
|
||||
}
|
||||
|
||||
JdbcTemplate template = new JdbcTemplate(dataSource);
|
||||
|
||||
template.execute(
|
||||
"CREATE TABLE CONTACTS(ID INTEGER NOT NULL PRIMARY KEY, CONTACT_NAME VARCHAR_IGNORECASE(50) NOT NULL, EMAIL VARCHAR_IGNORECASE(50) NOT NULL)");
|
||||
template.execute(
|
||||
"INSERT INTO contacts VALUES (1, 'John Smith', 'john@somewhere.com');"); // marissa
|
||||
template.execute(
|
||||
"INSERT INTO contacts VALUES (2, 'Michael Citizen', 'michael@xyz.com');"); // marissa
|
||||
template.execute(
|
||||
"INSERT INTO contacts VALUES (3, 'Joe Bloggs', 'joe@demo.com');"); // marissa
|
||||
template.execute(
|
||||
"INSERT INTO contacts VALUES (4, 'Karen Sutherland', 'karen@sutherland.com');"); // marissa + dianne + scott
|
||||
template.execute(
|
||||
"INSERT INTO contacts VALUES (5, 'Mitchell Howard', 'mitchell@abcdef.com');"); // dianne
|
||||
template.execute(
|
||||
"INSERT INTO contacts VALUES (6, 'Rose Costas', 'rose@xyz.com');"); // dianne + scott
|
||||
template.execute(
|
||||
"INSERT INTO contacts VALUES (7, 'Amanda Smith', 'amanda@abcdef.com');"); // scott
|
||||
template.execute(
|
||||
"INSERT INTO contacts VALUES (8, 'Cindy Smith', 'cindy@smith.com');"); // dianne + scott
|
||||
template.execute(
|
||||
"INSERT INTO contacts VALUES (9, 'Jonathan Citizen', 'jonathan@xyz.com');"); // scott
|
||||
template.execute(
|
||||
"CREATE TABLE ACL_OBJECT_IDENTITY(ID INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY,OBJECT_IDENTITY VARCHAR_IGNORECASE(250) NOT NULL,PARENT_OBJECT INTEGER,ACL_CLASS VARCHAR_IGNORECASE(250) NOT NULL,CONSTRAINT UNIQUE_OBJECT_IDENTITY UNIQUE(OBJECT_IDENTITY),CONSTRAINT SYS_FK_3 FOREIGN KEY(PARENT_OBJECT) REFERENCES ACL_OBJECT_IDENTITY(ID))");
|
||||
template.execute(
|
||||
"INSERT INTO acl_object_identity VALUES (1, 'sample.contact.Contact:1', null, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');");
|
||||
template.execute(
|
||||
"INSERT INTO acl_object_identity VALUES (2, 'sample.contact.Contact:2', null, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');");
|
||||
template.execute(
|
||||
"INSERT INTO acl_object_identity VALUES (3, 'sample.contact.Contact:3', null, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');");
|
||||
template.execute(
|
||||
"INSERT INTO acl_object_identity VALUES (4, 'sample.contact.Contact:4', null, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');");
|
||||
template.execute(
|
||||
"INSERT INTO acl_object_identity VALUES (5, 'sample.contact.Contact:5', null, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');");
|
||||
template.execute(
|
||||
"INSERT INTO acl_object_identity VALUES (6, 'sample.contact.Contact:6', null, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');");
|
||||
template.execute(
|
||||
"INSERT INTO acl_object_identity VALUES (7, 'sample.contact.Contact:7', null, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');");
|
||||
template.execute(
|
||||
"INSERT INTO acl_object_identity VALUES (8, 'sample.contact.Contact:8', null, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');");
|
||||
template.execute(
|
||||
"INSERT INTO acl_object_identity VALUES (9, 'sample.contact.Contact:9', null, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');");
|
||||
template.execute(
|
||||
"CREATE TABLE ACL_PERMISSION(ID INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY,ACL_OBJECT_IDENTITY INTEGER NOT NULL,RECIPIENT VARCHAR_IGNORECASE(100) NOT NULL,MASK INTEGER NOT NULL,CONSTRAINT UNIQUE_RECIPIENT UNIQUE(ACL_OBJECT_IDENTITY,RECIPIENT),CONSTRAINT SYS_FK_7 FOREIGN KEY(ACL_OBJECT_IDENTITY) REFERENCES ACL_OBJECT_IDENTITY(ID))");
|
||||
template.execute(
|
||||
"INSERT INTO acl_permission VALUES (null, 1, 'marissa', 1);"); // administer
|
||||
template.execute(
|
||||
"INSERT INTO acl_permission VALUES (null, 2, 'marissa', 2);"); // read
|
||||
template.execute(
|
||||
"INSERT INTO acl_permission VALUES (null, 3, 'marissa', 22);"); // read+write+delete
|
||||
template.execute(
|
||||
"INSERT INTO acl_permission VALUES (null, 4, 'marissa', 1);"); // administer
|
||||
template.execute(
|
||||
"INSERT INTO acl_permission VALUES (null, 4, 'dianne', 1);"); // administer
|
||||
template.execute(
|
||||
"INSERT INTO acl_permission VALUES (null, 4, 'scott', 2);"); // read
|
||||
template.execute(
|
||||
"INSERT INTO acl_permission VALUES (null, 5, 'dianne', 2);"); // read
|
||||
template.execute(
|
||||
"INSERT INTO acl_permission VALUES (null, 6, 'dianne', 22);"); // read+write+delete
|
||||
template.execute(
|
||||
"INSERT INTO acl_permission VALUES (null, 6, 'scott', 2);"); // read
|
||||
template.execute(
|
||||
"INSERT INTO acl_permission VALUES (null, 7, 'scott', 1);"); // administer
|
||||
template.execute(
|
||||
"INSERT INTO acl_permission VALUES (null, 8, 'dianne', 2);"); // read
|
||||
template.execute(
|
||||
"INSERT INTO acl_permission VALUES (null, 8, 'scott', 2);"); // read
|
||||
template.execute(
|
||||
"INSERT INTO acl_permission VALUES (null, 9, 'scott', 22);"); // read+write+delete
|
||||
template.execute(
|
||||
"CREATE TABLE USERS(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,PASSWORD VARCHAR_IGNORECASE(50) NOT NULL,ENABLED BOOLEAN NOT NULL);");
|
||||
template.execute(
|
||||
"CREATE TABLE AUTHORITIES(USERNAME VARCHAR_IGNORECASE(50) NOT NULL,AUTHORITY VARCHAR_IGNORECASE(50) NOT NULL,CONSTRAINT FK_AUTHORITIES_USERS FOREIGN KEY(USERNAME) REFERENCES USERS(USERNAME));");
|
||||
template.execute(
|
||||
"CREATE UNIQUE INDEX IX_AUTH_USERNAME ON AUTHORITIES(USERNAME,AUTHORITY);");
|
||||
|
||||
/*
|
||||
Passwords encoded using MD5, NOT in Base64 format, with null as salt
|
||||
Encoded password for marissa is "koala"
|
||||
Encoded password for dianne is "emu"
|
||||
Encoded password for scott is "wombat"
|
||||
Encoded password for peter is "opal" (but user is disabled)
|
||||
|
||||
*/
|
||||
template.execute(
|
||||
"INSERT INTO USERS VALUES('marissa','a564de63c2d0da68cf47586ee05984d7',TRUE);");
|
||||
template.execute(
|
||||
"INSERT INTO USERS VALUES('dianne','65d15fe9156f9c4bbffd98085992a44e',TRUE);");
|
||||
template.execute(
|
||||
"INSERT INTO USERS VALUES('scott','2b58af6dddbd072ed27ffc86725d7d3a',TRUE);");
|
||||
template.execute(
|
||||
"INSERT INTO USERS VALUES('peter','22b5c9accc6e1ba628cedc63a72d57f8',FALSE);");
|
||||
template.execute(
|
||||
"INSERT INTO AUTHORITIES VALUES('marissa','ROLE_USER');");
|
||||
template.execute(
|
||||
"INSERT INTO AUTHORITIES VALUES('marissa','ROLE_SUPERVISOR');");
|
||||
template.execute(
|
||||
"INSERT INTO AUTHORITIES VALUES('dianne','ROLE_USER');");
|
||||
template.execute("INSERT INTO AUTHORITIES VALUES('scott','ROLE_USER');");
|
||||
template.execute("INSERT INTO AUTHORITIES VALUES('peter','ROLE_USER');");
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ package sample.contact;
|
|||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.web.bind.RequestUtils;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.mvc.Controller;
|
||||
|
||||
|
@ -28,7 +29,7 @@ import javax.servlet.http.HttpServletResponse;
|
|||
|
||||
|
||||
/**
|
||||
* Controller to delete a contact page.
|
||||
* Controller to delete a contact.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
|
@ -57,8 +58,8 @@ public class DeleteController implements Controller, InitializingBean {
|
|||
|
||||
public ModelAndView handleRequest(HttpServletRequest request,
|
||||
HttpServletResponse response) throws ServletException, IOException {
|
||||
Integer id = new Integer(request.getParameter("id"));
|
||||
Contact contact = contactManager.getById(id);
|
||||
int id = RequestUtils.getRequiredIntParameter(request, "contactId");
|
||||
Contact contact = contactManager.getById(new Integer(id));
|
||||
contactManager.delete(contact);
|
||||
|
||||
return new ModelAndView("deleted", "contact", contact);
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sample.contact;
|
||||
|
||||
import net.sf.acegisecurity.acl.AclManager;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.web.bind.RequestUtils;
|
||||
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 deleting an ACL permission.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class DeletePermissionController implements Controller, InitializingBean {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private AclManager aclManager;
|
||||
private ContactManager contactManager;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void setAclManager(AclManager aclManager) {
|
||||
this.aclManager = aclManager;
|
||||
}
|
||||
|
||||
public AclManager getAclManager() {
|
||||
return aclManager;
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
if (aclManager == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"An aclManager implementation is required");
|
||||
}
|
||||
}
|
||||
|
||||
public ModelAndView handleRequest(HttpServletRequest request,
|
||||
HttpServletResponse response) throws ServletException, IOException {
|
||||
int contactId = RequestUtils.getRequiredIntParameter(request,
|
||||
"contactId");
|
||||
String recipient = RequestUtils.getRequiredStringParameter(request,
|
||||
"recipient");
|
||||
|
||||
Contact contact = contactManager.getById(new Integer(contactId));
|
||||
|
||||
contactManager.deletePermission(contact, recipient);
|
||||
|
||||
Map model = new HashMap();
|
||||
model.put("contact", contact);
|
||||
model.put("recipient", recipient);
|
||||
|
||||
return new ModelAndView("deletePermission", "model", model);
|
||||
}
|
||||
}
|
|
@ -15,13 +15,6 @@
|
|||
|
||||
package sample.contact;
|
||||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.AuthenticationCredentialsNotFoundException;
|
||||
import net.sf.acegisecurity.GrantedAuthority;
|
||||
import net.sf.acegisecurity.UserDetails;
|
||||
import net.sf.acegisecurity.context.ContextHolder;
|
||||
import net.sf.acegisecurity.context.SecureContext;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
@ -30,6 +23,7 @@ import org.springframework.web.servlet.mvc.Controller;
|
|||
import java.io.IOException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
@ -67,38 +61,17 @@ public class SecureIndexController implements Controller, InitializingBean {
|
|||
|
||||
public ModelAndView handleRequest(HttpServletRequest request,
|
||||
HttpServletResponse response) throws ServletException, IOException {
|
||||
SecureContext secureContext = ((SecureContext) ContextHolder.getContext());
|
||||
List myContactsList = contactManager.getAll();
|
||||
Contact[] myContacts;
|
||||
|
||||
if (null == secureContext) {
|
||||
throw new AuthenticationCredentialsNotFoundException(
|
||||
"Authentication credentials were not found in the "
|
||||
+ "SecureContext");
|
||||
if (myContactsList.size() == 0) {
|
||||
myContacts = null;
|
||||
} else {
|
||||
myContacts = (Contact[]) myContactsList.toArray(new Contact[] {});
|
||||
}
|
||||
|
||||
// Lookup username. As we must accommodate DaoAuthenticationProvider,
|
||||
// CAS and container based authentication, we take care with casting
|
||||
Authentication auth = secureContext.getAuthentication();
|
||||
String username = auth.getPrincipal().toString();
|
||||
|
||||
if (auth.getPrincipal() instanceof UserDetails) {
|
||||
username = ((UserDetails) auth.getPrincipal()).getUsername();
|
||||
}
|
||||
|
||||
boolean supervisor = false;
|
||||
GrantedAuthority[] granted = auth.getAuthorities();
|
||||
|
||||
for (int i = 0; i < granted.length; i++) {
|
||||
if (granted[i].getAuthority().equals("ROLE_SUPERVISOR")) {
|
||||
supervisor = true;
|
||||
}
|
||||
}
|
||||
|
||||
Contact[] myContacts = contactManager.getAllByOwner(username);
|
||||
|
||||
Map model = new HashMap();
|
||||
model.put("contacts", myContacts);
|
||||
model.put("supervisor", new Boolean(supervisor));
|
||||
model.put("user", username);
|
||||
|
||||
return new ModelAndView("index", "model", model);
|
||||
}
|
||||
|
|
|
@ -15,19 +15,10 @@
|
|||
|
||||
package sample.contact;
|
||||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.UserDetails;
|
||||
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;
|
||||
|
||||
|
@ -57,20 +48,8 @@ public class WebContactAddController extends SimpleFormController {
|
|||
String name = ((WebContact) command).getName();
|
||||
String email = ((WebContact) command).getEmail();
|
||||
|
||||
Authentication auth = ((SecureContext) ContextHolder.getContext())
|
||||
.getAuthentication();
|
||||
String owner = auth.getPrincipal().toString();
|
||||
|
||||
if (auth.getPrincipal() instanceof UserDetails) {
|
||||
owner = ((UserDetails) auth.getPrincipal()).getUsername();
|
||||
}
|
||||
|
||||
Contact contact = new Contact(contactManager.getNextId(), name, email,
|
||||
owner);
|
||||
contactManager.save(contact);
|
||||
|
||||
Map myModel = new HashMap();
|
||||
myModel.put("now", new Date());
|
||||
Contact contact = new Contact(name, email);
|
||||
contactManager.create(contact);
|
||||
|
||||
return new ModelAndView(new RedirectView(getSuccessView()));
|
||||
}
|
||||
|
|
|
@ -35,12 +35,16 @@ public class WebContactValidator implements Validator {
|
|||
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.getName() == null) || (wc.getName().length() < 3)
|
||||
|| (wc.getName().length() > 50)) {
|
||||
errors.rejectValue("name", "err.name",
|
||||
"Name 3-50 characters is required.");
|
||||
}
|
||||
|
||||
if ((wc.getEmail() == null) || (wc.getEmail().length() < 3)) {
|
||||
errors.rejectValue("email", "not-used", null, "Email is required.");
|
||||
if ((wc.getEmail() == null) || (wc.getEmail().length() < 3)
|
||||
|| (wc.getEmail().length() > 50)) {
|
||||
errors.rejectValue("email", "err.email",
|
||||
"Email 3-50 characters is required.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
# Global logging configuration
|
||||
log4j.rootLogger=WARN, stdout, fileout
|
||||
|
||||
#log4j.logger.org.springframework.aop.framework.autoproxy=DEBUG, stdout, fileout
|
||||
#log4j.logger.org.springframework.aop.framework.autoproxy.metadata=DEBUG, stdout, fileout
|
||||
#log4j.logger.org.springframework.aop.framework.autoproxy.target=DEBUG, stdout, fileout
|
||||
#log4j.logger.org.springframework.transaction.interceptor=DEBUG, stdout, fileout
|
||||
#log4j.logger.net.sf.acegisecurity.intercept=DEBUG, stdout, fileout
|
||||
#log4j.logger.net.sf.acegisecurity.intercept.method=DEBUG, stdout, fileout
|
||||
#log4j.logger.net.sf.acegisecurity.afterinvocation=DEBUG, stdout, fileout
|
||||
#log4j.logger.net.sf.acegisecurity.acl=DEBUG, stdout, fileout
|
||||
#log4j.logger.net.sf.acegisecurity.acl.basic=DEBUG, stdout, fileout
|
||||
#log4j.logger.net.sf.acegisecurity.taglibs.authz=DEBUG, stdout, fileout
|
||||
|
||||
|
||||
# Console output...
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.conversionPattern=[%p,%c{1},%t] %m%n
|
||||
|
||||
# Rolling log file output...
|
||||
log4j.appender.fileout=org.apache.log4j.RollingFileAppender
|
||||
log4j.appender.fileout.File=log4j.log
|
||||
#log4j.appender.fileout.File=${webapp.root}/WEB-INF/log4j.log
|
||||
log4j.appender.fileout.MaxFileSize=100KB
|
||||
log4j.appender.fileout.MaxBackupIndex=1
|
||||
log4j.appender.fileout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.fileout.layout.conversionPattern=%d{ABSOLUTE} %5p %c{1},%t:%L - %m%n
|
|
@ -0,0 +1,43 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
|
||||
|
||||
<!--
|
||||
- Application context containing authentication, channel
|
||||
- security and web URI beans.
|
||||
-
|
||||
- Only used by "ca" artifact.
|
||||
-
|
||||
- $Id$
|
||||
-->
|
||||
|
||||
<beans>
|
||||
|
||||
<!-- ======================== AUTHENTICATION ======================= -->
|
||||
|
||||
<!-- We could also have a daoAuthenticationProvider in order to
|
||||
process BASIC authentication requests, but this has been
|
||||
left out given container adapters aren't recommended and
|
||||
it would increase the number of bean declarations required -->
|
||||
<bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">
|
||||
<property name="providers">
|
||||
<list>
|
||||
<ref local="authByAdapterProvider"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="authByAdapterProvider" class="net.sf.acegisecurity.adapters.AuthByAdapterProvider">
|
||||
<property name="key"><value>my_password</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="httpRequestIntegrationFilter" class="net.sf.acegisecurity.adapters.HttpRequestIntegrationFilter"/>
|
||||
|
||||
<!-- ===================== HTTP CHANNEL REQUIREMENTS ==================== -->
|
||||
|
||||
<!-- Implement by servlet specification -->
|
||||
|
||||
<!-- ===================== HTTP REQUEST SECURITY ==================== -->
|
||||
|
||||
<!-- Implement by servlet specification -->
|
||||
|
||||
</beans>
|
|
@ -1,142 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
|
||||
|
||||
<!--
|
||||
- Application context loaded by ContextLoaderListener if using container adapters
|
||||
- $Id$
|
||||
-->
|
||||
|
||||
<beans>
|
||||
|
||||
<!-- =================== SECURITY SYSTEM DEFINITIONS ================== -->
|
||||
|
||||
<!-- RunAsManager -->
|
||||
<bean id="runAsManager" class="net.sf.acegisecurity.runas.RunAsManagerImpl">
|
||||
<property name="key"><value>my_run_as_password</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHENTICATION DEFINITIONS ~~~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
<bean id="runAsAuthenticationProvider" class="net.sf.acegisecurity.runas.RunAsImplAuthenticationProvider">
|
||||
<property name="key"><value>my_run_as_password</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="authByAdapterProvider" class="net.sf.acegisecurity.adapters.AuthByAdapterProvider">
|
||||
<property name="key"><value>my_password</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">
|
||||
<property name="providers">
|
||||
<list>
|
||||
<ref local="runAsAuthenticationProvider"/>
|
||||
<ref local="authByAdapterProvider"/>
|
||||
<ref local="daoAuthenticationProvider"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="inMemoryDaoImpl" class="net.sf.acegisecurity.providers.dao.memory.InMemoryDaoImpl">
|
||||
<property name="userMap">
|
||||
<value>
|
||||
marissa=koala,ROLE_TELLER,ROLE_SUPERVISOR
|
||||
dianne=emu,ROLE_TELLER
|
||||
scott=wombat,ROLE_TELLER
|
||||
peter=opal,disabled,ROLE_TELLER
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
|
||||
<property name="authenticationDao"><ref local="inMemoryDaoImpl"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="basicProcessingFilter" class="net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter">
|
||||
<property name="authenticationManager"><ref local="authenticationManager"/></property>
|
||||
<property name="authenticationEntryPoint"><ref local="basicProcessingFilterEntryPoint"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="basicProcessingFilterEntryPoint" class="net.sf.acegisecurity.ui.basicauth.BasicProcessingFilterEntryPoint">
|
||||
<property name="realmName"><value>Contacts Realm</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="autoIntegrationFilter" class="net.sf.acegisecurity.ui.AutoIntegrationFilter" />
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHORIZATION DEFINITIONS ~~~~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
<!-- An access decision voter that reads ROLE_* configuaration settings -->
|
||||
<bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/>
|
||||
|
||||
<!-- An access decision voter that reads CONTACT_OWNED_BY_CURRENT_USER configuaration settings -->
|
||||
<bean id="contactSecurityVoter" class="sample.contact.ContactSecurityVoter"/>
|
||||
|
||||
<!-- An access decision manager used by the business objects -->
|
||||
<bean id="businessAccessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased">
|
||||
<property name="allowIfAllAbstainDecisions"><value>false</value></property>
|
||||
<property name="decisionVoters">
|
||||
<list>
|
||||
<ref local="roleVoter"/>
|
||||
<ref local="contactSecurityVoter"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ===================== SECURITY DEFINITIONS ======================= -->
|
||||
|
||||
<bean id="publicContactManagerSecurity" class="net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
|
||||
<property name="authenticationManager"><ref local="authenticationManager"/></property>
|
||||
<property name="accessDecisionManager"><ref local="businessAccessDecisionManager"/></property>
|
||||
<property name="runAsManager"><ref local="runAsManager"/></property>
|
||||
<property name="objectDefinitionSource">
|
||||
<value>
|
||||
sample.contact.ContactManager.delete=ROLE_SUPERVISOR,RUN_AS_SERVER
|
||||
sample.contact.ContactManager.getAllByOwner=CONTACT_OWNED_BY_CURRENT_USER,RUN_AS_SERVER
|
||||
sample.contact.ContactManager.save=CONTACT_OWNED_BY_CURRENT_USER,RUN_AS_SERVER
|
||||
sample.contact.ContactManager.getById=ROLE_TELLER,RUN_AS_SERVER
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- We expect all callers of the backend object to hold the role ROLE_RUN_AS_SERVER -->
|
||||
<bean id="backendContactManagerSecurity" class="net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
|
||||
<property name="authenticationManager"><ref local="authenticationManager"/></property>
|
||||
<property name="accessDecisionManager"><ref local="businessAccessDecisionManager"/></property>
|
||||
<property name="runAsManager"><ref local="runAsManager"/></property>
|
||||
<property name="objectDefinitionSource">
|
||||
<value>
|
||||
sample.contact.ContactManager.delete=ROLE_RUN_AS_SERVER
|
||||
sample.contact.ContactManager.getAllByOwner=ROLE_RUN_AS_SERVER
|
||||
sample.contact.ContactManager.save=ROLE_RUN_AS_SERVER
|
||||
sample.contact.ContactManager.getById=ROLE_RUN_AS_SERVER
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ======================= BUSINESS DEFINITIONS ===================== -->
|
||||
|
||||
<bean id="contactManager" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces"><value>sample.contact.ContactManager</value></property>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<idref local="publicContactManagerSecurity"/>
|
||||
<idref local="publicContactManagerTarget"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="publicContactManagerTarget" class="sample.contact.ContactManagerFacade">
|
||||
<property name="backend"><ref local="backendContactManager"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="backendContactManager" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces"><value>sample.contact.ContactManager</value></property>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<idref local="backendContactManagerSecurity"/>
|
||||
<idref local="backendContactManagerTarget"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="backendContactManagerTarget" class="sample.contact.ContactManagerBackend"/>
|
||||
|
||||
</beans>
|
|
@ -3,73 +3,65 @@
|
|||
|
||||
<!--
|
||||
- Contacts web application
|
||||
-
|
||||
- web.xml for "ca" artifact only.
|
||||
-
|
||||
- $Id$
|
||||
- File will be copied into WAR's WEB-INF directory if using container adapter
|
||||
-->
|
||||
|
||||
<web-app>
|
||||
|
||||
<display-name>Contacts Sample Application</display-name>
|
||||
|
||||
<description>
|
||||
Example of an application secured using Acegi Security System for Spring.
|
||||
</description>
|
||||
|
||||
<!--
|
||||
- Location of the XML file that defines the root application context
|
||||
- Applied by ContextLoaderListener.
|
||||
-->
|
||||
<context-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value>/WEB-INF/applicationContext.xml</param-value>
|
||||
<param-value>
|
||||
/WEB-INF/applicationContext-acegi-security.xml
|
||||
/WEB-INF/applicationContext-common-business.xml
|
||||
/WEB-INF/applicationContext-common-authorization.xml
|
||||
</param-value>
|
||||
</context-param>
|
||||
|
||||
<context-param>
|
||||
<param-name>log4jConfigLocation</param-name>
|
||||
<param-value>/WEB-INF/classes/log4j.properties</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- Obtains Authentication from HttpServletRequest.getPrincipal(),
|
||||
and puts it into ContextHolder for request duration -->
|
||||
<filter>
|
||||
<filter-name>Acegi HTTP BASIC Authorization Filter</filter-name>
|
||||
<filter-name>Acegi Security System for Spring HttpRequest Integration Filter</filter-name>
|
||||
<filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
|
||||
<init-param>
|
||||
<param-name>targetClass</param-name>
|
||||
<param-value>net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter</param-value>
|
||||
</init-param>
|
||||
</filter>
|
||||
|
||||
<filter>
|
||||
<filter-name>Acegi Security System for Spring Auto Integration Filter</filter-name>
|
||||
<filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
|
||||
<init-param>
|
||||
<param-name>targetClass</param-name>
|
||||
<param-value>net.sf.acegisecurity.ui.AutoIntegrationFilter</param-value>
|
||||
<param-value>net.sf.acegisecurity.ui.webapp.HttpSessionIntegrationFilter</param-value>
|
||||
</init-param>
|
||||
</filter>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>Acegi HTTP BASIC Authorization Filter</filter-name>
|
||||
<filter-name>Acegi Security System for Spring HttpRequest Integration Filter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>Acegi Security System for Spring Auto Integration Filter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
|
||||
<!--
|
||||
- Loads the root application context of this web app at startup,
|
||||
- by default from "/WEB-INF/applicationContext.xml".
|
||||
- Use WebApplicationContextUtils.getWebApplicationContext(servletContext)
|
||||
- to access it anywhere in the web application, outside of the framework.
|
||||
- Loads the root application context of this web app at startup.
|
||||
- The application context is then available via
|
||||
- WebApplicationContextUtils.getWebApplicationContext(servletContext).
|
||||
-->
|
||||
<listener>
|
||||
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
|
||||
</listener>
|
||||
|
||||
<listener>
|
||||
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
|
||||
</listener>
|
||||
|
||||
<!--
|
||||
- Servlet that dispatches request to registered handlers (Controller implementations).
|
||||
- Has its own application context, by default defined in "{servlet-name}-servlet.xml",
|
||||
- i.e. "contacts-servlet.xml".
|
||||
-
|
||||
- A web app can contain any number of such servlets.
|
||||
- Note that this web app does not have a shared root application context,
|
||||
- therefore the DispatcherServlet contexts do not have a common parent.
|
||||
- Provides core MVC application controller. See contacts-servlet.xml.
|
||||
-->
|
||||
<servlet>
|
||||
<servlet-name>contacts</servlet-name>
|
||||
|
@ -77,25 +69,20 @@
|
|||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<!--
|
||||
- Provides web services endpoint. See caucho-servlet.xml.
|
||||
-->
|
||||
<servlet>
|
||||
<servlet-name>caucho</servlet-name>
|
||||
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
|
||||
<load-on-startup>2</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<!--
|
||||
- Maps the contacts dispatcher to /*.
|
||||
-
|
||||
-->
|
||||
<servlet-mapping>
|
||||
<servlet-name>contacts</servlet-name>
|
||||
<url-pattern>*.htm</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!--
|
||||
- Dispatcher servlet mapping for HTTP remoting via the Caucho protocols,
|
||||
- i.e. Hessian and Burlap (see caucho-servlet.xml for the controllers).
|
||||
-->
|
||||
<servlet-mapping>
|
||||
<servlet-name>caucho</servlet-name>
|
||||
<url-pattern>/caucho/*</url-pattern>
|
||||
|
@ -117,7 +104,7 @@
|
|||
<url-pattern>/secure/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>ROLE_TELLER</role-name>
|
||||
<role-name>ROLE_USER</role-name>
|
||||
<role-name>ROLE_SUPERVISOR</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
|
@ -145,7 +132,7 @@
|
|||
<role-name>ROLE_SUPERVISOR</role-name>
|
||||
</security-role>
|
||||
<security-role>
|
||||
<role-name>ROLE_TELLER</role-name>
|
||||
<role-name>ROLE_USER</role-name>
|
||||
</security-role>
|
||||
|
||||
</web-app>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<%@ taglib prefix='c' uri='http://java.sun.com/jstl/core' %>
|
||||
<%-- This page will be copied into WAR's root directory if using container adapter --%>
|
||||
<html>
|
||||
<head>
|
||||
<title>Login</title>
|
||||
|
@ -8,11 +7,12 @@
|
|||
<body>
|
||||
<h1>Login</h1>
|
||||
|
||||
<P>If you've used the standard springsecurity.xml, try these users:
|
||||
<P>Valid users:
|
||||
<P>
|
||||
<P>username <b>marissa</b>, password <b>koala</b> (granted ROLE_SUPERVISOR)
|
||||
<P>username <b>dianne</b>, password <b>emu</b> (not a supervisor)
|
||||
<p>username <b>scott</b>, password <b>wombat</b> (not a supervisor)
|
||||
<P>username <b>marissa</b>, password <b>koala</b>
|
||||
<P>username <b>dianne</b>, password <b>emu</b>
|
||||
<p>username <b>scott</b>, password <b>wombat</b>
|
||||
<p>username <b>peter</b>, password <b>opal</b> (user disabled)
|
||||
<p>
|
||||
|
||||
<%-- this form-login-page form is also used as the
|
||||
|
|
|
@ -2,60 +2,40 @@
|
|||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
|
||||
|
||||
<!--
|
||||
- Application context loaded by ContextLoaderListener if NOT using container adapters
|
||||
- Application context containing authentication, channel
|
||||
- security and web URI beans.
|
||||
-
|
||||
- Only used by "cas" artifact.
|
||||
-
|
||||
- $Id$
|
||||
-
|
||||
-
|
||||
- HAVING PROBLEMS? See the etc/ssl/howto.txt file and read "TROUBLESHOOTING".
|
||||
-
|
||||
-
|
||||
-->
|
||||
|
||||
<beans>
|
||||
|
||||
<!-- =================== SECURITY SYSTEM DEFINITIONS ================== -->
|
||||
|
||||
<!-- RunAsManager -->
|
||||
<bean id="runAsManager" class="net.sf.acegisecurity.runas.RunAsManagerImpl">
|
||||
<property name="key"><value>my_run_as_password</value></property>
|
||||
</bean>
|
||||
<!-- ======================== AUTHENTICATION ======================= -->
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHENTICATION DEFINITIONS ~~~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
<bean id="runAsAuthenticationProvider" class="net.sf.acegisecurity.runas.RunAsImplAuthenticationProvider">
|
||||
<property name="key"><value>my_run_as_password</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">
|
||||
<property name="providers">
|
||||
<list>
|
||||
<ref local="runAsAuthenticationProvider"/>
|
||||
<bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">
|
||||
<property name="providers">
|
||||
<list>
|
||||
<ref local="casAuthenticationProvider"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="inMemoryDaoImpl" class="net.sf.acegisecurity.providers.dao.memory.InMemoryDaoImpl">
|
||||
<property name="userMap">
|
||||
<value>
|
||||
marissa=PASSWORD_NOT_USED,ROLE_TELLER,ROLE_SUPERVISOR
|
||||
dianne=PASSWORD_NOT_USED,ROLE_TELLER
|
||||
scott=PASSWORD_NOT_USED,ROLE_TELLER
|
||||
peter=PASSWORD_NOT_USED_AND_DISABLED_IGNORED,disabled,ROLE_TELLER
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="basicProcessingFilter" class="net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter">
|
||||
<property name="authenticationManager"><ref local="authenticationManager"/></property>
|
||||
<property name="authenticationEntryPoint"><ref local="basicProcessingFilterEntryPoint"/></property>
|
||||
</bean>
|
||||
<bean id="jdbcDaoImpl" class="net.sf.acegisecurity.providers.dao.jdbc.JdbcDaoImpl">
|
||||
<property name="dataSource"><ref bean="dataSource"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="basicProcessingFilterEntryPoint" class="net.sf.acegisecurity.ui.basicauth.BasicProcessingFilterEntryPoint">
|
||||
<property name="realmName"><value>Contacts Realm</value></property>
|
||||
</bean>
|
||||
<bean id="basicProcessingFilter" class="net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter">
|
||||
<property name="authenticationManager"><ref local="authenticationManager"/></property>
|
||||
<property name="authenticationEntryPoint"><ref local="basicProcessingFilterEntryPoint"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="autoIntegrationFilter" class="net.sf.acegisecurity.ui.AutoIntegrationFilter" />
|
||||
<bean id="basicProcessingFilterEntryPoint" class="net.sf.acegisecurity.ui.basicauth.BasicProcessingFilterEntryPoint">
|
||||
<property name="realmName"><value>Contacts Realm</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="httpSessionIntegrationFilter" class="net.sf.acegisecurity.ui.webapp.HttpSessionIntegrationFilter"/>
|
||||
|
||||
<bean id="casAuthenticationProvider" class="net.sf.acegisecurity.providers.cas.CasAuthenticationProvider">
|
||||
<property name="casAuthoritiesPopulator"><ref local="casAuthoritiesPopulator"/></property>
|
||||
|
@ -77,7 +57,7 @@
|
|||
</bean>
|
||||
|
||||
<bean id="casAuthoritiesPopulator" class="net.sf.acegisecurity.providers.cas.populator.DaoCasAuthoritiesPopulator">
|
||||
<property name="authenticationDao"><ref local="inMemoryDaoImpl"/></property>
|
||||
<property name="authenticationDao"><ref local="jdbcDaoImpl"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="casProxyDecider" class="net.sf.acegisecurity.providers.cas.proxy.RejectProxyTickets">
|
||||
|
@ -88,86 +68,9 @@
|
|||
<property name="sendRenew"><value>false</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHORIZATION DEFINITIONS ~~~~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
<!-- An access decision voter that reads ROLE_* configuaration settings -->
|
||||
<bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/>
|
||||
|
||||
<!-- An access decision voter that reads CONTACT_OWNED_BY_CURRENT_USER configuaration settings -->
|
||||
<bean id="contactSecurityVoter" class="sample.contact.ContactSecurityVoter"/>
|
||||
|
||||
<!-- An access decision manager used by the business objects -->
|
||||
<bean id="businessAccessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased">
|
||||
<property name="allowIfAllAbstainDecisions"><value>false</value></property>
|
||||
<property name="decisionVoters">
|
||||
<list>
|
||||
<ref local="roleVoter"/>
|
||||
<ref local="contactSecurityVoter"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ===================== SECURITY DEFINITIONS ======================= -->
|
||||
|
||||
<bean id="publicContactManagerSecurity" class="net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
|
||||
<property name="authenticationManager"><ref local="authenticationManager"/></property>
|
||||
<property name="accessDecisionManager"><ref local="businessAccessDecisionManager"/></property>
|
||||
<property name="runAsManager"><ref local="runAsManager"/></property>
|
||||
<property name="objectDefinitionSource">
|
||||
<value>
|
||||
sample.contact.ContactManager.delete=ROLE_SUPERVISOR,RUN_AS_SERVER
|
||||
sample.contact.ContactManager.getAllByOwner=CONTACT_OWNED_BY_CURRENT_USER,RUN_AS_SERVER
|
||||
sample.contact.ContactManager.save=CONTACT_OWNED_BY_CURRENT_USER,RUN_AS_SERVER
|
||||
sample.contact.ContactManager.getById=ROLE_TELLER,RUN_AS_SERVER
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- We expect all callers of the backend object to hold the role ROLE_RUN_AS_SERVER -->
|
||||
<bean id="backendContactManagerSecurity" class="net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
|
||||
<property name="authenticationManager"><ref local="authenticationManager"/></property>
|
||||
<property name="accessDecisionManager"><ref local="businessAccessDecisionManager"/></property>
|
||||
<property name="runAsManager"><ref local="runAsManager"/></property>
|
||||
<property name="objectDefinitionSource">
|
||||
<value>
|
||||
sample.contact.ContactManager.delete=ROLE_RUN_AS_SERVER
|
||||
sample.contact.ContactManager.getAllByOwner=ROLE_RUN_AS_SERVER
|
||||
sample.contact.ContactManager.save=ROLE_RUN_AS_SERVER
|
||||
sample.contact.ContactManager.getById=ROLE_RUN_AS_SERVER
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ======================= BUSINESS DEFINITIONS ===================== -->
|
||||
|
||||
<bean id="contactManager" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces"><value>sample.contact.ContactManager</value></property>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<idref local="publicContactManagerSecurity"/>
|
||||
<idref local="publicContactManagerTarget"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="publicContactManagerTarget" class="sample.contact.ContactManagerFacade">
|
||||
<property name="backend"><ref local="backendContactManager"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="backendContactManager" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces"><value>sample.contact.ContactManager</value></property>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<idref local="backendContactManagerSecurity"/>
|
||||
<idref local="backendContactManagerTarget"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="backendContactManagerTarget" class="sample.contact.ContactManagerBackend"/>
|
||||
|
||||
<!-- ===================== HTTP CHANNEL REQUIREMENTS ==================== -->
|
||||
|
||||
<!-- Enabled by default for CAS, as a CAS deployment uses HTTPS -->
|
||||
<bean id="channelProcessingFilter" class="net.sf.acegisecurity.securechannel.ChannelProcessingFilter">
|
||||
<property name="channelDecisionManager"><ref local="channelDecisionManager"/></property>
|
||||
<property name="filterInvocationDefinitionSource">
|
||||
|
@ -194,6 +97,11 @@
|
|||
|
||||
<!-- ===================== HTTP REQUEST SECURITY ==================== -->
|
||||
|
||||
<bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter">
|
||||
<property name="filterSecurityInterceptor"><ref local="filterInvocationInterceptor"/></property>
|
||||
<property name="authenticationEntryPoint"><ref local="casProcessingFilterEntryPoint"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="casProcessingFilter" class="net.sf.acegisecurity.ui.cas.CasProcessingFilter">
|
||||
<property name="authenticationManager"><ref local="authenticationManager"/></property>
|
||||
<property name="authenticationFailureUrl"><value>/casfailed.jsp</value></property>
|
||||
|
@ -201,11 +109,6 @@
|
|||
<property name="filterProcessesUrl"><value>/j_acegi_cas_security_check</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter">
|
||||
<property name="filterSecurityInterceptor"><ref local="filterInvocationInterceptor"/></property>
|
||||
<property name="authenticationEntryPoint"><ref local="casProcessingFilterEntryPoint"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="casProcessingFilterEntryPoint" class="net.sf.acegisecurity.ui.cas.CasProcessingFilterEntryPoint">
|
||||
<property name="loginUrl"><value>https://localhost:8443/cas/login</value></property>
|
||||
<property name="serviceProperties"><ref local="serviceProperties"/></property>
|
||||
|
@ -215,7 +118,7 @@
|
|||
<property name="allowIfAllAbstainDecisions"><value>false</value></property>
|
||||
<property name="decisionVoters">
|
||||
<list>
|
||||
<ref local="roleVoter"/>
|
||||
<ref bean="roleVoter"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
@ -226,7 +129,6 @@
|
|||
<bean id="filterInvocationInterceptor" class="net.sf.acegisecurity.intercept.web.FilterSecurityInterceptor">
|
||||
<property name="authenticationManager"><ref local="authenticationManager"/></property>
|
||||
<property name="accessDecisionManager"><ref local="httpRequestAccessDecisionManager"/></property>
|
||||
<property name="runAsManager"><ref local="runAsManager"/></property>
|
||||
<property name="objectDefinitionSource">
|
||||
<value>
|
||||
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
|
|
@ -3,17 +3,33 @@
|
|||
|
||||
<!--
|
||||
- Contacts web application
|
||||
-
|
||||
- web.xml for "cas" artifact only.
|
||||
-
|
||||
- $Id$
|
||||
- File will be copied into WAR's WEB-INF directory if NOT using container adapter
|
||||
-->
|
||||
|
||||
<web-app>
|
||||
|
||||
<display-name>Contacts Sample Application</display-name>
|
||||
|
||||
<description>
|
||||
Example of an application secured using Acegi Security System for Spring.
|
||||
</description>
|
||||
<!--
|
||||
- Location of the XML file that defines the root application context
|
||||
- Applied by ContextLoaderListener.
|
||||
-->
|
||||
<context-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value>
|
||||
/WEB-INF/applicationContext-acegi-security.xml
|
||||
/WEB-INF/applicationContext-common-business.xml
|
||||
/WEB-INF/applicationContext-common-authorization.xml
|
||||
</param-value>
|
||||
</context-param>
|
||||
|
||||
<context-param>
|
||||
<param-name>log4jConfigLocation</param-name>
|
||||
<param-value>/WEB-INF/classes/log4j.properties</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- Required for CAS ProxyTicketReceptor servlet. This is the
|
||||
URL to CAS' "proxy" actuator, where a PGT and TargetService can
|
||||
|
@ -24,15 +40,6 @@
|
|||
<param-value>http://localhost:8433/cas/proxy</param-value>
|
||||
</context-param>
|
||||
|
||||
<!--
|
||||
- Location of the XML file that defines the root application context
|
||||
- Applied by ContextLoaderListener.
|
||||
-->
|
||||
<context-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value>/WEB-INF/applicationContext.xml</param-value>
|
||||
</context-param>
|
||||
|
||||
<filter>
|
||||
<filter-name>Acegi Channel Processing Filter</filter-name>
|
||||
<filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
|
||||
|
@ -42,6 +49,7 @@
|
|||
</init-param>
|
||||
</filter>
|
||||
|
||||
<!-- Responds to HTTP POSTs to j_acegi_cas_security_check URI -->
|
||||
<filter>
|
||||
<filter-name>Acegi CAS Processing Filter</filter-name>
|
||||
<filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
|
||||
|
@ -51,6 +59,7 @@
|
|||
</init-param>
|
||||
</filter>
|
||||
|
||||
<!-- Responds to HTTP requests with a BASIC (RFC 1945) authentication header -->
|
||||
<filter>
|
||||
<filter-name>Acegi HTTP BASIC Authorization Filter</filter-name>
|
||||
<filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
|
||||
|
@ -60,15 +69,21 @@
|
|||
</init-param>
|
||||
</filter>
|
||||
|
||||
<!-- Obtains Authentication from HttpSession attribute, puts it into
|
||||
ContextHolder for request duration, proceeds with request, then
|
||||
copies Authentication from ContextHolder back into HttpSession -->
|
||||
<filter>
|
||||
<filter-name>Acegi Security System for Spring Auto Integration Filter</filter-name>
|
||||
<filter-name>Acegi Security System for Spring HttpSession Integration Filter</filter-name>
|
||||
<filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
|
||||
<init-param>
|
||||
<param-name>targetClass</param-name>
|
||||
<param-value>net.sf.acegisecurity.ui.AutoIntegrationFilter</param-value>
|
||||
<param-value>net.sf.acegisecurity.ui.webapp.HttpSessionIntegrationFilter</param-value>
|
||||
</init-param>
|
||||
</filter>
|
||||
|
||||
<!-- Provides HTTP request URL security, and also catches
|
||||
AcegiSecurityExceptions and sends 403 errors (if access denied)
|
||||
or commences an authentication mechanism as appropriate -->
|
||||
<filter>
|
||||
<filter-name>Acegi HTTP Request Security Filter</filter-name>
|
||||
<filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
|
||||
|
@ -77,12 +92,12 @@
|
|||
<param-value>net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter</param-value>
|
||||
</init-param>
|
||||
</filter>
|
||||
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>Acegi Channel Processing Filter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>Acegi CAS Processing Filter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
|
@ -94,7 +109,7 @@
|
|||
</filter-mapping>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>Acegi Security System for Spring Auto Integration Filter</filter-name>
|
||||
<filter-name>Acegi Security System for Spring HttpSession Integration Filter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
|
@ -104,23 +119,20 @@
|
|||
</filter-mapping>
|
||||
|
||||
<!--
|
||||
- Loads the root application context of this web app at startup,
|
||||
- by default from "/WEB-INF/applicationContext.xml".
|
||||
- Use WebApplicationContextUtils.getWebApplicationContext(servletContext)
|
||||
- to access it anywhere in the web application, outside of the framework.
|
||||
- Loads the root application context of this web app at startup.
|
||||
- The application context is then available via
|
||||
- WebApplicationContextUtils.getWebApplicationContext(servletContext).
|
||||
-->
|
||||
<listener>
|
||||
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
|
||||
</listener>
|
||||
|
||||
<listener>
|
||||
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
|
||||
</listener>
|
||||
|
||||
<!--
|
||||
- Servlet that dispatches request to registered handlers (Controller implementations).
|
||||
- Has its own application context, by default defined in "{servlet-name}-servlet.xml",
|
||||
- i.e. "contacts-servlet.xml".
|
||||
-
|
||||
- A web app can contain any number of such servlets.
|
||||
- Note that this web app does not have a shared root application context,
|
||||
- therefore the DispatcherServlet contexts do not have a common parent.
|
||||
- Provides core MVC application controller. See contacts-servlet.xml.
|
||||
-->
|
||||
<servlet>
|
||||
<servlet-name>contacts</servlet-name>
|
||||
|
@ -128,44 +140,25 @@
|
|||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<!--
|
||||
- Provides web services endpoint. See caucho-servlet.xml.
|
||||
-->
|
||||
<servlet>
|
||||
<servlet-name>caucho</servlet-name>
|
||||
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
|
||||
<load-on-startup>2</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<!-- CAS servlet which receives a proxy-granting ticket from the CAS
|
||||
server. THIS CAN BE REMOVED IF THE APPLICATION DOESN'T NEED TO
|
||||
ACT AS A PROXY -->
|
||||
<servlet>
|
||||
<servlet-name>casproxy</servlet-name>
|
||||
<servlet-class>edu.yale.its.tp.cas.proxy.ProxyTicketReceptor</servlet-class>
|
||||
<load-on-startup>3</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<!--
|
||||
- Maps the contacts dispatcher to /*.
|
||||
-
|
||||
-->
|
||||
<servlet-mapping>
|
||||
<servlet-name>contacts</servlet-name>
|
||||
<url-pattern>*.htm</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!--
|
||||
- Dispatcher servlet mapping for HTTP remoting via the Caucho protocols,
|
||||
- i.e. Hessian and Burlap (see caucho-servlet.xml for the controllers).
|
||||
-->
|
||||
<servlet-mapping>
|
||||
<servlet-name>caucho</servlet-name>
|
||||
<url-pattern>/caucho/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>casproxy</servlet-name>
|
||||
<url-pattern>/casProxy/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<welcome-file-list>
|
||||
<welcome-file>index.jsp</welcome-file>
|
||||
</welcome-file-list>
|
||||
|
@ -174,5 +167,5 @@
|
|||
<taglib-uri>/spring</taglib-uri>
|
||||
<taglib-location>/WEB-INF/spring.tld</taglib-location>
|
||||
</taglib>
|
||||
|
||||
|
||||
</web-app>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<%@ taglib prefix='c' uri='http://java.sun.com/jstl/core' %>
|
||||
<%@ page import="net.sf.acegisecurity.ui.AbstractProcessingFilter" %>
|
||||
<%@ page import="net.sf.acegisecurity.AuthenticationException" %>
|
||||
<%-- This page will be copied into WAR's root directory if using CAS --%>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
|
||||
|
||||
<!--
|
||||
- Application context containing authentication beans.
|
||||
-
|
||||
- Used by all artifacts.
|
||||
-
|
||||
- $Id$
|
||||
-->
|
||||
|
||||
<beans>
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~ "BEFORE INVOCATION" AUTHORIZATION DEFINITIONS ~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
<!-- An access decision voter that reads ROLE_* configuration settings -->
|
||||
<bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/>
|
||||
|
||||
<!-- An access decision voter that reads ACL_CONTACT_READ configuration settings -->
|
||||
<bean id="aclContactReadVoter" class="net.sf.acegisecurity.vote.BasicAclEntryVoter">
|
||||
<property name="processConfigAttribute"><value>ACL_CONTACT_READ</value></property>
|
||||
<property name="processDomainObjectClass"><value>sample.contact.Contact</value></property>
|
||||
<property name="aclManager"><ref local="aclManager"/></property>
|
||||
<property name="requirePermission">
|
||||
<list>
|
||||
<value>1</value> <!-- SimpleAclEntry.ADMINISTER -->
|
||||
<value>2</value> <!-- SimpleAclEntry.READ -->
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- An access decision voter that reads ACL_CONTACT_DELETE configuration settings -->
|
||||
<bean id="aclContactDeleteVoter" class="net.sf.acegisecurity.vote.BasicAclEntryVoter">
|
||||
<property name="processConfigAttribute"><value>ACL_CONTACT_DELETE</value></property>
|
||||
<property name="processDomainObjectClass"><value>sample.contact.Contact</value></property>
|
||||
<property name="aclManager"><ref local="aclManager"/></property>
|
||||
<property name="requirePermission">
|
||||
<list>
|
||||
<value>1</value> <!-- SimpleAclEntry.ADMINISTER -->
|
||||
<value>16</value> <!-- SimpleAclEntry.DELETE -->
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- An access decision voter that reads ACL_CONTACT_ADMIN configuration settings -->
|
||||
<bean id="aclContactAdminVoter" class="net.sf.acegisecurity.vote.BasicAclEntryVoter">
|
||||
<property name="processConfigAttribute"><value>ACL_CONTACT_ADMIN</value></property>
|
||||
<property name="processDomainObjectClass"><value>sample.contact.Contact</value></property>
|
||||
<property name="aclManager"><ref local="aclManager"/></property>
|
||||
<property name="requirePermission">
|
||||
<list>
|
||||
<value>1</value> <!-- SimpleAclEntry.ADMINISTER -->
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- An access decision manager used by the business objects -->
|
||||
<bean id="businessAccessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased">
|
||||
<property name="allowIfAllAbstainDecisions"><value>false</value></property>
|
||||
<property name="decisionVoters">
|
||||
<list>
|
||||
<ref local="roleVoter"/>
|
||||
<ref local="aclContactReadVoter"/>
|
||||
<ref local="aclContactDeleteVoter"/>
|
||||
<ref local="aclContactAdminVoter"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ========= ACCESS CONTROL LIST LOOKUP MANAGER DEFINITIONS ========= -->
|
||||
|
||||
<bean id="aclManager" class="net.sf.acegisecurity.acl.AclProviderManager">
|
||||
<property name="providers">
|
||||
<list>
|
||||
<ref local="basicAclProvider"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="basicAclProvider" class="net.sf.acegisecurity.acl.basic.BasicAclProvider">
|
||||
<property name="basicAclDao"><ref local="basicAclDao"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="basicAclDao" class="net.sf.acegisecurity.acl.basic.jdbc.JdbcDaoImpl">
|
||||
<property name="dataSource"><ref bean="dataSource"/></property>
|
||||
</bean>
|
||||
|
||||
<!-- ============== "AFTER INTERCEPTION" AUTHORIZATION DEFINITIONS =========== -->
|
||||
|
||||
<bean id="afterInvocationManager" class="net.sf.acegisecurity.afterinvocation.AfterInvocationProviderManager">
|
||||
<property name="providers">
|
||||
<list>
|
||||
<ref local="afterAclRead"/>
|
||||
<ref local="afterAclCollectionRead"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Processes AFTER_ACL_COLLECTION_READ configuration settings -->
|
||||
<bean id="afterAclCollectionRead" class="net.sf.acegisecurity.afterinvocation.BasicAclEntryAfterInvocationCollectionFilteringProvider">
|
||||
<property name="aclManager"><ref local="aclManager"/></property>
|
||||
<property name="requirePermission">
|
||||
<list>
|
||||
<value>1</value> <!-- SimpleAclEntry.ADMINISTER -->
|
||||
<value>2</value> <!-- SimpleAclEntry.READ -->
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Processes AFTER_ACL_READ configuration settings -->
|
||||
<bean id="afterAclRead" class="net.sf.acegisecurity.afterinvocation.BasicAclEntryAfterInvocationProvider">
|
||||
<property name="aclManager"><ref local="aclManager"/></property>
|
||||
<property name="requirePermission">
|
||||
<list>
|
||||
<value>1</value> <!-- SimpleAclEntry.ADMINISTER -->
|
||||
<value>2</value> <!-- SimpleAclEntry.READ -->
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
|
||||
<!-- ================= METHOD INVOCATION AUTHORIZATION ==================== -->
|
||||
|
||||
<!-- getRandomContact() is public.
|
||||
|
||||
The create, getAll, getById etc have ROLE_USER to ensure user is
|
||||
authenticated (all users hold ROLE_USER in this application).
|
||||
|
||||
The delete and update methods don't need a ROLE_USER as they will
|
||||
ensure the user is authenticated via their ACL_CONTACT_DELETE or
|
||||
ACL_CONTACT_READ attribute, which also ensures the user has permission
|
||||
to the Contact presented as a method argument.
|
||||
-->
|
||||
<bean id="contactManagerSecurity" class="net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
|
||||
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
|
||||
<property name="accessDecisionManager"><ref local="businessAccessDecisionManager"/></property>
|
||||
<property name="afterInvocationManager"><ref local="afterInvocationManager"/></property>
|
||||
<property name="objectDefinitionSource">
|
||||
<value>
|
||||
sample.contact.ContactManager.create=ROLE_USER
|
||||
sample.contact.ContactManager.getAllRecipients=ROLE_USER
|
||||
sample.contact.ContactManager.getAll=ROLE_USER,AFTER_ACL_COLLECTION_READ
|
||||
sample.contact.ContactManager.getById=ROLE_USER,AFTER_ACL_READ
|
||||
sample.contact.ContactManager.delete=ACL_CONTACT_DELETE
|
||||
sample.contact.ContactManager.deletePermission=ACL_CONTACT_ADMIN
|
||||
sample.contact.ContactManager.addPermission=ACL_CONTACT_ADMIN
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
|
@ -0,0 +1,71 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
|
||||
|
||||
<!--
|
||||
- Application context containing business beans.
|
||||
-
|
||||
- Used by all artifacts.
|
||||
-
|
||||
- $Id$
|
||||
-->
|
||||
|
||||
<beans>
|
||||
|
||||
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
|
||||
<property name="driverClassName">
|
||||
<value>org.hsqldb.jdbcDriver</value>
|
||||
</property>
|
||||
<property name="url">
|
||||
<value>jdbc:hsqldb:mem:contacts</value>
|
||||
</property>
|
||||
<property name="username">
|
||||
<value>sa</value>
|
||||
</property>
|
||||
<property name="password">
|
||||
<value></value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
|
||||
<property name="dataSource"><ref local="dataSource"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
|
||||
<property name="transactionManager"><ref bean="transactionManager"/></property>
|
||||
<property name="transactionAttributeSource">
|
||||
<value>
|
||||
sample.contact.ContactManager.create=PROPAGATION_REQUIRED
|
||||
sample.contact.ContactManager.getAllRecipients=PROPAGATION_REQUIRED,readOnly
|
||||
sample.contact.ContactManager.getAll=PROPAGATION_REQUIRED,readOnly
|
||||
sample.contact.ContactManager.getById=PROPAGATION_REQUIRED,readOnly
|
||||
sample.contact.ContactManager.delete=PROPAGATION_REQUIRED
|
||||
sample.contact.ContactManager.deletePermission=PROPAGATION_REQUIRED
|
||||
sample.contact.ContactManager.addPermission=PROPAGATION_REQUIRED
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="dataSourcePopulator" class="sample.contact.DataSourcePopulator">
|
||||
<property name="dataSource"><ref local="dataSource"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="contactDao" class="sample.contact.ContactDaoSpring">
|
||||
<property name="dataSource"><ref local="dataSource"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="contactManager" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces"><value>sample.contact.ContactManager</value></property>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<idref local="transactionInterceptor"/>
|
||||
<idref bean="contactManagerSecurity"/>
|
||||
<idref local="contactManagerTarget"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="contactManagerTarget" class="sample.contact.ContactManagerBackend">
|
||||
<property name="contactDao"><ref local="contactDao"/></property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
<!--
|
||||
- Application context definition for "contacts" DispatcherServlet.
|
||||
-
|
||||
- $Id$
|
||||
-->
|
||||
|
||||
|
@ -22,6 +23,16 @@
|
|||
<property name="contactManager"><ref bean="contactManager"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="adminPermissionController" class="sample.contact.AdminPermissionController">
|
||||
<property name="contactManager"><ref bean="contactManager"/></property>
|
||||
<property name="aclManager"><ref bean="aclManager"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="deletePermissionController" class="sample.contact.DeletePermissionController">
|
||||
<property name="contactManager"><ref bean="contactManager"/></property>
|
||||
<property name="aclManager"><ref bean="aclManager"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
|
||||
<property name="mappings">
|
||||
<props>
|
||||
|
@ -29,11 +40,17 @@
|
|||
<prop key="/secure/add.htm">secureAddForm</prop>
|
||||
<prop key="/secure/index.htm">secureIndexController</prop>
|
||||
<prop key="/secure/del.htm">secureDeleteController</prop>
|
||||
<prop key="/secure/adminPermission.htm">adminPermissionController</prop>
|
||||
<prop key="/secure/deletePermission.htm">deletePermissionController</prop>
|
||||
<prop key="/secure/addPermission.htm">addPermissionForm</prop>
|
||||
</props>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="addValidator" class="sample.contact.WebContactValidator"/>
|
||||
|
||||
<bean id="addPermissionValidator" class="sample.contact.AddPermissionValidator"/>
|
||||
|
||||
<bean id="secureAddForm" class="sample.contact.WebContactAddController">
|
||||
<property name="sessionForm"><value>true</value></property>
|
||||
<property name="commandName"><value>webContact</value></property>
|
||||
|
@ -46,6 +63,18 @@
|
|||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="addPermissionForm" class="sample.contact.AddPermissionController">
|
||||
<property name="sessionForm"><value>true</value></property>
|
||||
<property name="commandName"><value>addPermission</value></property>
|
||||
<property name="commandClass"><value>sample.contact.AddPermission</value></property>
|
||||
<property name="validator"><ref bean="addPermissionValidator"/></property>
|
||||
<property name="formView"><value>addPermission</value></property>
|
||||
<property name="successView"><value>index.htm</value></property>
|
||||
<property name="contactManager">
|
||||
<ref bean="contactManager"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
|
||||
<property name="prefix"><value>/WEB-INF/jsp/</value></property>
|
||||
<property name="suffix"><value>.jsp</value></property>
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
<%@ include file="/WEB-INF/jsp/include.jsp" %>
|
||||
<html>
|
||||
<head><title>Add Permission</title></head>
|
||||
<body>
|
||||
<h1>Add Permission</h1>
|
||||
<form method="post">
|
||||
<table width="95%" bgcolor="f8f8ff" border="0" cellspacing="0" cellpadding="5">
|
||||
<tr>
|
||||
<td alignment="right" width="20%">Contact:</td>
|
||||
<td width="60%"><c:out value="${addPermission.contact}"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td alignment="right" width="20%">Recipient:</td>
|
||||
<spring:bind path="addPermission.recipient">
|
||||
<td width="20%">
|
||||
<select name="<c:out value="${status.expression}"/>">
|
||||
<c:forEach var="thisRecipient" items="${recipients}">
|
||||
<option <c:if test="${thisRecipient.key == status.value}">selected</c:if> value="<c:out value="${thisRecipient.key}"/>">
|
||||
<c:out value="${thisRecipient.value}"/></option>
|
||||
</c:forEach>
|
||||
</select>
|
||||
</td>
|
||||
<td width="60%">
|
||||
<font color="red"><c:out value="${status.errorMessage}"/></font>
|
||||
</td>
|
||||
</spring:bind>
|
||||
</tr>
|
||||
<tr>
|
||||
<td alignment="right" width="20%">Permission:</td>
|
||||
<spring:bind path="addPermission.permission">
|
||||
<td width="20%">
|
||||
<select name="<c:out value="${status.expression}"/>">
|
||||
<c:forEach var="thisPermission" items="${permissions}">
|
||||
<option <c:if test="${thisPermission.key == status.value}">selected</c:if> value="<c:out value="${thisPermission.key}"/>">
|
||||
<c:out value="${thisPermission.value}"/></option>
|
||||
</c:forEach>
|
||||
</select>
|
||||
</td>
|
||||
<td width="60%">
|
||||
<font color="red"><c:out value="${status.errorMessage}"/></font>
|
||||
</td>
|
||||
</spring:bind>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<spring:hasBindErrors name="webContact">
|
||||
<b>Please fix all errors!</b>
|
||||
</spring:hasBindErrors>
|
||||
<br><br>
|
||||
<input name="execute" type="submit" alignment="center" value="Execute">
|
||||
</form>
|
||||
<p>
|
||||
<A HREF="<c:url value="adminPermission.htm"><c:param name="contactId" value="${addPermission.contact.id}"/></c:url>">Admin Permission</A> <a href="<c:url value="index.htm"/>">Manage</a>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,39 @@
|
|||
<%@ page import="net.sf.acegisecurity.acl.basic.SimpleAclEntry" %>
|
||||
<%@ include file="/WEB-INF/jsp/include.jsp" %>
|
||||
|
||||
<html>
|
||||
<head><title>Administer Permissions</title></head>
|
||||
<body>
|
||||
<h1>Administer Permissions</h1>
|
||||
<P>
|
||||
<code>
|
||||
<c:out value="${model.contact}"/>
|
||||
</code>
|
||||
<P>
|
||||
<table cellpadding=3 border=0>
|
||||
<c:forEach var="acl" items="${model.acls}">
|
||||
<c:if test="${acl.class.name eq 'net.sf.acegisecurity.acl.basic.SimpleAclEntry'}">
|
||||
<tr>
|
||||
<td>
|
||||
<code>
|
||||
<%
|
||||
SimpleAclEntry simpleAcl = ((SimpleAclEntry) pageContext.getAttribute("acl"));
|
||||
String permissionBlock = simpleAcl.printPermissionsBlock();
|
||||
%>
|
||||
<%= permissionBlock %>
|
||||
[<c:out value="${acl.mask}"/>]
|
||||
<c:out value="${acl.recipient}"/>
|
||||
</code>
|
||||
</td>
|
||||
<td>
|
||||
<!-- This application doesn't use ACL inheritance, so we can safely use
|
||||
the model's contact and know it was directly assigned the ACL -->
|
||||
<A HREF="<c:url value="deletePermission.htm"><c:param name="contactId" value="${model.contact.id}"/><c:param name="recipient" value="${acl.recipient}"/></c:url>">Del</A>
|
||||
</td>
|
||||
</tr>
|
||||
</c:if>
|
||||
</c:forEach>
|
||||
</table>
|
||||
<p><a href="<c:url value="addPermission.htm"><c:param name="contactId" value="${model.contact.id}"/></c:url>">Add Permission</a> <a href="<c:url value="index.htm"/>">Manage</a>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,18 @@
|
|||
<%@ page import="net.sf.acegisecurity.acl.basic.SimpleAclEntry" %>
|
||||
<%@ include file="/WEB-INF/jsp/include.jsp" %>
|
||||
|
||||
<html>
|
||||
<head><title>Permission Deleted</title></head>
|
||||
<body>
|
||||
<h1>Permission Deleted</h1>
|
||||
<P>
|
||||
<code>
|
||||
<c:out value="${model.contact}"/>
|
||||
</code>
|
||||
<P>
|
||||
<code>
|
||||
<c:out value="${model.recipient}"/>
|
||||
</code>
|
||||
<p><a href="<c:url value="index.htm"/>">Manage</a>
|
||||
</body>
|
||||
</html>
|
|
@ -4,28 +4,42 @@
|
|||
<head><title>Contacts Security Demo</title></head>
|
||||
<body>
|
||||
<h1>Contacts Security Demo</h1>
|
||||
<p>This is a very simple application to demonstrate the Acegi Security System for Spring.
|
||||
The application manages contacts, partitioned based on the user that owns them.
|
||||
Users may only manage their own contacts, and only users with ROLE_SUPERVISOR
|
||||
are allowed to delete their contacts. It also demonstrates how to configure
|
||||
server-side secure objects so they can only be accessed via a public facade.
|
||||
<P>Contacts demonstrates the following central Acegi Security capabilities:
|
||||
<ul>
|
||||
<li><b>Role-based security</b>. Each principal is a member of certain roles,
|
||||
which are used to restrict access to certain secure objects.</li>
|
||||
<li><b>Domain object instance security</b>. The <code>Contact</code>, the
|
||||
main domain object in the application, has an access control list (ACL)
|
||||
that indicates who is allowed read, administer and delete the object.</li>
|
||||
<li><b>Method invocation security</b>. The <code>ContactManager</code> service
|
||||
layer bean has a number of secured (protected) and public (unprotected)
|
||||
methods.</li>
|
||||
<li><b>Web request security</b>. The <code>/secure</code> URI path is protected
|
||||
by Acegi Security from principals not holding the
|
||||
<code>ROLE_USER</code> granted authority.</li>
|
||||
<li><b>Security unaware application objects</b>. None of the objects
|
||||
are aware of the security being implemented by Acegi Security. *</li>
|
||||
<li><b>Security taglib usage</b>. All of the JSPs use Acegi Security's
|
||||
taglib to evaluate security information. *</li>
|
||||
<li><b>Fully declarative security</b>. Every capability is configured in
|
||||
the application context using standard Acegi Security classes. *</li>
|
||||
<li><b>Database-sourced security data</b>. All of the user, role and ACL
|
||||
information is obtained from an in-memory JDBC-compliant database.</li>
|
||||
</ul>
|
||||
|
||||
<P>If you deployed the contacts-container-adapter.war file, the application
|
||||
automatically extracts the principal from the web container (which should be
|
||||
configured with a suitable Acegi Security System for Spring adapter). If
|
||||
you're using the standard contacts.war file, the application is entirely
|
||||
self-contained and you don't need to do anything special with your web
|
||||
container. If you're using the contacts-cas.war file, please review the
|
||||
setup in samples/contacts/etc/cas/applicationContext.xml for your CAS server
|
||||
and if necessary rebuild using the Contacts application's build.xml.
|
||||
* As the application provides an "ACL Administration" use case, those
|
||||
classes are necessarily aware of security. But no business use cases are.
|
||||
|
||||
<P>This application also demonstrates a public method, which is used to select
|
||||
the random contact that is shown below:
|
||||
<P>
|
||||
<p>Please excuse the lack of look 'n' feel polish in this application.
|
||||
It is about security, after all! :-)
|
||||
|
||||
<p>To demonstrate a public method on <code>ContactManager</code>,
|
||||
here's a random <code>Contact</code>:
|
||||
<p>
|
||||
<code>
|
||||
<c:out value="${contact}"/>
|
||||
</code>
|
||||
<p>
|
||||
<p>Get started by clicking "Manage"...
|
||||
<p><A HREF="<c:url value="secure/index.htm"/>">Manage</a>
|
||||
<A HREF="<c:url value="secure/debug.jsp"/>">Debug</a>
|
||||
</body>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<html>
|
||||
<head><title>Your Contacts</title></head>
|
||||
<body>
|
||||
<h1><c:out value="${model.user}"/>'s Contacts</h1>
|
||||
<h1><authz:authentication operation="principal"/>'s Contacts</h1>
|
||||
<P>
|
||||
<table cellpadding=3 border=0>
|
||||
<tr><td><b>id</b></td><td><b>Name</b></td><td><b>Email</b></td></tr>
|
||||
|
@ -18,9 +18,12 @@
|
|||
<td>
|
||||
<c:out value="${contact.email}"/>
|
||||
</td>
|
||||
<authz:authorize ifAllGranted="ROLE_SUPERVISOR">
|
||||
<td><A HREF="<c:url value="del.htm"><c:param name="id" value="${contact.id}"/></c:url>">Del</A></td>
|
||||
</authz:authorize>
|
||||
<authz:acl domainObject="${contact}" hasPermission="16,1">
|
||||
<td><A HREF="<c:url value="del.htm"><c:param name="contactId" value="${contact.id}"/></c:url>">Del</A></td>
|
||||
</authz:acl>
|
||||
<authz:acl domainObject="${contact}" hasPermission="1">
|
||||
<td><A HREF="<c:url value="adminPermission.htm"><c:param name="contactId" value="${contact.id}"/></c:url>">Admin Permission</A></td>
|
||||
</authz:acl>
|
||||
</tr>
|
||||
</c:forEach>
|
||||
</table>
|
||||
|
|
|
@ -27,21 +27,20 @@ if (context != null) { %>
|
|||
if (auth instanceof AuthByAdapter) { %>
|
||||
<BR><B>SUCCESS! Your container adapter appears to be properly configured!</B><BR><BR>
|
||||
<% } else { %>
|
||||
<BR><B>SUCCESS! Your web filter appears to be properly configured!</B><BR>
|
||||
<BR><B>SUCCESS! Your web filters appear to be properly configured!</B><BR>
|
||||
<% }
|
||||
|
||||
} else { %>
|
||||
Authentication object is null.<BR>
|
||||
This is an error and your container adapter will not operate properly until corrected.<BR><BR>
|
||||
This is an error and your Acegi Security application will not operate properly until corrected.<BR><BR>
|
||||
<% }
|
||||
} else { %>
|
||||
<B>ContextHolder does not contain a SecureContext.</B><BR>
|
||||
This is an error and your container adapter will not operate properly until corrected.<BR><BR>
|
||||
This is an error and your Acegi Security application will not operate properly until corrected.<BR><BR>
|
||||
<% }
|
||||
} else { %>
|
||||
<B>ContextHolder on ContextHolder is null.</B><BR>
|
||||
This indicates improper setup of the container adapter. Refer to the reference documentation.<BR>
|
||||
Also ensure the correct subclass of AbstractMvcIntegrationInterceptor is being used for your container.<BR>
|
||||
This indicates improper setup of the Acegi Security application. Refer to the reference documentation.<BR>
|
||||
<%}
|
||||
%>
|
||||
|
||||
|
|
|
@ -2,54 +2,34 @@
|
|||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
|
||||
|
||||
<!--
|
||||
- Application context loaded by ContextLoaderListener if NOT using container adapters
|
||||
- Application context containing authentication, channel
|
||||
- security and web URI beans.
|
||||
-
|
||||
- Only used by "filter" artifact.
|
||||
-
|
||||
- $Id$
|
||||
-->
|
||||
|
||||
<beans>
|
||||
|
||||
<!-- =================== SECURITY SYSTEM DEFINITIONS ================== -->
|
||||
|
||||
<!-- RunAsManager -->
|
||||
<bean id="runAsManager" class="net.sf.acegisecurity.runas.RunAsManagerImpl">
|
||||
<property name="key"><value>my_run_as_password</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHENTICATION DEFINITIONS ~~~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
<bean id="runAsAuthenticationProvider" class="net.sf.acegisecurity.runas.RunAsImplAuthenticationProvider">
|
||||
<property name="key"><value>my_run_as_password</value></property>
|
||||
</bean>
|
||||
<!-- ======================== AUTHENTICATION ======================= -->
|
||||
|
||||
<bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">
|
||||
<property name="providers">
|
||||
<list>
|
||||
<ref local="runAsAuthenticationProvider"/>
|
||||
<ref local="daoAuthenticationProvider"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Passwords encoded using MD5, NOT in Base64 format, with null as salt
|
||||
Encoded password for marissa is "koala"
|
||||
Encoded password for dianne is "emu"
|
||||
Encoded password for scott is "wombat"
|
||||
Encoded password for peter is "opal" -->
|
||||
<bean id="inMemoryDaoImpl" class="net.sf.acegisecurity.providers.dao.memory.InMemoryDaoImpl">
|
||||
<property name="userMap">
|
||||
<value>
|
||||
marissa=a564de63c2d0da68cf47586ee05984d7,ROLE_TELLER,ROLE_SUPERVISOR
|
||||
dianne=65d15fe9156f9c4bbffd98085992a44e,ROLE_TELLER
|
||||
scott=2b58af6dddbd072ed27ffc86725d7d3a,ROLE_TELLER
|
||||
peter=22b5c9accc6e1ba628cedc63a72d57f8,disabled,ROLE_TELLER
|
||||
</value>
|
||||
</property>
|
||||
<bean id="jdbcDaoImpl" class="net.sf.acegisecurity.providers.dao.jdbc.JdbcDaoImpl">
|
||||
<property name="dataSource"><ref bean="dataSource"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="passwordEncoder" class="net.sf.acegisecurity.providers.encoding.Md5PasswordEncoder"/>
|
||||
|
||||
<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
|
||||
<property name="authenticationDao"><ref local="inMemoryDaoImpl"/></property>
|
||||
<property name="authenticationDao"><ref local="jdbcDaoImpl"/></property>
|
||||
<property name="userCache"><ref local="userCache"/></property>
|
||||
<property name="passwordEncoder"><ref local="passwordEncoder"/></property>
|
||||
</bean>
|
||||
|
@ -70,85 +50,7 @@
|
|||
<property name="realmName"><value>Contacts Realm</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="autoIntegrationFilter" class="net.sf.acegisecurity.ui.AutoIntegrationFilter"/>
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHORIZATION DEFINITIONS ~~~~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
<!-- An access decision voter that reads ROLE_* configuration settings -->
|
||||
<bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/>
|
||||
|
||||
<!-- An access decision voter that reads CONTACT_OWNED_BY_CURRENT_USER configuration settings -->
|
||||
<bean id="contactSecurityVoter" class="sample.contact.ContactSecurityVoter"/>
|
||||
|
||||
<!-- An access decision manager used by the business objects -->
|
||||
<bean id="businessAccessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased">
|
||||
<property name="allowIfAllAbstainDecisions"><value>false</value></property>
|
||||
<property name="decisionVoters">
|
||||
<list>
|
||||
<ref local="roleVoter"/>
|
||||
<ref local="contactSecurityVoter"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ===================== SECURITY DEFINITIONS ======================= -->
|
||||
|
||||
<bean id="publicContactManagerSecurity" class="net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
|
||||
<property name="authenticationManager"><ref local="authenticationManager"/></property>
|
||||
<property name="accessDecisionManager"><ref local="businessAccessDecisionManager"/></property>
|
||||
<property name="runAsManager"><ref local="runAsManager"/></property>
|
||||
<property name="objectDefinitionSource">
|
||||
<value>
|
||||
sample.contact.ContactManager.delete=ROLE_SUPERVISOR,RUN_AS_SERVER
|
||||
sample.contact.ContactManager.getAllByOwner=CONTACT_OWNED_BY_CURRENT_USER,RUN_AS_SERVER
|
||||
sample.contact.ContactManager.save=CONTACT_OWNED_BY_CURRENT_USER,RUN_AS_SERVER
|
||||
sample.contact.ContactManager.getById=ROLE_TELLER,RUN_AS_SERVER
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- We expect all callers of the backend object to hold the role ROLE_RUN_AS_SERVER -->
|
||||
<bean id="backendContactManagerSecurity" class="net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
|
||||
<property name="authenticationManager"><ref local="authenticationManager"/></property>
|
||||
<property name="accessDecisionManager"><ref local="businessAccessDecisionManager"/></property>
|
||||
<property name="runAsManager"><ref local="runAsManager"/></property>
|
||||
<property name="objectDefinitionSource">
|
||||
<value>
|
||||
sample.contact.ContactManager.delete=ROLE_RUN_AS_SERVER
|
||||
sample.contact.ContactManager.getAllByOwner=ROLE_RUN_AS_SERVER
|
||||
sample.contact.ContactManager.save=ROLE_RUN_AS_SERVER
|
||||
sample.contact.ContactManager.getById=ROLE_RUN_AS_SERVER
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ======================= BUSINESS DEFINITIONS ===================== -->
|
||||
|
||||
<bean id="contactManager" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces"><value>sample.contact.ContactManager</value></property>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<idref local="publicContactManagerSecurity"/>
|
||||
<idref local="publicContactManagerTarget"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="publicContactManagerTarget" class="sample.contact.ContactManagerFacade">
|
||||
<property name="backend"><ref local="backendContactManager"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="backendContactManager" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces"><value>sample.contact.ContactManager</value></property>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<idref local="backendContactManagerSecurity"/>
|
||||
<idref local="backendContactManagerTarget"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="backendContactManagerTarget" class="sample.contact.ContactManagerBackend"/>
|
||||
<bean id="httpSessionIntegrationFilter" class="net.sf.acegisecurity.ui.webapp.HttpSessionIntegrationFilter"/>
|
||||
|
||||
<!-- ===================== HTTP CHANNEL REQUIREMENTS ==================== -->
|
||||
|
||||
|
@ -182,18 +84,18 @@
|
|||
|
||||
<!-- ===================== HTTP REQUEST SECURITY ==================== -->
|
||||
|
||||
<bean id="authenticationProcessingFilter" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
|
||||
<property name="authenticationManager"><ref local="authenticationManager"/></property>
|
||||
<property name="authenticationFailureUrl"><value>/acegilogin.jsp?login_error=1</value></property>
|
||||
<property name="defaultTargetUrl"><value>/</value></property>
|
||||
<property name="filterProcessesUrl"><value>/j_acegi_security_check</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter">
|
||||
<property name="filterSecurityInterceptor"><ref local="filterInvocationInterceptor"/></property>
|
||||
<property name="authenticationEntryPoint"><ref local="authenticationProcessingFilterEntryPoint"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="authenticationProcessingFilter" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
|
||||
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
|
||||
<property name="authenticationFailureUrl"><value>/acegilogin.jsp?login_error=1</value></property>
|
||||
<property name="defaultTargetUrl"><value>/</value></property>
|
||||
<property name="filterProcessesUrl"><value>/j_acegi_security_check</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="authenticationProcessingFilterEntryPoint" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
|
||||
<property name="loginFormUrl"><value>/acegilogin.jsp</value></property>
|
||||
<property name="forceHttps"><value>false</value></property>
|
||||
|
@ -203,7 +105,7 @@
|
|||
<property name="allowIfAllAbstainDecisions"><value>false</value></property>
|
||||
<property name="decisionVoters">
|
||||
<list>
|
||||
<ref local="roleVoter"/>
|
||||
<ref bean="roleVoter"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
@ -212,14 +114,13 @@
|
|||
The FilterSecurityInterceptor will work from the top of the list down to the FIRST pattern that matches the request URL.
|
||||
Accordingly, you should place MOST SPECIFIC (ie a/b/c/d.*) expressions first, with LEAST SPECIFIC (ie a/.*) expressions last -->
|
||||
<bean id="filterInvocationInterceptor" class="net.sf.acegisecurity.intercept.web.FilterSecurityInterceptor">
|
||||
<property name="authenticationManager"><ref local="authenticationManager"/></property>
|
||||
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
|
||||
<property name="accessDecisionManager"><ref local="httpRequestAccessDecisionManager"/></property>
|
||||
<property name="runAsManager"><ref local="runAsManager"/></property>
|
||||
<property name="objectDefinitionSource">
|
||||
<value>
|
||||
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
|
||||
\A/secure/super.*\Z=ROLE_WE_DONT_HAVE
|
||||
\A/secure/.*\Z=ROLE_SUPERVISOR,ROLE_TELLER
|
||||
\A/secure/.*\Z=ROLE_SUPERVISOR,ROLE_USER
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
|
@ -3,27 +3,35 @@
|
|||
|
||||
<!--
|
||||
- Contacts web application
|
||||
-
|
||||
- web.xml for "filter" artifact only.
|
||||
-
|
||||
- $Id$
|
||||
- File will be copied into WAR's WEB-INF directory if NOT using container adapter
|
||||
-->
|
||||
|
||||
<web-app>
|
||||
|
||||
<display-name>Contacts Sample Application</display-name>
|
||||
|
||||
<description>
|
||||
Example of an application secured using Acegi Security System for Spring.
|
||||
</description>
|
||||
|
||||
<!--
|
||||
- Location of the XML file that defines the root application context
|
||||
- Applied by ContextLoaderListener.
|
||||
-->
|
||||
<context-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value>/WEB-INF/applicationContext.xml</param-value>
|
||||
<param-value>
|
||||
/WEB-INF/applicationContext-acegi-security.xml
|
||||
/WEB-INF/applicationContext-common-business.xml
|
||||
/WEB-INF/applicationContext-common-authorization.xml
|
||||
</param-value>
|
||||
</context-param>
|
||||
|
||||
<context-param>
|
||||
<param-name>log4jConfigLocation</param-name>
|
||||
<param-value>/WEB-INF/classes/log4j.properties</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- The <filter-mapping> to this filter is disabled by default -->
|
||||
<filter>
|
||||
<filter-name>Acegi Channel Processing Filter</filter-name>
|
||||
<filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
|
||||
|
@ -33,6 +41,7 @@
|
|||
</init-param>
|
||||
</filter>
|
||||
|
||||
<!-- Responds to HTTP POSTs to j_acegi_security_check URI -->
|
||||
<filter>
|
||||
<filter-name>Acegi Authentication Processing Filter</filter-name>
|
||||
<filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
|
||||
|
@ -42,6 +51,7 @@
|
|||
</init-param>
|
||||
</filter>
|
||||
|
||||
<!-- Responds to HTTP requests with a BASIC (RFC 1945) authentication header -->
|
||||
<filter>
|
||||
<filter-name>Acegi HTTP BASIC Authorization Filter</filter-name>
|
||||
<filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
|
||||
|
@ -51,15 +61,21 @@
|
|||
</init-param>
|
||||
</filter>
|
||||
|
||||
<!-- Obtains Authentication from HttpSession attribute, puts it into
|
||||
ContextHolder for request duration, proceeds with request, then
|
||||
copies Authentication from ContextHolder back into HttpSession -->
|
||||
<filter>
|
||||
<filter-name>Acegi Security System for Spring Auto Integration Filter</filter-name>
|
||||
<filter-name>Acegi Security System for Spring HttpSession Integration Filter</filter-name>
|
||||
<filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
|
||||
<init-param>
|
||||
<param-name>targetClass</param-name>
|
||||
<param-value>net.sf.acegisecurity.ui.AutoIntegrationFilter</param-value>
|
||||
<param-value>net.sf.acegisecurity.ui.webapp.HttpSessionIntegrationFilter</param-value>
|
||||
</init-param>
|
||||
</filter>
|
||||
|
||||
<!-- Provides HTTP request URL security, and also catches
|
||||
AcegiSecurityExceptions and sends 403 errors (if access denied)
|
||||
or commences an authentication mechanism as appropriate -->
|
||||
<filter>
|
||||
<filter-name>Acegi HTTP Request Security Filter</filter-name>
|
||||
<filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
|
||||
|
@ -89,7 +105,7 @@
|
|||
</filter-mapping>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>Acegi Security System for Spring Auto Integration Filter</filter-name>
|
||||
<filter-name>Acegi Security System for Spring HttpSession Integration Filter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
|
@ -99,23 +115,20 @@
|
|||
</filter-mapping>
|
||||
|
||||
<!--
|
||||
- Loads the root application context of this web app at startup,
|
||||
- by default from "/WEB-INF/applicationContext.xml".
|
||||
- Use WebApplicationContextUtils.getWebApplicationContext(servletContext)
|
||||
- to access it anywhere in the web application, outside of the framework.
|
||||
- Loads the root application context of this web app at startup.
|
||||
- The application context is then available via
|
||||
- WebApplicationContextUtils.getWebApplicationContext(servletContext).
|
||||
-->
|
||||
<listener>
|
||||
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
|
||||
</listener>
|
||||
|
||||
<listener>
|
||||
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
|
||||
</listener>
|
||||
|
||||
<!--
|
||||
- Servlet that dispatches request to registered handlers (Controller implementations).
|
||||
- Has its own application context, by default defined in "{servlet-name}-servlet.xml",
|
||||
- i.e. "contacts-servlet.xml".
|
||||
-
|
||||
- A web app can contain any number of such servlets.
|
||||
- Note that this web app does not have a shared root application context,
|
||||
- therefore the DispatcherServlet contexts do not have a common parent.
|
||||
- Provides core MVC application controller. See contacts-servlet.xml.
|
||||
-->
|
||||
<servlet>
|
||||
<servlet-name>contacts</servlet-name>
|
||||
|
@ -123,25 +136,20 @@
|
|||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<!--
|
||||
- Provides web services endpoint. See caucho-servlet.xml.
|
||||
-->
|
||||
<servlet>
|
||||
<servlet-name>caucho</servlet-name>
|
||||
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
|
||||
<load-on-startup>2</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<!--
|
||||
- Maps the contacts dispatcher to /*.
|
||||
-
|
||||
-->
|
||||
<servlet-mapping>
|
||||
<servlet-name>contacts</servlet-name>
|
||||
<url-pattern>*.htm</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!--
|
||||
- Dispatcher servlet mapping for HTTP remoting via the Caucho protocols,
|
||||
- i.e. Hessian and Burlap (see caucho-servlet.xml for the controllers).
|
||||
-->
|
||||
<servlet-mapping>
|
||||
<servlet-name>caucho</servlet-name>
|
||||
<url-pattern>/caucho/*</url-pattern>
|
||||
|
@ -155,5 +163,5 @@
|
|||
<taglib-uri>/spring</taglib-uri>
|
||||
<taglib-location>/WEB-INF/spring.tld</taglib-location>
|
||||
</taglib>
|
||||
|
||||
|
||||
</web-app>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<%@ taglib prefix='c' uri='http://java.sun.com/jstl/core' %>
|
||||
<%@ page import="net.sf.acegisecurity.ui.AbstractProcessingFilter" %>
|
||||
<%@ page import="net.sf.acegisecurity.AuthenticationException" %>
|
||||
<%-- This page will be copied into WAR's root directory if NOT using container adapter --%>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
|
@ -11,11 +10,12 @@
|
|||
<body>
|
||||
<h1>Login</h1>
|
||||
|
||||
<P>If you've used the standard springsecurity.xml, try these users:
|
||||
<P>Valid users:
|
||||
<P>
|
||||
<P>username <b>marissa</b>, password <b>koala</b> (granted ROLE_SUPERVISOR)
|
||||
<P>username <b>dianne</b>, password <b>emu</b> (not a supervisor)
|
||||
<p>username <b>scott</b>, password <b>wombat</b> (not a supervisor)
|
||||
<P>username <b>marissa</b>, password <b>koala</b>
|
||||
<P>username <b>dianne</b>, password <b>emu</b>
|
||||
<p>username <b>scott</b>, password <b>wombat</b>
|
||||
<p>username <b>peter</b>, password <b>opal</b> (user disabled)
|
||||
<p>
|
||||
|
||||
<%-- this form-login-page form is also used as the
|
||||
|
|
Loading…
Reference in New Issue