rogerrut 2004/12/04 14:28:19 Modified: components/sso/src/java/org/apache/jetspeed/sso/impl SSOSiteImpl.java PersistenceBrokerSSOProvider.java components/sso/src/test/org/apache/jetspeed/sso TestSSOComponent.java components/sso/src/java/META-INF sso_repository.xml Log: Fix for SSO Entries where not unique to a user/site which required an new association table (SSO_SITE_TO_REMOTE) Re factored the code for the API to include the mapping table Updated Unit test Revision Changes Path 1.5 +16 -3 jakarta-jetspeed-2/components/sso/src/java/org/apache/jetspeed/sso/impl/SSOSiteImpl.java Index: SSOSiteImpl.java =================================================================== RCS file: /home/cvs/jakarta-jetspeed-2/components/sso/src/java/org/apache/jetspeed/sso/impl/SSOSiteImpl.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- SSOSiteImpl.java 30 Nov 2004 18:19:10 -0000 1.4 +++ SSOSiteImpl.java 4 Dec 2004 22:28:19 -0000 1.5 @@ -43,8 +43,9 @@ private boolean isAllowUserSet; private boolean isCertificateRequired; - private Collection credentials = new Vector();//= new ArrayList(0); - private Collection principals = new Vector();// = new ArrayList(0); + private Collection credentials = new Vector(); + private Collection principals = new Vector(); + private Collection remotePrincipals = new Vector(); /** * @@ -246,4 +247,16 @@ } } + /** + * @return Returns the remotePrincipals. + */ + public Collection getRemotePrincipals() { + return remotePrincipals; + } + /** + * @param remotePrincipals The remotePrincipals to set. + */ + public void setRemotePrincipals(Collection remotePrincipals) { + this.remotePrincipals = remotePrincipals; + } } 1.9 +179 -106 jakarta-jetspeed-2/components/sso/src/java/org/apache/jetspeed/sso/impl/PersistenceBrokerSSOProvider.java Index: PersistenceBrokerSSOProvider.java =================================================================== RCS file: /home/cvs/jakarta-jetspeed-2/components/sso/src/java/org/apache/jetspeed/sso/impl/PersistenceBrokerSSOProvider.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- PersistenceBrokerSSOProvider.java 3 Dec 2004 23:53:33 -0000 1.8 +++ PersistenceBrokerSSOProvider.java 4 Dec 2004 22:28:19 -0000 1.9 @@ -83,18 +83,32 @@ return false; // no entry for site } - // Get the principal from the subject BasePrincipal principal = (BasePrincipal)SecurityHelper.getBestPrincipal(subject, UserPrincipal.class); String fullPath = principal.getFullPath(); - // Check if the principal has any remote principals - Collection remotePrincipals = getRemotePrincipalsForPrincipal(ssoSite, fullPath); + // Get remotePrincipals for Site and match them with the Remote Principal for the Principal attached to site + Collection principalsForSite = ssoSite.getPrincipals(); + Collection remoteForSite = ssoSite.getRemotePrincipals(); + + // If any of them don't exist just return + if (principalsForSite == null || remoteForSite== null ) + return false; // no entry + + Collection remoteForPrincipals = getRemotePrincipalsForPrincipal(principalsForSite, fullPath); - if (remotePrincipals == null || remotePrincipals.size() < 1) - return false; // No remote credentials for Principal + if ( remoteForPrincipals == null) + return false; // no entry + + // Get remote Principal that matches the site and the principal + if (FindRemoteMatch(remoteForPrincipals, remoteForSite) == null ) + { + return false; // No entry + } else - return true; // User has credentials for site + { + return true; // Has an entry + } } /* (non-Javadoc) @@ -148,10 +162,29 @@ // Add an entry for the principal to the site if it doesn't exist SSOPrincipal principal = this.getPrincipalForSite(ssoSite, fullPath); + if (principal == null ) + { + principal = getSSOPrincipa(fullPath); + ssoSite.addPrincipal(principal); + } + else + { + // Check if the entry the user likes to update exists already + Collection remoteForSite = ssoSite.getRemotePrincipals(); + if ( remoteForSite != null) + { + if (FindRemoteMatch(principal.getRemotePrincipals(), remoteForSite) != null ) + { + // Entry exists can't to an add has to call update + throw new SSOException(SSOException.REMOTE_PRINCIPAL_EXISTS_CALL_UPDATE); + } + } + } + if (principal == null) throw new SSOException(SSOException.FAILED_ADDING_PRINCIPAL_TO_MAPPING_TABLE_FOR_SITE); - // Create a remote principal and add it to the principal + // Create a remote principal and credentials InternalUserPrincipalImpl remotePrincipal = new InternalUserPrincipalImpl(remoteUser); remotePrincipal.setFullPath("/sso/user/"+ principalName + "/" + remoteUser); @@ -164,9 +197,12 @@ remotePrincipal.setCredentials(new ArrayList(0)); remotePrincipal.getCredentials().add( credential); - - - principal.addRemotePrincipal(remotePrincipal); + + // Add it to Principals remotePrincipals list + principal.addRemotePrincipal(remotePrincipal); + + // Update the site remotePrincipals list + ssoSite.getRemotePrincipals().add(remotePrincipal); // Update database and reset cache try @@ -182,7 +218,6 @@ this.mapSite.put(site, ssoSite); // Clear cache //this.mapSite.clear(); - } /* (non-Javadoc) @@ -207,17 +242,31 @@ try { - // Remove remote principal from the association table - remotePrincipal = removeRemotePrincipalForPrincipal(ssoSite, fullPath); + // Get remotePrincipals for Site and match them with the Remote Principal for the Principal attached to site + Collection principalsForSite = ssoSite.getPrincipals(); + Collection remoteForSite = ssoSite.getRemotePrincipals(); + + // If any of them don't exist just return + if (principalsForSite == null || remoteForSite== null ) + throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE); - // Remove the principal association - principal = this.getPrincipalForSite(ssoSite, fullPath); - if ( principal != null ) - ssoSite.getPrincipals().remove(principal); - - // Remove Remote principal and associated credential from persistence store - if (remotePrincipal != null) - getPersistenceBrokerTemplate().delete(remotePrincipal); + Collection remoteForPrincipals = getRemotePrincipalsForPrincipal(principalsForSite, fullPath); + + if ( remoteForPrincipals == null) + throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE); + + // Get remote Principal that matches the site and the principal + if ((remotePrincipal = FindRemoteMatch(remoteForPrincipals, remoteForSite)) == null ) + { + throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE); + } + + // Update assocation tables + ssoSite.getRemotePrincipals().remove(remotePrincipal); + getRemotePrincipalsForPrincipal(principalsForSite, fullPath).remove(remotePrincipal); + + // delete the remote Principal from the SECURITY_PRINCIPAL table + getPersistenceBrokerTemplate().delete(remotePrincipal); } catch(SSOException ssoex) @@ -230,7 +279,7 @@ throw new SSOException(SSOException.FAILED_STORING_SITE_INFO_IN_DB + e.toString() ); } - // Update database and reset cache + // Update database try { getPersistenceBrokerTemplate().store(ssoSite); @@ -272,15 +321,25 @@ String fullPath = ((BasePrincipal)SecurityHelper.getBestPrincipal(subject, UserPrincipal.class)).getFullPath(); String principalName = ((BasePrincipal)SecurityHelper.getBestPrincipal(subject, UserPrincipal.class)).getName(); - // Get collection of remote principals and find a match for the one to remove - Collection remotePrincipals = getRemotePrincipalsForPrincipal(ssoSite, fullPath); - if ( remotePrincipals == null || remotePrincipals.size() < 1) - throw new SSOException(SSOException.REQUESTED_PRINCIPAL_DOES_NOT_EXIST); - - // User can have one remote user per site - Iterator itRemotePrincipals = remotePrincipals.iterator(); - remotePrincipal = (InternalUserPrincipal)itRemotePrincipals.next(); + // Get remotePrincipals for Site and match them with the Remote Principal for the Principal attached to site + Collection principalsForSite = ssoSite.getPrincipals(); + Collection remoteForSite = ssoSite.getRemotePrincipals(); + + // If any of them don't exist just return + if (principalsForSite == null || remoteForSite== null ) + throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE); + + Collection remoteForPrincipals = getRemotePrincipalsForPrincipal(principalsForSite, fullPath); + if ( remoteForPrincipals == null) + throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE); + + // Get remote Principal that matches the site and the principal + if ((remotePrincipal = FindRemoteMatch(remoteForPrincipals, remoteForSite)) == null ) + { + throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE); + } + // Update principal information remotePrincipal.setFullPath("/sso/user/"+ principalName + "/" + remoteUser); InternalCredential credential = (InternalCredential)remotePrincipal.getCredentials().iterator().next(); @@ -299,11 +358,7 @@ { e.printStackTrace(); throw new SSOException(SSOException.FAILED_STORING_SITE_INFO_IN_DB + e.toString() ); - } - - // Clear cache - // this.mapSite.clear(); - + } } /* @@ -366,60 +421,43 @@ private SSOContext getCredential(SSOSite ssoSite, String fullPath) { InternalCredential credential = null; + InternalUserPrincipal remotePrincipal = null; String remoteUser = null; String remoteFullPath = null; + + // Get remotePrincipals for Site and match them with the Remote Principal for the Principal attached to site + Collection principalsForSite = ssoSite.getPrincipals(); + Collection remoteForSite = ssoSite.getRemotePrincipals(); + + // If any of them don't exist just return + if (principalsForSite == null || remoteForSite== null ) + return null; // no entry + + Collection remoteForPrincipals = getRemotePrincipalsForPrincipal(principalsForSite, fullPath); - /* Error checking - * 1) should have at least one principal - * - * If one of the above fails return null wich means that the user doesn't have credentials for that site - */ - Collection principals = ssoSite.getPrincipals(); + if ( remoteForPrincipals == null) + return null; // no entry - if ( principals == null ) + // Get remote Principal that matches the site and the principal + if ((remotePrincipal = FindRemoteMatch(remoteForPrincipals, remoteForSite)) == null ) { - return null; + return null; // No entry } - - // Iterate over the principals and extract the principal id for the given full path - SSOPrincipal principal = null; - - Iterator itPrincipals = principals.iterator(); - while (itPrincipals.hasNext() && principal == null /*not found yet*/) + else { - SSOPrincipal tmp = (SSOPrincipal)itPrincipals.next(); - if ( tmp != null - && tmp.getFullPath().compareToIgnoreCase(fullPath) == 0 - && tmp.getSiteID() == ssoSite.getSiteId()) + // Has an entry + if ( remotePrincipal.getCredentials() != null) + credential = (InternalCredential)remotePrincipal.getCredentials().iterator().next(); + + // Error checking -- should have a credential at this point + if ( credential == null) { - // Found it stop iteration - principal = tmp; + System.out.println("Warning: Remote User " + remotePrincipal.getFullPath() + " doesn't have a credential"); + return null; } } - if ( principal == null) - return null; // No principal found for that site - - // Extract the remote principal - Collection remotePrincipals = principal.getRemotePrincipals(); - if (remotePrincipals == null || remotePrincipals.size() < 1) - return null; // no remote principals - - InternalUserPrincipal remotePrincipal = (InternalUserPrincipal)remotePrincipals.iterator().next(); - - // Get credentail for this remote user - if ( remotePrincipal.getCredentials() != null) - credential = (InternalCredential)remotePrincipal.getCredentials().iterator().next(); - - // Error checking -- should have a credential at this point - if ( credential == null) - { - System.out.println("Warning: Remote User " + remotePrincipal.getFullPath() + " doesn't have a credential"); - return null; - } - - - // Create new context + // Create new context String name = remotePrincipal.getFullPath(); int ix = name.lastIndexOf('/'); if ( ix != -1) @@ -479,36 +517,30 @@ } } - // Not yest in the site list. Add it but make sure that a user exists - if ( principal == null) - { - Criteria filter = new Criteria(); - filter.addEqualTo("fullPath", fullPath); - - QueryByCriteria query = QueryFactory.newQuery(SSOPrincipalImpl.class, filter); - Collection principals = getPersistenceBrokerTemplate().getCollectionByQuery(query); - - if ( principals != null && principals.isEmpty() != true) + return principal; + } + + private SSOPrincipal getSSOPrincipa(String fullPath) + { + // FInd if the principal exists in the SECURITY_PRINCIPAL table + SSOPrincipal principal = null; + + Criteria filter = new Criteria(); + filter.addEqualTo("fullPath", fullPath); + + QueryByCriteria query = QueryFactory.newQuery(SSOPrincipalImpl.class, filter); + Collection principals = getPersistenceBrokerTemplate().getCollectionByQuery(query); + + if ( principals != null && principals.isEmpty() != true) + { + Iterator itPrincipals = principals.iterator(); + // Get the site from the collection. There should be only one entry (uniqueness) + if (itPrincipals.hasNext()) { - Iterator itPrincipals = principals.iterator(); - // Get the site from the collection. There should be only one entry (uniqueness) - if (itPrincipals.hasNext()) - { - principal = (SSOPrincipal) itPrincipals.next(); - try - { - // Set the Site ID for this principal - principal.setSiteID(ssoSite.getSiteId()); - ssoSite.addPrincipal(principal); - } - catch (SSOException ssoex) - { - System.out.println("ERROR-SSO: Failed adding principal to principla map. Error: " + ssoex.getMessage()); - } - } + principal = (SSOPrincipal) itPrincipals.next(); } - } - + } + return principal; } @@ -572,5 +604,46 @@ } throw new SSOException(SSOException.REQUESTED_PRINCIPAL_DOES_NOT_EXIST); + } + + /* + * + * + */ + private InternalUserPrincipal FindRemoteMatch(Collection remoteForPrincipals, Collection remoteForSite) + { + // Iterate over the lists and find match + Iterator itRemoteForPrincipals = remoteForPrincipals.iterator(); + while ( itRemoteForPrincipals.hasNext()) + { + InternalUserPrincipal remoteForPrincipal = (InternalUserPrincipal)itRemoteForPrincipals.next(); + + // Find a match in the site list + Iterator itRemoteForSite = remoteForSite.iterator(); + while ( itRemoteForSite.hasNext()) + { + InternalUserPrincipal tmp = (InternalUserPrincipal)itRemoteForSite.next(); + + if ( tmp.getPrincipalId() == remoteForPrincipal.getPrincipalId() ) + return remoteForPrincipal; + } + } + // No match found + return null; + } + + private Collection getRemotePrincipalsForPrincipal(Collection principalsForSite, String fullPath) + { + if (principalsForSite == null ) + return null; + + Iterator itPrincipalsForSite = principalsForSite.iterator(); + while (itPrincipalsForSite.hasNext()) + { + SSOPrincipal principal = (SSOPrincipal)itPrincipalsForSite.next(); + if ( principal.getFullPath().compareToIgnoreCase(fullPath) == 0) + return principal.getRemotePrincipals(); + } + return null; } } 1.7 +34 -3 jakarta-jetspeed-2/components/sso/src/test/org/apache/jetspeed/sso/TestSSOComponent.java Index: TestSSOComponent.java =================================================================== RCS file: /home/cvs/jakarta-jetspeed-2/components/sso/src/test/org/apache/jetspeed/sso/TestSSOComponent.java,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- TestSSOComponent.java 4 Dec 2004 05:11:38 -0000 1.6 +++ TestSSOComponent.java 4 Dec 2004 22:28:19 -0000 1.7 @@ -49,8 +49,10 @@ * test url for this UnitTest */ static private String TEST_URL= "http://localhost/jetspeed"; + static private String TEST_URL2= "http://localhost/jetspeed-2"; static private String TEST_USER= "joe"; static private String REMOTE_USER= "remoteJS"; + static private String REMOTE_USER2= "remoteJS-2"; static private String REMOTE_PWD_1 = "remote_1"; static private String REMOTE_PWD_2 = "remote_2"; @@ -99,11 +101,12 @@ * Test user root. * </p> */ - public void testSSO() throws Exception + /* public void testSSO() throws Exception { // TODO: FIXME: test fails on HSQL Oracle } - public void XXXtestSSO() throws Exception + */ + public void testSSO() throws Exception { // Create a user try @@ -143,9 +146,37 @@ System.out.println("SSO Credential found for user:" + TEST_USER+ " site: " + TEST_URL); } + // Add another remote principal for the same user + if ( ssoBroker.hasSSOCredentials(subject, TEST_URL2) == false) + { + System.out.println("No SSO Credential for user:" + TEST_USER+ " site: " + TEST_URL2); + + // Add credential + try + { + ssoBroker.addCredentialsForSite(subject, REMOTE_USER2, TEST_URL2,REMOTE_PWD_1); + System.out.println("SSO Credential added for user:" + TEST_USER+ " site: " + TEST_URL2); + } + catch(SSOException ssoex) + { + System.out.println("SSO Credential add FAILED for user:" + TEST_USER+ " site: " + TEST_URL2); + ssoex.printStackTrace(); + throw new Exception(ssoex.getMessage()); + } + } + else + { + System.out.println("SSO Credential found for user:" + TEST_USER+ " site: " + TEST_URL2); + } + + // Test if the credential where persisted + // Test credential update SSOContext ssocontext = ssoBroker.getCredentials(subject, TEST_URL); - System.out.println("SSO Credential: User:" + ssocontext.getUserName() + " Password: " + ssocontext.getPassword()); + System.out.println("SSO Credential: User:" + ssocontext.getUserName() + " Password: " + ssocontext.getPassword()+ " for site: " + TEST_URL); + + SSOContext ssocontext2 = ssoBroker.getCredentials(subject, TEST_URL2); + System.out.println("SSO Credential: User:" + ssocontext.getUserName() + " Password: " + ssocontext.getPassword() + " for site: " + TEST_URL2); try { 1.5 +14 -0 jakarta-jetspeed-2/components/sso/src/java/META-INF/sso_repository.xml Index: sso_repository.xml =================================================================== RCS file: /home/cvs/jakarta-jetspeed-2/components/sso/src/java/META-INF/sso_repository.xml,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- sso_repository.xml 3 Dec 2004 21:59:15 -0000 1.4 +++ sso_repository.xml 4 Dec 2004 22:28:19 -0000 1.5 @@ -157,6 +157,20 @@ <fk-pointing-to-this-class column="SITE_ID"/> <fk-pointing-to-element-class column="PRINCIPAL_ID"/> </collection-descriptor> + <collection-descriptor + name="remotePrincipals" + element-class-ref="org.apache.jetspeed.security.om.impl.InternalUserPrincipalImpl" + proxy="true" + refresh="true" + auto-retrieve="true" + auto-update="object" + auto-delete="object" + indirection-table="SSO_SITE_TO_REMOTE" + > + <documentation>This is the reference to principals.</documentation> + <fk-pointing-to-this-class column="SITE_ID"/> + <fk-pointing-to-element-class column="PRINCIPAL_ID"/> + </collection-descriptor> </class-descriptor> </descriptor-repository>
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]