8 Replies Latest reply on Sep 4, 2013 8:15 AM by xiang yingbing

    How to flush JAAS Cache from war application?

    xiang yingbing Master

      Dear all,

       

      (1). After My EJB Client connects to my EJB(packed in an ear) deployed JBoss AS 7, I change its roles(add or remove), the change take effect immediately after I excecute bellow method on server side.

       

      (2). But, After one user loggs in my web application(packed in an ear), I change its roles(add or remove), the change does NOT take effect immediately after I excecute bellow same method on server side. Why? How to resolve this problem?

       

       

       

       

       

      Now, Let me discribe my problem in details.

       

      1. My Entities

       

      (a) DB Relation:

                    entities_relation.png

       

      (b) Codes:

       

      @Entity
      public class User implements Serializable{
          private Long id;
          private String username;//登录名
          private String hashedPassword;
          private Boolean activated = false;
          private Boolean locked = false;
          //..
          private Set<UserGroup> userGroups;
          //...
          @ManyToMany(targetEntity=UserGroup.class,fetch = FetchType.LAZY)
          @JoinTable(name               = "User_UserGroup",
                     joinColumns        = @JoinColumn(name="user_id"),
                     inverseJoinColumns = @JoinColumn(name="usergroup_id")
              )
          public Set<UserGroup> getUserGroups() {
              return userGroups;
          }
          //...
      }
      
      
      @Entity
      public class UserGroup implements Serializable {
          private Integer id;
          private String name;
          private Set<JaasRole> jaasRoles;
          ...
          @ManyToMany(targetEntity=JaasRole.class,fetch = FetchType.LAZY)
          @JoinTable(name               = "UserGroup_JaasRole",
                     joinColumns        = @JoinColumn(name="usergroup_id"),
                     inverseJoinColumns = @JoinColumn(name="jaasrole_id")
              )
          public Set<JaasRole> getJaasRoles() {
              return jaasRoles;
          }
          //...
      }
      
      
      @Entity
      public class JaasRole implements Serializable {
          private Integer id;
          private String name;
          private String displayName = "";
      }
      

       

       

       

       

      2. DB Records:

       

      2.1 JaasRole

                        jaasrole.png

       

       

      2.2 UserGroup

       

       

                              usergroup.png

       

       

       

      2.3 UserGroup_JaasRole

                           usergroup_jaasrole.png

       

       

       

       

      2.4 User

                             user.png

       

       

      2.5 User_UserGroup

       

       

                       user_usergroup.png

       

       

       

      3. Security domain configuration in standalone.xml

       

      <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule" flag="required">

                                  <module-option name="password-stacking" value="useFirstPass"/>

                                  <module-option name="dsJndiName" value="java:jboss/datasources/ybxiangForumMySqlDataSource"/>

                                  <module-option name="principalsQuery" value="SELECT hashedPassword FROM User WHERE username=? and activated=true and locked=false"/>

                                  <module-option name="rolesQuery" value="SELECT DISTINCT r.name, 'Roles' FROM User u, User_UserGroup ug, UserGroup_JaasRole gr, JaasRole r WHERE u.id=ug.user_id AND ug.usergroup_id=gr.usergroup_id AND gr.jaasrole_id=r.id AND u.username=?"/>

                                  <module-option name="hashAlgorithm" value="SHA-256"/>

                                  <module-option name="hashEncoding" value="Base64"/>

                                  <module-option name="hashCharset" value="UTF-8"/>

                                  <module-option name="unauthenticatedIdentity" value="guest"/>

                              </login-module>

       

       

       

      4. My page list.xhtml

      test link: http://127.0.0.1/faces/list.xhtml?mid=318

       

      ...




      <h:panelGroup layout="block" rendered="#{request.isUserInRole('318')}">



      <h:form id="form">




      bla bla...



      </h:form>



      </h:panelGroup>

      ...

       

       

      Now, the user(id=10010,name = 'tester') belong to UserGroup(id=2002) which is authorized with JAAS Role(id=10318, name='318').

       

       

       

       

      5. Test case 1

       

      5.1 The user "tester" log in and visit page:  http://127.0.0.1/faces/list.xhtml?mid=318

            He can see the "bla bla...".

            This is what I expect.

       

       

      5.2 Now, I (the admin) run bellow java codes to delete tester's usergroup and flush jaas cache:

       


      @RolesAllowed({KnownJaasRoles.ADMINISTRATOR})

      public void deleteUserGroup(Long userId, Integer userGroupId){


      em.createNativeQuery(User.NativeQuery_jpql_DeleteUserGroup)


      .setParameter(User.NativeQuery_param_DeleteUserGroup_userId, userId)


      .setParameter(User.NativeQuery_param_DeleteUserGroup_userGroupId, userGroupId)


      .executeUpdate();


      //


      User u = em.find(User.class, userId);





      jaasCacheSession.flushJavaarmForumSecurityDomainJaasCache(u.getUsername());

      }

       

       

      @RolesAllowed({KnownJaasRoles.ADMINISTRATOR})
      
      public void flushJaasCache(String securityDomain, String jaasUsername) {
      
      
      try {
      
      
      
      Object[] params = { jaasUsername };
      
      
      
      String[] signature = { "java.lang.String" };
      
      
      
      
      
      MBeanServerConnection mbeanServerConnection = java.lang.management.ManagementFactory.getPlatformMBeanServer();
      
      
      
      ObjectName mbeanName = new ObjectName("jboss.as:subsystem=security,security-domain="+ securityDomain);
      
      
      
      mbeanServerConnection.invoke(mbeanName, "flushCache", params,signature);
      
      
      } catch (Exception e) {
      
      
      
      throw new SecurityException(e);
      
      
      }
      
      }
      
      @RolesAllowed({KnownJaasRoles.ADMINISTRATOR})
      
      public void flushJavaarmForumSecurityDomainJaasCache(String jaasUsername){
      
      
      flushJaasCache(coreService.getJavaarmForumJaasSecurityDomain(),jaasUsername);
      
      }
      
      

       

       

       

       

      5.3 Result:

       

      (a) The record(10010, 20002) has been removed from "user_usergroup"

       

      (b) But, the tester can still see "bla bla..." in list.xhtml( http://127.0.0.1/faces/list.xhtml?mid=318 )

      This is NOT What I expect!

       

      Now, the tester log off, log in again and visit list.xhtml( http://127.0.0.1/faces/list.xhtml?mid=318 ),

      This time, he can NOT see the "bla bla..."

      This is What I expect.

       

       

       

      6. Test case 2 (no problem)

      Let's restore steps 1~4,

       

      6.1 The user "tester" log in and visit page:  http://127.0.0.1/faces/list.xhtml?mid=318

            He can see the "bla bla...".

            This is what I expect.

       

      6.2 Now, I (the admin) run bellow java codes to delete tester's usergroup( do NOT flush jaas cache):

       


      @RolesAllowed({KnownJaasRoles.ADMINISTRATOR})

      public void deleteUserGroup(Long userId, Integer userGroupId){


      em.createNativeQuery(User.NativeQuery_jpql_DeleteUserGroup)


      .setParameter(User.NativeQuery_param_DeleteUserGroup_userId, userId)


      .setParameter(User.NativeQuery_param_DeleteUserGroup_userGroupId, userGroupId)


      .executeUpdate();


      //


      User u = em.find(User.class, userId);


      //  jaasCacheSession.flushJavaarmForumSecurityDomainJaasCache(u.getUsername());

      }

       

       

       

       

       

      6.3 Result

      Now, the tester do NOT log off, just close all browsers.

      Then, he login and visit list.xhtml( http://127.0.0.1/faces/list.xhtml?mid=318 ),

      This time, he can still see the "bla bla..."

      This is what I expect, because the cache is NOT flushed.

       

       

       

      7. My Question/Problem

       

      ONLY 5.3 is NOT what I expect.

       

      It seems that 'tester''s jaas roles is NOT flushed immediately/successfully in step 5.2, because it does NOT take effect immediately in step 5.3 (b).

       

       

      Is my description clear?

        • 1. Re: How to flush JAAS Cache from war application?
          jaikiran pai Master

          xiang yingbing wrote:

           

           

          2. But, After one user loggs in my web application(packed in an ear), I change its roles(add or remove), the change does NOT take effect immediately after I excecute bellow same method on server side. Why? How to resolve this problem?

           

           

          What kind of user authentication/authorization is involved in that application?

          • 2. Re: How to flush JAAS Cache from war application?
            xiang yingbing Master

            Dear pai,

             

                       I described my problem in details. Please read it again.

                       Thank you very much.

             

            This is my last problem abou JAAS CACHE.

            After this problem is fixed, I will summarize all JAAS related configuration/code in jboss as 7 and post them as a new article in jboss forum.

            I hope this can help other guys.

            • 3. Re: How to flush JAAS Cache from war application?
              aquee Newbie

              I am facing same problem.

              I have similar configuration and code.

               

              Have you find a solution to this problem xiang?

              • 4. Re: How to flush JAAS Cache from war application?
                xiang yingbing Master

                NOT yet now.

                EJB JAAS cache can be refreshed and take effect immediately.

                 

                So, I think there is bug in tomcat JAAS cache.

                I will study this issue when I finished my articles.

                If I find solution, I will post it here.

                • 5. Re: How to flush JAAS Cache from war application?
                  aquee Newbie

                  Thank you for your immediate reply Xiang.

                  Can you pleas share a code snippet to refreshed EJB JAAS Cache?

                  • 6. Re: How to flush JAAS Cache from war application?
                    xiang yingbing Master

                    Of course:

                     

                    @RolesAllowed({KnownJaasRoles.ADMINISTRATOR})
                    private void flushJaasCache(String securityDomain){
                       try {
                       javax.management.MBeanServerConnection mbeanServerConnection = java.lang.management.ManagementFactory
                       .getPlatformMBeanServer();
                       javax.management.ObjectName mbeanName = new javax.management.ObjectName("jboss.as:subsystem=security,security-domain="+securityDomain);
                       mbeanServerConnection.invoke(mbeanName, "flushCache", null, null);
                       } catch (Exception e) {
                       throw new SecurityException(e);
                       }
                    }

                     

                     

                     

                     

                    @RolesAllowed({KnownJaasRoles.ADMINISTRATOR})
                    private void flushJaasCache(String securityDomain, String jaasUsername){
                       try {
                       Object[] params = {jaasUsername};
                       String[] signature = {"java.lang.String"};
                      
                       javax.management.MBeanServerConnection mbeanServerConnection = java.lang.management.ManagementFactory
                       .getPlatformMBeanServer();
                       javax.management.ObjectName mbeanName = new javax.management.ObjectName("jboss.as:subsystem=security,security-domain="+securityDomain);
                       mbeanServerConnection.invoke(mbeanName, "flushCache", params, signature);
                       } catch (Exception e) {
                       throw new SecurityException(e);
                       }
                    }
                    • 7. Re: How to flush JAAS Cache from war application?
                      aquee Newbie

                      Thank you xiang for your reply.

                      I have fixed my problem. and just posting it, if some one need it in future.

                       

                      public void flushJaasCache() {

                        ModelControllerClient client=null;

                        try { 

                                   client= ModelControllerClient.Factory.create("localhost", 9999); 

                                   final ModelNode address = new ModelNode(); 

                                   address.add("subsystem", "security"); 

                                   address.add("security-domain", "domain-name"); 

                        

                                   final ModelNode operation = new ModelNode(); 

                                   operation.get("operation").set("flush-cache"); 

                                   operation.get("address").set(address); 

                        

                                   final ModelNode result = client.execute(operation); 

                        

                                   if(! "success".equals(result.get("outcome").asString())) { 

                                       throw new IllegalStateException("operation failed"); 

                                   } 

                        

                               } catch (UnknownHostException e) {

                                          e.printStackTrace();

                                  } catch (IOException e) {

                                          e.printStackTrace();

                                  } finally { 

                                   if(client != null) { 

                                       try {

                                              client.close();

                                          } catch (IOException e) {

                                                  e.printStackTrace();

                                          }                 

                                   }  

                               } 

                        }

                      • 8. Re: How to flush JAAS Cache from war application?
                        xiang yingbing Master

                        "ModelControllerClient" is a good method, but it depend on JBoss specified jars and is NOT portable.