Page 3 of 4 FirstFirst 1234 LastLast
Results 21 to 30 of 34

Thread: Dynamic Authorization

  1. #21
    Join Date
    Sep 2005
    Location
    Boston, MA
    Posts
    57

    Default

    Quote Originally Posted by Ben Alex
    To answer question 1, this works because Spring automatically applies PropertyEditors. Because MethodSecurityInterceptor.objectDefinitionSource is a MethodDefinitionSource, Spring uses the MethodDefinitionSourceEditor. The MethodDefinitionSourceEditor gets passed the entire multi-line String that comprises the entire object definition. It then tokenizes it as if it were a standard Java Properties file. This results in the property name of each line (ie anything to the left of the equals sign) being treated as the method name and passed to the newly created MethodDefinitionMap, with the property value of each line (ie anything to the right of the equals sign) being passed to a ConfigAttributeEditor. ConfigAttributeEditor uses the comma delimiter to build a SecurityConfig instance of each token, putting them all into a ConfigAttributeDefinition that is then returned. The returned ConfigAttributeDefinition is passed to the MethodDefinitionMap.

    To answer question 2, I'd normalise the database so you have a SECURE_OBJECT table, a ROLES table, and a SECURE_OBJECT-ROLES table. Thus your DatabaseObjectDefinitionSource can be wired to either a MethodSecurityInterceptor or a FilterSecurityInterceptor. The SECURE_OBJECT table should have a TYPE column to denote whether it's for a MethodInvocation or a FilterInvocation declaration. Once you've got the schema sorted out, it's a simple matter to build a ConfigAttributeDefinition in response to a request. I'd consider returning null to the getConfigAttributeDefinitions() method, as it's only used by AbstractSecurityInterceptor to help with inital configuration checking.
    I would also suggest adding a "sort_order" column to the SECURE_OBJECT table to determine sort order if you plan on using this table to FilterInvocation definitions. With FilterInvocation defintions, the more specific URLs will need to be evaluted first.

    http://acegisecurity.org/docbook/ace...lterinvocation

  2. #22
    Join Date
    Aug 2004
    Location
    Sydney, Australia
    Posts
    2,768

    Default

    Quote Originally Posted by russpitre
    I would also suggest adding a "sort_order" column to the SECURE_OBJECT table to determine sort order if you plan on using this table to FilterInvocation definitions. With FilterInvocation defintions, the more specific URLs will need to be evaluted first.
    This is a good observation.
    Ben Alex
    Project Founder, Spring UAA, Spring Roo and Spring Security

  3. #23
    Join Date
    Sep 2006
    Posts
    2

    Default

    Hi,

    I'm interested on implementing this approach in our app as well. Our admin user needs to be able to change property level access permissions based on the ROLE at runtime and save these permission in the database.

    Is there any document or tutorial that I could use to guide me through this besides this thread?

    Than you

    Raul

  4. #24
    Join Date
    Aug 2006
    Posts
    22

    Red face

    I would suggest looking in the following:

    http://www.springframework.org/articles

    As far I could see this is a custom rolled solution.....it would be nice to see this in the acegi api, but I think since many people need different types of method level auth...that making a generic api for it my be difficult....although....I have been known to be wrong. LOL.

    I would like to implement this....but will wait a while before I attempt it....

    If someone does implement this....please added a tutorial in the articles or ask the senior members where to put it.....

  5. #25
    Join Date
    Mar 2007
    Posts
    7

    Default

    Quote Originally Posted by raulraja View Post
    Hi,

    I'm interested on implementing this approach in our app as well. Our admin user needs to be able to change property level access permissions based on the ROLE at runtime and save these permission in the database.

    Is there any document or tutorial that I could use to guide me through this besides this thread?

    Than you

    Raul
    I am also very interested in this. I see that org.acegisecurity.userdetails.jdbc.JdbcDaoImpl allready implements this for the Users, it would be nice to have a
    org.acegisecurity.intercept.web.jdbc.JdbcFilterInv ocationDefinitionSource
    with cache, and properties for overriding the query.

    I have searched in a lot of places and this doesn't seem to exist, anyone has some tips to share?

  6. #26
    Join Date
    Sep 2005
    Location
    Boston, MA
    Posts
    57

    Default

    Here's a bit of code you may be able to adjust to your environment.


    DatabasePathBasedFilterInvocationDefinitionMap.jav a

    Code:
    package com.mycompany.security.acegisecurity.intercept.web;
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Set;
    import java.util.Vector;
    import org.acegisecurity.ConfigAttributeDefinition;
    import org.acegisecurity.SecurityConfig;
    import org.acegisecurity.intercept.web.AbstractFilterInvocationDefinitionSource;
    import org.acegisecurity.intercept.web.FilterInvocationDefinitionMap;
    import org.apache.log4j.Logger;
    import org.springframework.util.AntPathMatcher;
    import org.springframework.util.PathMatcher;
    import com.mycompany.model.security.Role;
    import com.mycompany.model.security.SecureObject;
    import com.mycompany.service.security.SecurityService;
     
    public class DatabasePathBasedFilterInvocationDefinitionMap extends AbstractFilterInvocationDefinitionSource implements  FilterInvocationDefinitionMap {
     
     protected class EntryHolder {
            private String antPath;
            private ConfigAttributeDefinition configAttributeDefinition;
            protected EntryHolder() {
                throw new IllegalArgumentException("Cannot use default constructor");
            }
            public EntryHolder(String antPath, ConfigAttributeDefinition attr) {
                this.antPath = antPath;
                this.configAttributeDefinition = attr;
            }
            public String getAntPath() {
                return antPath;
            }
            public ConfigAttributeDefinition getConfigAttributeDefinition() {
                return configAttributeDefinition;
            }
        }
     
     private static final Logger logger = Logger.getLogger(DatabasePathBasedFilterInvocationDefinitionMap.class);
     
     private boolean convertUrlToLowercaseBeforeComparison = true;
     
     private PathMatcher pathMatcher = new AntPathMatcher();
     
     private List requestMap = new Vector();
     
     private SecurityService securityService;
     
     @SuppressWarnings("unchecked")
     public void addSecureUrl(String antPath, ConfigAttributeDefinition attr) {
            requestMap.add(new EntryHolder(antPath, attr));
            if (logger.isDebugEnabled()) {
                logger.debug("Added Ant path: " + antPath + "; attributes: " + attr);
            }
        }
     @SuppressWarnings("unchecked")
     public Iterator getConfigAttributeDefinitions() {
         initRequestMap();
            Set set = new HashSet();
            Iterator iter = requestMap.iterator();
            while (iter.hasNext()) {
                EntryHolder entryHolder = (EntryHolder) iter.next();
                set.add(entryHolder.getConfigAttributeDefinition());
            }
            return set.iterator();
        }
        public int getMapSize() {
            return this.requestMap.size();
        }
     
        @SuppressWarnings({"unused","unchecked"})
     private void initRequestMap() {
      List<SecureObject> secureUrlObjects = securityService.getSecureFilterInvocationObjects();
      ConfigAttributeDefinition def =  new ConfigAttributeDefinition();
      for(SecureObject filterInvocation: secureUrlObjects) {
       if(logger.isDebugEnabled()) {
        logger.debug("<Setting Secure Object Filter Definition: " + filterInvocation.getSecureObject() );
       }
       def = new ConfigAttributeDefinition();
       for(Role role : filterInvocation.getRoles()){
        def.addConfigAttribute(new SecurityConfig(role.getName()));
        requestMap.add(filterInvocation.getSortOrder() , new EntryHolder(filterInvocation.getSecureObject(), def) );
       }
      }
     }
     
        public boolean isConvertUrlToLowercaseBeforeComparison() {
            return convertUrlToLowercaseBeforeComparison;
        }
     @SuppressWarnings("unchecked")
     @Override
        public ConfigAttributeDefinition lookupAttributes(String url) {
      //initRequestMap();
     
            // Strip anything after a question mark symbol, as per SEC-161.
            int firstQuestionMarkIndex = url.lastIndexOf("?");
            if (firstQuestionMarkIndex != -1) {
                url = url.substring(0, firstQuestionMarkIndex);
            }
            if (convertUrlToLowercaseBeforeComparison) {
                url = url.toLowerCase();
                if (logger.isDebugEnabled()) {
                    logger.debug("Converted URL to lowercase, from: '" + url
                        + "'; to: '" + url + "'");
                }
            }
            Iterator iter = requestMap.iterator();
            while (iter.hasNext()) {
                EntryHolder entryHolder = (EntryHolder) iter.next();
                boolean matched = pathMatcher.match(entryHolder.getAntPath(), url);
                if (logger.isDebugEnabled()) {
                    logger.debug("Candidate is: '" + url + "'; pattern is "
                        + entryHolder.getAntPath() + "; matched=" + matched);
                }
                if (matched) {
                    return entryHolder.getConfigAttributeDefinition();
                }
            }
            return null;
        }
     
     public void setConvertUrlToLowercaseBeforeComparison(boolean convertUrlToLowercaseBeforeComparison) {
      this.convertUrlToLowercaseBeforeComparison = convertUrlToLowercaseBeforeComparison;
     }
     
     public SecurityService getSecurityService() {
      return securityService;
     }
     
     public void setSecurityService(SecurityService securityService) {
      this.securityService = securityService;
     }
    }

    SecureObject domain object....

    Code:
    package com.mycompany.model.security;
    import java.util.Set;
    import org.apache.commons.lang.builder.EqualsBuilder;
    import org.apache.commons.lang.builder.HashCodeBuilder;
    import com.mycompany.model.BaseObject;
     
    public class SecureObject extends BaseObject {
     
     private static final long serialVersionUID = 7093257566823171405L;
     
     private Integer secureObjectId;
     private Integer secureObjectTypeId;
     private String secureObject;
     private Integer sortOrder;
     
     private Set<Role> roles;
     
     public Set<Role> getRoles() {
      return roles;
     }
     public void setRoles(Set<Role> roles) {
      this.roles = roles;
     }
     public String getSecureObject() {
      return secureObject;
     }
     public void setSecureObject(String secureObject) {
      this.secureObject = secureObject;
     }
     public Integer getSecureObjectId() {
      return secureObjectId;
     }
     public void setSecureObjectId(Integer secureObjectId) {
      this.secureObjectId = secureObjectId;
     }
     public Integer getSortOrder() {
      return sortOrder;
     }
     public void setSortOrder(Integer sortOrder) {
      this.sortOrder = sortOrder;
     }
     public Integer getSecureObjectTypeId() {
      return secureObjectTypeId;
     }
     public void setSecureObjectTypeId(Integer secureObjectTypeId) {
      this.secureObjectTypeId = secureObjectTypeId;
     }
     
     public boolean equals(Object object) {
      if (!(object instanceof SecureObject)) {
       return false;
      }
      SecureObject rhs = (SecureObject) object;
      return new EqualsBuilder().
       append(this.secureObjectTypeId,rhs.getSecureObjectTypeId() ).
       append(this.sortOrder, rhs.getSortOrder() ).
       append(this.secureObject,rhs.getSecureObject() ).
       isEquals();
     }
     public int hashCode() {
      return new HashCodeBuilder(-1639360101, 1081503241).
       append(this.secureObjectTypeId).
       append(this.sortOrder).
       append(this.roles).
       append(this.secureObject).
       toHashCode();
     }
     
    }
    Last edited by russpitre; Mar 13th, 2007 at 07:59 PM.

  7. #27
    Join Date
    Sep 2005
    Location
    Boston, MA
    Posts
    57

    Default

    cont'd...

    Role domain object.

    Code:
    package com.mycompany.model.security;
    import java.util.List;
    import org.apache.commons.lang.StringUtils;
    import org.apache.commons.lang.builder.EqualsBuilder;
    import org.apache.commons.lang.builder.HashCodeBuilder;
    import org.apache.commons.lang.builder.ToStringBuilder;
    import com.mycompany.model.BaseObject;
    import com.mycompany.model.activedirectory.ADGroup;
    import com.mycompany.model.user.PrologUserGroup;
     
    public class Role extends BaseObject {
     
     private static final long serialVersionUID = 5977582917018176333L;
     
     private static String ROLE_PREFIX_ACTIVE_DIRECTORY = "ROLE_";
     private static String ROLE_PREFIX_PROLOG = "ROLE_PROLOG_";
     
     private Integer roleId;
     private String description;
     private String originalName;
     private String name;
     private String sourcePrimaryKey;
     private Integer typeId;
     private RoleType roleType;
     
     private List<String> problemsHolder;
     public String getDescription() {
      return description;
     }
     public void setDescription(String description) {
      this.description = description;
     }
     public String getName() {
      return name;
     }
     public void setName(String name) {
      this.name = name;
     }
     public String getOriginalName() {
      return originalName;
     }
     public void setOriginalName(String originalName) {
      this.originalName = originalName;
     }
     public Integer getRoleId() {
      return roleId;
     }
     public void setRoleId(Integer roleId) {
      this.roleId = roleId;
     }
     public RoleType getRoleType() {
      return roleType;
     }
     public void setRoleType(RoleType roleType) {
      this.roleType = roleType;
     }
     public String getSourcePrimaryKey() {
      return sourcePrimaryKey;
     }
     public void setSourcePrimaryKey(String sourcePrimaryKey) {
      this.sourcePrimaryKey = sourcePrimaryKey;
     }
     public Integer getTypeId() {
      return typeId;
     }
     public void setTypeId(Integer typeId) {
      this.typeId = typeId;
     }
     /**
      * name is the business key.  Do not change.
      * 
      * @see java.lang.Object#equals(Object)
      */
     public boolean equals(Object object) {
      if (!(object instanceof Role)) {
       return false;
      }
      Role rhs = (Role) object;
      return new EqualsBuilder().
       append(this.name, rhs.getName()).isEquals();
     }
     
     /**
      * name is the business key.  Do not change.
      * 
      * @see java.lang.Object#hashCode()
      */
     public int hashCode() {
      return new HashCodeBuilder(-2067913629, -1342727107).
       append(this.name).toHashCode();
     }
     
     /**
      * @see java.lang.Object#toString()
      */
     public String toString() {
      return new ToStringBuilder(this) .append("name", this.name)
        .append("description", this.description).append("typeId",
          this.typeId).append("roleId", this.roleId).append(
          "originalName", this.originalName).append(
          "sourcePrimaryKey", this.sourcePrimaryKey).toString();
     }
     
     public static String formatActiveDirectoryGroupNameToRoleName(String groupName) {
      try {
       String retVal = groupName.toUpperCase();
       retVal = StringUtils.replace(retVal, " ", "_");
       retVal = StringUtils.replace(retVal, ",", "");
       return ROLE_PREFIX_ACTIVE_DIRECTORY + retVal;
      } catch (Exception e ) {
       return null;
      }
     }
     
     public static String formatPrologGroupNameToRoleName(String groupName) {
      StringBuffer strBuffer = new StringBuffer( groupName.trim() );
      return ROLE_PREFIX_PROLOG + strBuffer.toString().toUpperCase().replaceAll(" ", "_").replaceAll("/","_");
     }
     
     public static Role getRole(PrologUserGroup group) {
      Role role = new Role();
      role.setDescription(group.getDescription());
      role.setName(Role.formatPrologGroupNameToRoleName(group.getName()));
      role.setOriginalName(group.getName());
      role.setSourcePrimaryKey(group.getGroupId() + "");
      role.setTypeId(RoleType.PROLOG);
      return role;
     }
     public static Role getRole(ADGroup group) {
      Role role = new Role();
      role.setDescription(group.getDescription());
      role.setName(Role.formatActiveDirectoryGroupNameToRoleName(group.getCn()));
      role.setOriginalName(group.getCn());
      role.setSourcePrimaryKey(group.getDn());
      role.setTypeId(RoleType.ACTIVE_DIRECTORY);
      return role;
     }
     
     public List<String> getProblems() {
      return problemsHolder;
     }
     public void setProblems(List<String> problemsHolder) {
      this.problemsHolder = problemsHolder;
     }
     
     public boolean isProblemsExists(){
      if(this.problemsHolder.size() > 0){
       return true;
      }else{
       return false;
      }
     }
    }
    ...spring bean definition...

    Code:
    <bean id="filterSecurityInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor"> <property name="validateConfigAttributes" value="true"/> <property name="authenticationManager" ref="authenticationManager"/> <property name="accessDecisionManager" ref="accessDecisionManager"/> <property name="objectDefinitionSource" ref="databasePathBasedFilterInvocationDefinitionMap"/> </bean>
    <bean id="databasePathBasedFilterInvocationDefinitionMap" class="com.shawmut.security.acegisecurity.intercept.web.DatabasePathBasedFilterInvocationDefinitionMap"> <property name="securityService" ref="securityService"/>
    </bean>
    Last edited by russpitre; Mar 13th, 2007 at 07:58 PM. Reason: `

  8. #28
    Join Date
    Mar 2007
    Posts
    7

    Default

    thanks! I'll give it a try.

  9. #29
    Join Date
    Nov 2005
    Posts
    6

    Default

    Quote Originally Posted by yfmoan View Post
    Sorry , the AuthorizationSaveOrUpdateEventListener.java above is not working correctly when l first save a entity (whatever object that intercepted by the hibernate event), it cause an endless loop . l guess l used the wrong listeners , and l make it work again by using another 3 listeners , AuthorizationInsertEventListener , AuthorizationUpdateEventListener and AuthorizationDeleteEventListener .

    l am not confirm all this implementations correct or not , but working for me now.
    Instead of using a seperate class I guess it should work if implementing the 3 interfaces in one class too?

    It still causes an endless loop and ultimately a Stack Overflow here...

  10. #30

    Default New Idea

    I am new to Ageci so I might missing the all point but I think you went the wrong way
    I think it would be better give each method it own role and let the adminstrator decide which users or groups can have that role
    You then effectivly can load the list of role for certain user when the session start.
    If permission change during an open session you will need to refresh the list.
    Something like hot deploy. This can be done easliy by being aware to all open sessions.
    Is this sound right?
    mmmm, I think I will order a cup of coffee in this beautiful spring day

Similar Threads

  1. Replies: 3
    Last Post: Mar 9th, 2011, 10:43 AM
  2. Replies: 2
    Last Post: Jul 14th, 2007, 09:05 AM
  3. Replies: 1
    Last Post: Oct 6th, 2005, 02:53 PM
  4. Custom Authorization Header
    By jslongo in forum Security
    Replies: 1
    Last Post: Sep 20th, 2005, 06:13 PM
  5. Replies: 1
    Last Post: Jul 12th, 2005, 05:41 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •