Shiro在LDAP中验证不存在的用户

时间:2014-01-27 21:01:41

标签: ldap shiro

有人可以建议为什么Shiro在我的跟踪日志中告诉我,一个不存在的用户“anybody”被验证了吗?在实际进行身份验证之前,它似乎在日志中为自己提供了一个会话。我假设这只是运行身份验证。

如果我注销然后尝试访问任何安全的URL,它会将ok重定向到我的ShiroFilterFactoryBean loginUrl。但它会验证任何用户。

Jan 27 20:25:16 TRACE org.apache.shiro.subject.support.DelegatingSubject - 尝试获取会话; create = false; session为null = false; session有id = true 1月27日20:25:16 TRACE org.apache.shiro.authc.AbstractAuthenticator - 收到令牌验证尝试[org.apache.shiro.authc.UsernamePasswordToken - anybody,rememberMe = false(127.0.0.1)] 1月27日20:25:16 DEBUG org.apache.shiro.realm.ldap.JndiLdapRealm - 通过LDAP验证用户'anybody' 1月27日20:25:16 DEBUG org.apache.shiro.realm.ldap.JndiLdapContextFactory - 使用URL [ldap://184.26.3.91:389]和principal [uid = anybody,ou = REMOTE,o = OFFICE]初始化LDAP上下文禁用池 1月27日20:25:16 DEBUG org.apache.shiro.realm.AuthenticatingRealm - 从doGetAuthenticationInfo中查找AuthenticationInfo [anybody] 1月27日20:25:16 DEBUG org.apache.shiro.realm.AuthenticatingRealm - 对info [anybody]禁用AuthenticationInfo缓存。提交的令牌:[org.apache.shiro.authc.UsernamePasswordToken - anybody,rememberMe = false(127.0.0.1)]。 1月27日20:25:16 DEBUG org.apache.shiro.authc.AbstractAuthenticator - 令牌成功验证[org.apache.shiro.authc.UsernamePasswordToken - anybody,rememberMe = false(127.0.0.1)]。退回帐户[任何人] 1月27日20:25:16 DEBUG org.apache.shiro.subject.support.DefaultSubjectContext - 主题上下文映射中没有可用的SecurityManager。回到SecurityUtils.getSecurityManager()查找。 1月27日20:25:16 TRACE org.apache.shiro.util.ThreadContext - get() - 在线程中[http-bio-8080-exec-6] 1月27日20:25:16 TRACE org.apache.shiro.util.ThreadContext - 检索到的值为[org.apache.shiro.web.mgt.DefaultWebSecurityManager]的值为[org.apache.shiro.util.ThreadContext_SECURITY_MANAGER_KEY]绑定到线程[http-bio-8080-exec-6] 1月27日20:25:16 TRACE org.apache.shiro.mgt.DefaultSecurityManager - Context已经包含一个SecurityManager实例。返回。 1月27日20:25:16 TRACE org.apache.shiro.subject.support.DelegatingSubject - 尝试获取会话; create = false; session为null = false; session有id = true 1月27日20:25:16 DEBUG org.apache.shiro.mgt.DefaultSecurityManager - 上下文已包含会话。返回。

我的LDAP领域是:

 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>

感谢您的帮助

1 个答案:

答案 0 :(得分:0)

奇怪的行为......但我认为这是标准的LDAP而不是Shiro本身(如果我猜错了,请纠正我)。 在创建LDAP初始上下文时,密钥对于url是错误的,所以显然它是去localhost而没有找到LDAP服务器它没有抛出异常但是快乐地恢复到匿名登录并且没有限制访问不存在的用户。我改成了:

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

并且有效。

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