12 Replies Latest reply on Oct 24, 2011 6:59 AM by henk53

    Custom Principal class problem. SessionContext always return

    misqu23

      Hi

      I need to store in the principal class not only name of the principal but also id from database. So I have created my own login module which inherits from the jboss DatabaseServerLoginModule. In the method getUsersPassword I also get the id of the user from the db. Here is the code snipet :

       password = rs.getString(1);
       password = convertRawPassword(password);
       if (trace)
       log.trace("Obtained user password");
       Long id = rs.getLong(2);
       if (getIdentity() instanceof SmartOfficePrincipal) {
       log.info("Setting id to the principal");
       ((SmartOfficePrincipal)getIdentity()).setId(id);
       }
      


      In login-config.xml I have configured login module to use my own principal implementation.
      login-config.xml :
       <application-policy name="smartoffice">
       <authentication>
       <login-module code="org.jboss.security.ClientLoginModule" flag="required">
       <module-option name="restore-login-identity">true</module-option>
       </login-module>
       <login-module code="com.foo.SmartOfficeDatabaseLoginModule" flag="required">
       <module-option name="principalClass">com.foo.SmartOfficePrincipal</module-option>
       <module-option name="dsJndiName">java:/smartofficeDS</module-option>
       <module-option name="principalsQuery">SELECT PASSWORD,ID FROM SMR_USERS_ASSIGN WHERE LOGIN=?</module-option>
       <module-option name="rolesQuery">SELECT ROLES.ROLE, 'Roles' FROM SMR_USER_ROLES AS ROLES,
       SMR_USERS_ASSIGN AS USERS WHERE USERS.LOGIN = ? AND ROLES.
      USER_ID = USERS.ID</module-option>
       <module-option name="hashAlgorithm">MD5</module-option>
       <module-option name="unauthenticatedIdentity">anonymous</module-option>
       </login-module>
       </authentication>
       </application-policy>
      


      My principal class :
      public class SmartOfficePrincipal extends SimplePrincipal implements Serializable {
      
       private static final long serialVersionUID = 2079488098348121376L;
      
       private Long id;
      
       public SmartOfficePrincipal(String name) {
       super(name);
       }
      
       public void setId(Long id) {
       this.id = id;
       }
      
       public Long getId() {
       return id;
       }
      
       @Override
       public int hashCode() {
       final int prime = 31;
       int result = super.hashCode();
       result = prime * result + ((id == null) ? 0 : id.hashCode());
       return result;
       }
      
       @Override
       public boolean equals(Object obj) {
       if (this == obj)
       return true;
       if (!super.equals(obj))
       return false;
       if (getClass() != obj.getClass())
       return false;
       SmartOfficePrincipal other = (SmartOfficePrincipal) obj;
       if (id == null) {
       if (other.id != null)
       return false;
       } else if (!id.equals(other.id))
       return false;
       return true;
       }
      }
      


      Everything works fine I can login to the application but when I try to get the callerPrincipal from the SessionContext object I get SimplePrincipal instance.
      I can't cast to SmartOfficePrincipal.

      Also when I try to get principal in the entitylistener using the following statement :
       Principal principal = SecurityAssociation.getPrincipal();
      


      I get the instance of SimplePrincipal class. I need user id because in entity listener i would like to set the user who have last modify object or created.
      So I don't have to remember to set up this by hand in the code.

      Also in my aspects I prefer to use the user id.

      What am I doing wrong ?


      Thanks a lot.

      Martin

        • 1. Re: Custom Principal class problem. SessionContext always re
          misqu23

          I guess it is a bug in JBoss.

          When I call

          SecurityAssociation.getSubject().getPrincipals()
          

          I get the set of the principals where the first element in this set is the my own implementation of the principal class and that's right, subject gets filled with principals in the LoginModule commit method.

          However when I call Sec
          SecurityAssociation.getPrincipal();
          or
          SecurityAssociation.getCallerPrincipal();
          or
          sessionContext.getCallerPrincipal();
          

          I always get the instance of the SimplePrincipal.

          It seems that my loginModule works well, but during the propagation of the caller principal jboss is ignoring my principal class and sets his default.

          Martin

          • 2. Re: Custom Principal class problem. SessionContext always re
            sanches

            Hello everybody,

             

            I have the same situation.

            I've written custom login module MyLoginModule on top of org.jboss.security.auth.spi.UsernamePasswordLoginModule

            My login module creates instance of the custom implementation MyPrincipal of java.security.Principal

             

            Although I always get instance of SimplePrincipal when try to obtain the caller of the EJB from within this EJB:

             

            @Resource

            protected SessionContext sctx;

            ...
            sctx.getCallerPrincipal();  // returns SimplePrincipal instead of MyPrincipal

             

             

            But call to

            SecurityAssociation.getSubject().getPrincipals();

            returns set which contains correct instance of MyPrinciple

            The following entry appears in the logs then:

            WARN  [org.jboss.security.SecurityAssociation] (WorkerThread#0[10.119.0.140:49777]) You are using deprecated api to getSubject. Use security context based approach

             

            Could somebody confirm this is an unresolved bug actually please?

            JBoss 5.1.0GA

             

            Thanks,

            Alexander.

             

            P.S.

            There is an article about writing custom principles at http://community.jboss.org/wiki/UsingCustomPrincpalsWith

            It describes how to compose custom principle, but does not have exaple of retrieving it, probably that would be useful addition.

            • 3. Re: Custom Principal class problem. SessionContext always re
              misqu23

              Hi

               

              I have created class ServerUtils with the folllowing static which properly returns principal :

               

               

              import org.jboss.security.SecurityAssociation;
              import org.jboss.security.auth.spi.Util;
               
              public class ServerUtils {
               
                   public static SmartOfficePrincipal getPrincipal() {
                        if (SecurityAssociation.getSubject().getPrincipals(SmartOfficePrincipal.class).toArray().length == 0) 
                             return null;
                        return (SmartOfficePrincipal) SecurityAssociation.getSubject().getPrincipals(SmartOfficePrincipal.class).toArray()[0];
                   }
               
              ...
              }
              
              

               

               

              And it works perfectly

              • 4. Re: Custom Principal class problem. SessionContext always re
                sanches

                Hi, Marcin.

                 

                That's right. Static method of SecurityAssociation does return proper principal.

                The trouble described here is the wrong principal being returned by the method of auto injected SessionContext.

                 

                Alexander.

                • 5. Re: Custom Principal class problem. SessionContext always re
                  marnold

                  I have also hit this bug (JBoss 5.1 GA).  Annoying - I will have to write JBoss specific code to workaround.

                   

                  Can anybody confirm that it is a recognised bug?  Will it be fixed?

                  • 6. Re: Custom Principal class problem. SessionContext always return
                    anil.saldhana

                    As of JBoss5.x, SecurityAssociation is deprecated.

                     

                    SecurityContext API is preferred.   SecurityContextAssociation.getSecurityContext()

                     

                    securityContext.getUtil().getUserPrincipal()

                    • 7. Re: Custom Principal class problem. SessionContext always return
                      sanches

                      ANIL SALDHANA

                      Thank you for that notification. That's just great, but this is still not J2EE compliant code.

                      Are you aware of the plans for fixing the following notation?

                      @Resource

                      protected SessionContext sctx;

                      ...
                      sctx.getCallerPrincipal();  // returns SimplePrincipal instead of MyPrincipal
                      • 8. Re: Custom Principal class problem. SessionContext always return
                        anil.saldhana

                        Custom Principal is never part of any Java EE specs.

                         

                        Here is a bug report for investigation and potential fix:

                        https://jira.jboss.org/browse/JBAS-8427

                        • 9. Re: Custom Principal class problem. SessionContext always return
                          mmoyses

                          To get the custom principal returned you will need to update EJB3 jars as there is a known issue (https://jira.jboss.org/browse/EJBTHREE-1756) and also have your identity (the custom principal) added to a group named CallerPrincipal in the Subject. See http://community.jboss.org/wiki/UsingCustomPrincpalsWith for an example login module (more specifically the getRoleSets method).

                          • 10. Re: Custom Principal class problem. SessionContext always re
                            sirwayne

                            I have the same problem in JBoss 6.0.0 final. I get alwas the SimplePrincipal

                             

                            Interceptor

                             

                             

                            @Interceptor
                            public class MyInterceptor
                            
                            @Resource    
                            private SessionContext sessionContext;    
                            
                            @AroundInvoke     
                            public Object injectMap(InvocationContext ic) throws Exception {   
                            
                                 System.out.println(sessionContext.getCallerPrincipal());   Always SimplePrincipal      
                                 System.out.println(SecurityContextAssociation.getSecurityContext().getUtil().getCredential());    
                                 System.out.println(SecurityContextAssociation.getSecurityContext().getUtil().getUserPrincipal());   
                                 MyPrincipal ppPrincipal = (MyPrincipal) SecurityContextAssociation.getSecurityContext().getUtil().
                                 getSubject().getPrincipals(MyPrincipal.class); 
                            

                             

                            TesLogin

                             

                             

                            public class TestLogin extends AbstractServerLoginModule { 
                            
                            protected MyPrincipal principal;
                            protected String sessionId; 
                            
                            public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
                                 super.initialize(subject, callbackHandler, sharedState, options); 
                                 sessionId = UUID.randomUUID().toString(); 
                                 try { 
                                      principal = (MyPrincipal) createIdentity(getUsername()); 
                                 } catch (Exception e) 
                                 { // TODO Auto-generated catch block e.printStackTrace(); }
                            }
                            @Override 
                            protected Principal createIdentity(String name) throws Exception { 
                                 return new MyPrincipal(sessionId, name); 
                            } 
                            
                            @Override 
                            protected Principal getIdentity()
                            { 
                                 return principal; 
                            }
                            
                             @Override 
                            protected Group[] getRoleSets() throws LoginException { 
                                 SimpleGroup rolesGroup = new SimpleGroup(&quot;Roles&quot;); 
                                 rolesGroup.addMember(getIdentity()); 
                                 Group[] roleSets = {rolesGroup}; return roleSets; 
                            }  
                            
                            protected String getUsername() throws LoginException   { 
                                 return "admin";
                            }
                            

                             

                             

                            public class MyPrincipal implements Principal{
                            
                            private String sessionId; 
                            private String name; 
                            
                            public PPPrincipal(String sessionId, String name) 
                            { 
                            this.sessionId = sessionId; 
                            this.name = name; 
                            } 
                            
                            @Override public String getName()
                             { return name; } 
                            
                            public String getSessionId() { 
                                 return sessionId; 
                            } 
                            } 
                            
                            
                            

                             

                             

                            What's wrong?

                            • 11. Re: Custom Principal class problem. SessionContext always return
                              superdev

                              I have exactly the same problem with Micheal, JBoss 6.0.0 final. always get the SimplePrincipal instead of my Cumtom Principal, has anyone successfully get Cumtom Principal from SessionContext under JBoss 6.0.0 final ?

                              • 12. Re: Custom Principal class problem. SessionContext always return
                                henk53

                                superDev superDev wrote:

                                 

                                I have exactly the same problem with Micheal, JBoss 6.0.0 final. always get the SimplePrincipal instead of my Cumtom Principal, has anyone successfully get Cumtom Principal from SessionContext under JBoss 6.0.0 final ?

                                 

                                It seems this is simply impossible. It's a LONG standing bug in JBoss AS and there doesn't seem to be any hope of this ever getting fixed.

                                 

                                Meanwhile, it seems the suggestion offered here is a workaround: http://community.jboss.org/message/141598#141598

                                 

                                Via the PolicyContext you can get the original Subject that the login module (parent) creates, and from that you can get your Custom Principal. I'm going to try this method. If anyone knows of any bad side-effects with using this method, please let me know.