SSM架构整合开发LDAP(轻量级目录访问协议)

近期项目中有一个需求是需要整合LDAP开进行开发一个功能,该功能旨在同步LDAP服务器中的用户到本地数据库,然后在LDAP当中注册的账号都能在同一个平台中登录访问资源;那么首先就要知道LDAP为何物?LDAP既Lightweight Directory Access Protocol的英文缩写,轻量级目录访问协议。具体的概念介绍在这就不多做陈述,本文主要是记录介绍代码层面的功能开发跟实现;

package cn.ouryun.task;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import cn.ouryun.pojo.SysAccountModel;
import cn.ouryun.service.IUserService;
import lombok.extern.slf4j.Slf4j;

/**
 * LDAP定时任务:定时同步数据到基础开发平台用户表中
 * @author huangsiyuan
 *
 */
@Slf4j
@Component
public class LDAPScheduledTask {
    

    @Autowired
    private IUserService userService;
    
     
    
    
    /**
     * 每天晚上0点更新数据
     * @throws InterruptedException
     */
    //@Scheduled(cron="0/3 * * * * *") 
    @Scheduled(cron = "0 0 0 * * ?")
    public void updateLdapUsers() {
        log.info("开始调度定时任务更新LDAP服务器账户");
        Hashtable env = new Hashtable();
        
        env.put(Context.REFERRAL, "ignore");
        
        env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
        //LDAP服务器url, 389是默认端口号
        env.put(Context.PROVIDER_URL, "ldap://***.**.**.**:389");
        
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
        //账号: 用户名@域名为固定格式
        env.put(Context.SECURITY_PRINCIPAL, "******@example.com");
        //密码
        env.put(Context.SECURITY_CREDENTIALS, "******");
             
        try {
             DirContext ctx = new InitialDirContext(env);// 初始化上下文
             // 域节点
             String searchBase = "dc=example, dc=com";
             String searchFilter = "objectClass=User";
             SearchControls searchCtls = new SearchControls(); // Create the
             searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE); // Specify

             // 根据设置的域节点、过滤器类和搜索控制器搜索LDAP得到结果
             NamingEnumeration entries = ctx.search(searchBase, searchFilter,searchCtls);
             
             //封装LDAP用户
             List accountList = new ArrayList();
             SysAccountModel accountModel = null;
             while (entries.hasMoreElements()) {
                 SearchResult sr = entries.nextElement();
                 //获取属性
                 Attributes attrs = sr.getAttributes();
                 //根据具体取值(用户名)
                 String disName = attrs.get("name")==null ? "null":attrs.get("name").toString();
                 
                 //去除掉disName前缀name:
                 int index = disName.indexOf(":");
                 disName = disName.substring(index + 1, disName.length());
                 
                 accountModel = new SysAccountModel();
                 accountModel.setAccName(disName);
                 
                 accountList.add(accountModel);
             }
             
             if(accountList != null && accountList.size() > 0) {
                userService.saveLdapAccount(accountList);  //调用本地代码同步数据
             }
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
}

这段代码是通过Spring定时任务每天晚上十二点去将LDAP服务器上的用户同步到我们平台的用户表中;而这里要说明的是,以下这段代码是用于校验账户的合法性

@SuppressWarnings("unused")
    public Result userLdapLogin(String account, String password) throws Exception {
        
        Hashtable env = new Hashtable();
        
        SysAccountModel accountModel = new SysAccountModel();
        accountModel.setAccName(account);
        
        env.put(Context.REFERRAL, "ignore");
        
        env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
        //url
        env.put(Context.PROVIDER_URL, "ldap://172.16.88.86:389");
        
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
        //账号
        env.put(Context.SECURITY_PRINCIPAL, account + "@example.com");
        //密码
        env.put(Context.SECURITY_CREDENTIALS, password);
        
        //初始化上下文(所谓初始化上下文就是通过InitialDirContext去校验LDAP的账户跟密码还有url连接是否正确,如果正确则返回dirContext对象,否则会抛出异常)
        DirContext dirContext = new InitialDirContext(env);

 

 DirContext dirContext = new InitialDirContext(env);如果账户名或者密码错误,则会抛出异常。在一些业务场景中,系统原有的登录机制

例如Shiro,如果整合了LDAP用户,则需要LDAP用户在LDAP上验证,就是让new InitialDirContext(env);去初始化账户密码,如果验证通过则放行让其访问系统资源;

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(SSM架构整合开发LDAP(轻量级目录访问协议))