Question

Can anyone suggest why Shiro tells me in my trace logs below that a non existent user "anybody" is authenticated ok? It seems to give itself a session earlier on in the log prior to actually authenticating. I assume that this is just to run the authentication.

It redirects ok to my ShiroFilterFactoryBean loginUrl if I logout and then try to access any secured url. But then it will authenticate any user.

Jan 27 20:25:16 TRACE org.apache.shiro.subject.support.DelegatingSubject - attempting to get session; create = false; session is null = false; session has id = true Jan 27 20:25:16 TRACE org.apache.shiro.authc.AbstractAuthenticator - Authentication attempt received for token [org.apache.shiro.authc.UsernamePasswordToken - anybody, rememberMe=false (127.0.0.1)] Jan 27 20:25:16 DEBUG org.apache.shiro.realm.ldap.JndiLdapRealm - Authenticating user 'anybody' through LDAP Jan 27 20:25:16 DEBUG org.apache.shiro.realm.ldap.JndiLdapContextFactory - Initializing LDAP context using URL [ldap://184.26.3.91:389] and principal [uid=anybody,ou=REMOTE,o=OFFICE] with pooling disabled Jan 27 20:25:16 DEBUG org.apache.shiro.realm.AuthenticatingRealm - Looked up AuthenticationInfo [anybody] from doGetAuthenticationInfo Jan 27 20:25:16 DEBUG org.apache.shiro.realm.AuthenticatingRealm - AuthenticationInfo caching is disabled for info [anybody]. Submitted token: [org.apache.shiro.authc.UsernamePasswordToken - anybody, rememberMe=false (127.0.0.1)]. Jan 27 20:25:16 DEBUG org.apache.shiro.authc.AbstractAuthenticator - Authentication successful for token [org.apache.shiro.authc.UsernamePasswordToken - anybody, rememberMe=false (127.0.0.1)]. Returned account [anybody] Jan 27 20:25:16 DEBUG org.apache.shiro.subject.support.DefaultSubjectContext - No SecurityManager available in subject context map. Falling back to SecurityUtils.getSecurityManager() lookup. Jan 27 20:25:16 TRACE org.apache.shiro.util.ThreadContext - get() - in thread [http-bio-8080-exec-6] Jan 27 20:25:16 TRACE org.apache.shiro.util.ThreadContext - Retrieved value of type [org.apache.shiro.web.mgt.DefaultWebSecurityManager] for key [org.apache.shiro.util.ThreadContext_SECURITY_MANAGER_KEY] bound to thread [http-bio-8080-exec-6] Jan 27 20:25:16 TRACE org.apache.shiro.mgt.DefaultSecurityManager - Context already contains a SecurityManager instance. Returning. Jan 27 20:25:16 TRACE org.apache.shiro.subject.support.DelegatingSubject - attempting to get session; create = false; session is null = false; session has id = true Jan 27 20:25:16 DEBUG org.apache.shiro.mgt.DefaultSecurityManager - Context already contains a session. Returning.

My LDAP realm is :

 public class MyJndiLdapRealm extends JndiLdapRealm {

private static final Logger logger = LoggerFactory.getLogger(MyJndiLdapRealm.class);

@Override
protected AuthorizationInfo queryForAuthorizationInfo(PrincipalCollection principals, LdapContextFactory ldapContextFactory) throws NamingException {

    logger.debug("queryForAuthorizationInfo(PrincipalCollection: entering");

    String username = (String) getAvailablePrincipal(principals);

    logger.debug("queryForAuthorizationInfo(PrincipalCollection: user is "+ username);

    // Perform context search
    LdapContext ldapContext = ldapContextFactory.getSystemLdapContext();

    Set<String> roleNames;

    try {
      roleNames = getRoleNamesForUser(username, ldapContext);
    } finally {
      LdapUtils.closeContext(ldapContext);
    }

    return buildAuthorizationInfo(roleNames);
}

protected AuthorizationInfo buildAuthorizationInfo(Set<String> roleNames) {
    return new SimpleAuthorizationInfo(roleNames);
}

protected Set<String> getRoleNamesForUser(String username, LdapContext ldapContext) throws NamingException {
    Set<String> roleNames;
    roleNames = new LinkedHashSet<String>();

    logger.debug("getRoleNamesForUser : entering");

    SearchControls searchCtls = new SearchControls();
    searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);

    //SHIRO-115 - prevent potential code injection:
    String searchFilter = "(&(objectClass=*)(CN={0}))";
    Object[] searchArguments = new Object[]{ username };

//  Name searchBase; // ?
    String searchBase = "test";
    NamingEnumeration<SearchResult> answer = ldapContext.search(searchBase, searchFilter, searchArguments, searchCtls);

    while (answer.hasMoreElements()) {
      SearchResult sr = (SearchResult) answer.next();

      logger.debug("Retrieving group names for user [" + sr.getName() + "]");


      Attributes attrs = sr.getAttributes();

      if (attrs != null) {
        NamingEnumeration<? extends Attribute> ae = attrs.getAll();
        while (ae.hasMore()) {
          Attribute attr = (Attribute) ae.next();

          if (attr.getID().equals("memberOf")) {

            Collection<String> groupNames = LdapUtils.getAllAttributeValues(attr);

            logger.debug("Groups found for user [" + username + "]: " + groupNames);

            Collection<String> rolesForGroups = getRoleNamesForGroups(groupNames);
            roleNames.addAll(rolesForGroups);
          }
        }
      }
    }
    return roleNames;
}
    // active dir
protected Collection<String> getRoleNamesForGroups(Collection<String> groupNames) {
        Set<String> roleNames = new HashSet<String>(groupNames.size());
/*
           if (groupRolesMap != null) {
               for (String groupName : groupNames) {
                   String strRoleNames = groupRolesMap.get(groupName);
                   if (strRoleNames != null) {
                         for (String roleName : strRoleNames.split(ROLE_NAMES_DELIMETER)) {


                               log.debug("User is member of group [" + groupName + "] so adding role [" + roleName + "]");


                           roleNames.add(roleName);

                         }
                     }
                 }
              }   */
             return roleNames;
       }

}

spring application context :

     <bean id="customAuthFilter" class="security.MyAuthenticationFilter"/>

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <property name="securityManager" ref="securityManager"/>
    <property name="loginUrl" value="/ldapLogin"/>
    <property name="successUrl" value="/referral_form"/>
    <property name="unauthorizedUrl" value="/unauthorized"/>
     <property name="filterChainDefinitions">
        <value>
            /** = authc, customAuthFilter
            [main]
            /logout = logout
        </value>
    </property>   
</bean>

<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <!-- Single realm app.  If you have multiple realms, use the 'realms' property instead. -->
    <property name="realm" ref="authenticateRealm"/>
<!--   <property name="sessionManager.globalSessionTimeout ="30000"/>  -->  
     <property name="sessionMode" value="native"/> 
</bean>
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

<bean id="authenticateRealm" class="security.MyJndiLdapRealm">
    <property name="contextFactory" ref="contextFactory" />
    <property name="userDnTemplate" value="uid={0},ou=OFFICE" />
</bean>

<bean id="contextFactory" class="org.apache.shiro.realm.ldap.JndiLdapContextFactory">
    <property name="environment">
        <map>
            <entry key="java.naming.provider.url" value="ldap://184.26.3.91:389" />
        </map>    
    </property> 

</bean>

<!-- Enable Shiro Annotations for Spring-configured beans.  Only run after -->
<!-- the lifecycleBeanProcessor has run: -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"/>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
    <property name="securityManager" ref="securityManager"/>
</bean>

Thanks for any help

Was it helpful?

Solution

Weird behaviour ... but I think this is standard LDAP rather than Shiro per se (correct me if I'm guessing wrong). In the creation of the LDAP initial context the key was wrong for the url so apparently it was going to localhost and not finding an LDAP server it didn't throw an exception but merrily reverted back to the anonymous login and didn't restrict access to the non-existent user. I changed it to:

    <bean id="contextFactory" class="org.apache.shiro.realm.ldap.JndiLdapContextFactory">
  <property name="url" value="ldap://184.26.3.91:389"/>
   </bean>

and it worked.

(thanks to http://shiro-user.582556.n2.nabble.com/What-is-the-configuration-for-ldap-authentication-with-spring-td6656846.html)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top