使用AD域登录示例,请先查看 《与第三方系统用户集成》的第 4、使用第三方系统的用户验证
AD域登录示例
package smartbi.usermanager.auth.impl; import java.io.IOException; import java.io.InputStream; import java.util.*; import javax.naming.*; import javax.naming.directory.*; import javax.naming.ldap.InitialLdapContext; import javax.naming.ldap.LdapContext; import javax.servlet.ServletContext; import org.apache.log4j.Logger; import smartbi.usermanager.auth.*; import smartbi.util.StringUtil; /** * 此类为使用Microsoft的AD(活动目录)登录验证的一个例子。<br> * 需要配置文件ad.properties,并放入到war包中的WEB-INF目录中,配置文件中包含的键值为:<br> * * <pre> * # 上下文对象工厂类,一般不需要改变 * initial_context_factory=com.sun.jndi.ldap.LdapCtxFactory * # 活动目录的访问地址 * provider_url=ldap://ADServer:3268 * # 活动目录的登录用户名前缀 * principal_prefix=MyDomain\\ * # 活动目录的登录用户名 * login_user=username * # 活动目录的登录密码 * login_password=password * </pre> */ public class ADAuthentication implements IAuthentication { private static final Logger log = Logger.getLogger(ADAuthentication.class); private String initialContextFactory; private String providerUrl; private String prefix; private String loginUser; private String loginPassword; private String baseName; private String filterPrefix; private String filterSuffix; /** * 配置登录验证类 * * @param ctx * 应用的上下文对象 * @throws IOException * 当出现初始化错误时。 */ public void config(ServletContext ctx) throws IOException { init(ctx.getResourceAsStream("/WEB-INF/ad.properties")); } /** * 读取必要的配置信息 * * @param is * 配置文件 * @throws IOException * 当读取配置文件出错时抛出 */ private void init(InputStream is) throws IOException { if (is != null) { Properties prop = new Properties(); prop.load(is); initialContextFactory = prop.getProperty("initial_context_factory"); providerUrl = prop.getProperty("provider_url"); prefix = prop.getProperty("principal_prefix"); loginUser = prop.getProperty("login_user"); loginPassword = prop.getProperty("login_password"); baseName = StringUtil.nullToEmpty(prop.getProperty("baseName")); filterPrefix = StringUtil.nullToEmpty(prop.getProperty("filterPrefix")); filterSuffix = StringUtil.nullToEmpty(prop.getProperty("filterSuffix")); is.close(); } } /** * 判断登录用户名、密码是否正确 * * @param userName * 用户名 * @param password * 密码 * @return 如果登录成功则返回true,如果失败则返回false * @throws IOException * 当出现通信异常 */ public boolean isPasswordValidate(String userName, String password) throws IOException { if (StringUtil.isNullOrEmpty(password)) { return false; } try { Hashtable<String, String> env = initEnv(userName, password); LdapContext context = new InitialLdapContext(env, null); context.close(); return true; } catch (NamingException e) { return false; } } /** * 初始化访问活动目录所需要的参数设置 * * @param userName * 登录活动目录的用户名 * @param password * 登录活动目录的密码 * @return 返回相应的参数配置 */ private Hashtable<String, String> initEnv(String userName, String password) { Hashtable<String, String> env = new Hashtable<String, String>(); env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory); env.put(Context.PROVIDER_URL, providerUrl); env.put(Context.SECURITY_PRINCIPAL, prefix + userName); env.put(Context.SECURITY_CREDENTIALS, password); return env; } /** * 获取用户的名称、别名信息 * * @param userName * 用户名 * @return 指定用户的信息 * @throws IOException * 当出现通信异常 * @throws UserNotExistException * 如果抛出此异常,则smartbi会删除此用户 */ public UserInfo getUser(String userName) throws IOException, UserNotExistException { try { // AD-使用配置文件中的用户名、密码登录 Hashtable<String, String> env = initEnv(loginUser, loginPassword); LdapContext context = new InitialLdapContext(env, null); // baseName 可以通过Softerra LDAP Browser查看 String base = baseName; // AD-指定搜索范围为个人,并且用户名为客户端输入的用户名称 String filter = filterPrefix + userName + filterSuffix; SearchControls controls = new SearchControls(); controls.setSearchScope(SearchControls.SUBTREE_SCOPE); // AD-返回用户的名称、别名及部门 controls.setReturningAttributes(new String[] { "sAMAccountName", "displayName", "department" }); NamingEnumeration<SearchResult> answer = context.search(base, filter, controls); if (answer.hasMore()) { // 如果找到相应的用户 SearchResult result = answer.next(); Attributes attrs = result.getAttributes(); Attribute attr = attrs.get("sAMAccountName"); String name = attr == null || attr.get() == null ? null : attr.get().toString(); attr = attrs.get("displayName"); String alias = attr == null || attr.get() == null ? null : attr.get().toString(); attr = attrs.get("department"); String dept = attr == null || attr.get() == null ? null : attr.get().toString(); answer.close(); // 设置用户信息,smartbi会自动同步 UserInfo info = new UserInfo(name, alias, alias); // 设置组信息 GroupInfo group = new GroupInfo(); group.setName(dept); // 设置组的父组为null,即此组会建立在smartbi的"默认组"之下 // 如果不为null,smartbi会根据此属性来建立用户组的树结构 group.setParentGroup(null); // smartbi支持一个用户同时属于多个用户组,所以使用List<GroupInfo> List<GroupInfo> groups = new ArrayList<GroupInfo>(); groups.add(group); // 设置用户所属的组 info.setGroups(groups); // AD不支持返回角色列表,所以设置角色为null,smartbi不会修改此用户所属的角色 info.setRoles(null); return info; } // 如果用户不存在,则抛出异常 throw new UserNotExistException(userName); } catch (NamingException e) { log.error("getUser fail.", e); return null; } } /** * 返回用户是否在本Authentication类中验证密码 * * @param userName * 用户名 * @return 如果返回true,表示该用户的密码在本类中验证;如果返回false,表示该用户的密码在知识库中验证 * @throws IOException * 当出现通信异常 */ public boolean shallUserValidateInAuthentication(String userName) throws IOException { // admin用户还是使用知识库本身的方式验证 if ("admin".equals(userName)) return false; else return true; } /** * 设置用户的密码 * * @param oldPassword * 旧密码 * @param newPassword * 新密码 * @return 返回设置用户密码是否成功 * @throws IOException * 当出现通信异常时抛出 * @throws UnsupportedOperationException * 当该用户验证类不支持此操作时抛出 */ public boolean changePassword(String userName, String oldPassword, String newPassword) throws IOException, UnsupportedOperationException { throw new UnsupportedOperationException(); } }