Apache Shiro 配置 LDAP 驗證

一般在根據LDAP進行身份驗證時通常進行如下三步:java

  1. 利用一個LDAP用戶的用戶名和密碼綁定到LDAP服務器。
  2. 在LDAP中檢索一個用戶的條目,而後將提供的密碼和檢索到的LDAP記錄中進行驗證。
  3. 根據LDAP提供的記錄,再去本系統中查找受權信息。

Shiro 提供了DefaultLdapRealm,只作了第二步,根據用戶的條目和密碼來驗證。並不能知足咱們的需求,因此確定是要定製化LdapRealm。spring

這裏使用Spring Ldap 來簡化Ldap操做服務器

public class LdapRealm extends AuthorizingRealm {

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

    private LdapTemplate ldapTemplate;

    @Autowired
    private UserService userService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private MenuService menuService;

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String username = (String) token.getPrincipal();
        String password = new String((char[]) token.getCredentials());

        try {
            LdapQuery ldapQuery = LdapQueryBuilder.query().base("DC=example,DC=com").searchScope(SearchScope.SUBTREE)
                    .filter("(sAMAccountName={0})", username);

            boolean authResult = ldapTemplate.authenticate(ldapQuery.base(), ldapQuery.filter().encode(), password);

            if (!authResult) {
                logger.debug("ldap authentication for {} failed", username);
                return null;
            }

            User ldapUser = (User) ldapTemplate.searchForObject(ldapQuery, new LdapUserAttrMapper());

            User user = userService.selectUserById(ldapUser.getUserId());
            if (user == null) {
                // 用戶名不存在拋出異常
                throw new UnknownAccountException();
            }
            if (user.getRemoveFlag()) {
                // 用戶被管理員鎖定拋出異常
                throw new LockedAccountException();
            }

            SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, token.getCredentials(),
                    "LdapRealm");
            return authenticationInfo;
        } catch (Exception e) {
            logger.error("ldap authentication failed", e.toString());
            return null;
        }

    }


    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        Long userId = ShiroUtils.getUserId();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        // 角色加入AuthorizationInfo認證對象
        info.setRoles(roleService.selectRoleKeys(userId));
        // 權限加入AuthorizationInfo認證對象
        info.setStringPermissions(menuService.selectPermsByUserId(userId));
        return info;
    }

    public LdapTemplate getLdapTemplate() {
        return ldapTemplate;
    }

    public void setLdapTemplate(LdapTemplate ldapTemplate) {
        this.ldapTemplate = ldapTemplate;
    }
}

關鍵的代碼以下,驗證用戶和獲取LDAP用戶信息app

LdapQuery ldapQuery = LdapQueryBuilder.query().base("DC=example,DC=com").searchScope(SearchScope.SUBTREE)
                    .filter("(sAMAccountName={0})", username);
boolean authResult = ldapTemplate.authenticate(ldapQuery.base(), ldapQuery.filter().encode(), password);
User ldapUser = (User) ldapTemplate.searchForObject(ldapQuery, new LdapUserAttrMapper());

Spring 的 ldap 配置以下:ide

<bean id="ldapContextSource" class="org.springframework.ldap.core.support.LdapContextSource">
    <property name="url" value="ldap://192.168.100.1:3268"/>
    <property name="userDn" value="CN=Reader"/>
    <property name="password" value="secret"/>
</bean>

<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
    <property name="contextSource" ref="ldapContextSource"/>
</bean>

<bean id="ldapRealm" class="com.example.shiro.LdapRealm">
    <property name="ldapTemplate" ref="ldapTemplate"/>
</bean>
相關文章
相關標籤/搜索