8 Replies Latest reply on Sep 4, 2013 8:15 AM by ybxiang.china

    How to flush JAAS Cache from war application?

    ybxiang.china

      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

          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?
            ybxiang.china

            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

              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?
                ybxiang.china

                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

                  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?
                    ybxiang.china

                    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

                      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?
                        ybxiang.china

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