`
Tyler_Zhou
  • 浏览: 216982 次
  • 性别: Icon_minigender_1
  • 来自: 湖北->上海
社区版块
存档分类
最新评论

liferay ldap配置与相关代码

阅读更多

1.下载LDAP server 并安装, liferay支持如下的server,推荐使用apacheds,或openLDAP


 

2.下载一个LDAP客户端工具,官方网站都有提供 ,推荐使用 jxplorer,测试能否正常连接。

 

3. Enterprise Admin->setting->authentication->LDAP,Enable使用LDAP验证,Required是否必须通过LDAP验证,如果不勾选通过liferay验证即可。


	/**
	 * LDAP验证
	 * @param companyId
	 * @param emailAddress
	 * @param screenName
	 * @param userId
	 * @param password
	 * @return
	 * @throws Exception
	 */
	protected int authenticate(
			long companyId, String emailAddress, String screenName, long userId,
			String password)
		throws Exception {
		//是否需要LDAP验证
		if (!PortalLDAPUtil.isAuthEnabled(companyId)) {
			if (_log.isDebugEnabled()) {
				_log.debug("Authenticator is not enabled");
			}

			return SUCCESS;
		}

		if (_log.isDebugEnabled()) {
			_log.debug("Authenticator is enabled");
		}

		// Make exceptions for omniadmins so that if they break the LDAP
		// configuration, they can still login to fix the problem
		//如果此用户是管理员的角色就返回成功
		if (authenticateOmniadmin(companyId, emailAddress, userId) == SUCCESS) {
			return SUCCESS;
		}
		//相对DN
		String baseDN = PrefsPropsUtil.getString(
			companyId, PropsUtil.LDAP_BASE_DN);

		LdapContext ctx = PortalLDAPUtil.getContext(companyId);

		if (ctx == null) {
			//查看LDAP验证是否是必须的
			return authenticateRequired(
				companyId, userId, emailAddress, FAILURE);
		}

		//  Process LDAP auth search filter

		String filter = PortalLDAPUtil.getAuthSearchFilter(
			companyId, emailAddress, screenName, String.valueOf(userId));

		try {
			SearchControls cons = new SearchControls(
				SearchControls.SUBTREE_SCOPE, 1, 0, null, false, false);

			NamingEnumeration<SearchResult> enu = ctx.search(
				baseDN, filter, cons);

			if (enu.hasMore()) {
				if (_log.isDebugEnabled()) {
					_log.debug("Search filter returned at least one result");
				}

				SearchResult result = enu.next();

				String fullUserDN = PortalLDAPUtil.getNameInNamespace(
					companyId, result);

				Attributes attrs = PortalLDAPUtil.getAttributes(
					ctx, fullUserDN);

				LDAPAuthResult ldapAuthResult = authenticate(
					ctx, companyId, attrs, fullUserDN, password);

				// Process LDAP failure codes

				String errorMessage = ldapAuthResult.getErrorMessage();

				if (errorMessage != null) {
					if (errorMessage.indexOf(PrefsPropsUtil.getString(
							companyId, PropsUtil.LDAP_ERROR_USER_LOCKOUT))
								!= -1) {

						throw new UserLockoutException();
					}
					else if (errorMessage.indexOf(PrefsPropsUtil.getString(
						companyId, PropsUtil.LDAP_ERROR_PASSWORD_EXPIRED))
							!= -1) {

						throw new PasswordExpiredException();
					}
				}

				if (!ldapAuthResult.isAuthenticated()) {
					//查看LDAP验证是否是必须的
					return authenticateRequired(
						companyId, userId, emailAddress, FAILURE);
				}

				// Get user or create from LDAP

				User user = PortalLDAPUtil.importLDAPUser(
					companyId, ctx, attrs, password, true);

				// Process LDAP success codes

				String resultCode = ldapAuthResult.getResponseControl();

				if (resultCode.equals(LDAPAuth.RESULT_PASSWORD_RESET)) {
					UserLocalServiceUtil.updatePasswordReset(
						user.getUserId(), true);
				}
				else if (
					resultCode.equals(LDAPAuth.RESULT_PASSWORD_EXP_WARNING)) {

					UserLocalServiceUtil.updatePasswordReset(
						user.getUserId(), true);
				}
			}
			else {
				if (_log.isDebugEnabled()) {
					_log.debug("Search filter did not return any results");
				}
				//查看LDAP验证是否是必须的
				return authenticateRequired(
					companyId, userId, emailAddress, DNE);
			}
		}
		catch (Exception e) {
			_log.error("Problem accessing LDAP server: " + e.getMessage());
			//查看LDAP验证是否是必须的
			if (authenticateRequired(
					companyId, userId, emailAddress, FAILURE) == FAILURE) {

				throw e;
			}
		}
		finally {
			ctx.close();
		}

		return SUCCESS;
	}
 

4.Default Values选择你使用的DS服务

 

5.测试连接能否成功。这些参数要根据自已的服务来填写。

测试成功

	/**
	 * 获得连接上下文
	 * @param companyId
	 * @return
	 * @throws Exception
	 */
	public static LdapContext getContext(long companyId) throws Exception {
		//连接地址(优先取数据库中)
		String baseProviderURL = PrefsPropsUtil.getString(
			companyId, PropsUtil.LDAP_BASE_PROVIDER_URL);
		//用户地址(优先取数据库中)
		String pricipal = PrefsPropsUtil.getString(
			companyId, PropsUtil.LDAP_SECURITY_PRINCIPAL);
		//连接密码(优先取数据库中)
		String credentials = PrefsPropsUtil.getString(
			companyId, PropsUtil.LDAP_SECURITY_CREDENTIALS);

		return getContext(companyId, baseProviderURL, pricipal, credentials);
	}

	public static LdapContext getContext(
			long companyId, String providerURL, String pricipal,
			String credentials)
		throws Exception {

		Properties env = new Properties();

		env.put(
			Context.INITIAL_CONTEXT_FACTORY,
			PrefsPropsUtil.getString(
				companyId, PropsUtil.LDAP_FACTORY_INITIAL));
		env.put(Context.PROVIDER_URL, providerURL);
		env.put(Context.SECURITY_PRINCIPAL, pricipal);
		env.put(Context.SECURITY_CREDENTIALS, credentials);

		LogUtil.debug(_log, env);

		LdapContext ctx = null;

		try {
			ctx = new InitialLdapContext(env, null);
		}
		catch (Exception e) {
			if (_log.isWarnEnabled()) {
				_log.warn("Failed to bind to the LDAP server");
			}

			if (_log.isDebugEnabled()) {
				_log.debug(e);
			}
		}

		return ctx;
	}

 

6.测试用户:Authentication search Filter验证过滤语句,现在是过滤email,Test LDAP Users这个按钮是不会调用这个过滤的,Import Search Filter测试用户过滤语句。下面是liferay数据与ldap数据一对应的关系。

 测试成功

 

	/**
	 * 测试取用户列表
	 * @param companyId
	 * @param ctx
	 * @param maxResults
	 * @return
	 * @throws Exception
	 */
	public static NamingEnumeration<SearchResult> getUsers(
			long companyId, LdapContext ctx, int maxResults)
		throws Exception {

		String baseDN = PrefsPropsUtil.getString(
			companyId, PropsUtil.LDAP_BASE_DN);
		String userFilter = PrefsPropsUtil.getString(
			companyId, PropsUtil.LDAP_IMPORT_USER_SEARCH_FILTER);

		return getUsers(companyId, ctx, maxResults, baseDN, userFilter);
	}

	public static NamingEnumeration<SearchResult> getUsers(
			long companyId, LdapContext ctx, int maxResults, String baseDN,
			String userFilter)
		throws Exception {

		SearchControls cons = new SearchControls(
			SearchControls.SUBTREE_SCOPE, maxResults, 0, null, false, false);

		return ctx.search(baseDN, userFilter, cons);
	}

 

7.测试取得用户组织,基本上同上就不详解,仅贴出成功画面和相关代码

	/**
	 * 测试用户组织
	 * @param companyId
	 * @param ctx
	 * @param maxResults
	 * @return
	 * @throws Exception
	 */
	public static NamingEnumeration<SearchResult> getGroups(
			long companyId, LdapContext ctx, int maxResults)
		throws Exception {

		String baseDN = PrefsPropsUtil.getString(
			companyId, PropsUtil.LDAP_BASE_DN);
		String groupFilter = PrefsPropsUtil.getString(
			companyId, PropsUtil.LDAP_IMPORT_GROUP_SEARCH_FILTER);

		return getGroups(companyId, ctx, maxResults, baseDN, groupFilter);
	}

	public static NamingEnumeration<SearchResult> getGroups(
			long companyId, LdapContext ctx, int maxResults, String baseDN,
			String groupFilter)
		throws Exception {

		SearchControls cons = new SearchControls(
			SearchControls.SUBTREE_SCOPE, maxResults, 0, null, false, false);

		return ctx.search(baseDN, groupFilter, cons);
	}
 

8.导入导出配置:Import Enabled:是否导入,导入时密码为空 Import on Startup Enabled:启动导入。Import Interval:导入间隔时间,注意时间太短会影响性能。Export Enabled:是否导出, 在用户登陆时和修改用户信息时都会导出至LDAP但不导出密码,在修改时如果修改了密码才会把密码也导出进去,如果密码未导入至LDAP并且前面的 Required也勾选了,那么LDAP验证不会通过 。后面三个为导出的设置。

 

	/**
	 * 从LDAP中导入用户
	 * @param companyId
	 * @param ctx
	 * @param attrs
	 * @param password
	 * @param importGroupMembership
	 * @return
	 * @throws Exception
	 */
	public static User importLDAPUser(
			long companyId, LdapContext ctx, Attributes attrs, String password,
			boolean importGroupMembership)
		throws Exception {

		AttributesTransformer attrsTransformer =
			AttributesTransformerFactory.getInstance();

		attrs = attrsTransformer.transformUser(attrs);

		Properties userMappings = getUserMappings(companyId);

		LogUtil.debug(_log, userMappings);

		User defaultUser = UserLocalServiceUtil.getDefaultUser(companyId);

		boolean autoPassword = false;
		boolean updatePassword = true;

		if (password.equals(StringPool.BLANK)) {
			autoPassword = true;
			updatePassword = false;
		}

		long creatorUserId = 0;
		boolean passwordReset = false;
		boolean autoScreenName = false;
		String screenName = LDAPUtil.getAttributeValue(
			attrs, userMappings.getProperty("screenName")).toLowerCase();
		String emailAddress = LDAPUtil.getAttributeValue(
			attrs, userMappings.getProperty("emailAddress"));
		Locale locale = defaultUser.getLocale();
		String firstName = LDAPUtil.getAttributeValue(
			attrs, userMappings.getProperty("firstName"));
		String middleName = LDAPUtil.getAttributeValue(
			attrs, userMappings.getProperty("middleName"));
		String lastName = LDAPUtil.getAttributeValue(
			attrs, userMappings.getProperty("lastName"));

		if (Validator.isNull(firstName) || Validator.isNull(lastName)) {
			String fullName = LDAPUtil.getAttributeValue(
				attrs, userMappings.getProperty("fullName"));

			String[] names = LDAPUtil.splitFullName(fullName);

			firstName = names[0];
			middleName = names[1];
			lastName = names[2];
		}

		int prefixId = 0;
		int suffixId = 0;
		boolean male = true;
		int birthdayMonth = Calendar.JANUARY;
		int birthdayDay = 1;
		int birthdayYear = 1970;
		String jobTitle = LDAPUtil.getAttributeValue(
			attrs, userMappings.getProperty("jobTitle"));
		long[] organizationIds = new long[0];
		boolean sendEmail = false;

		if (_log.isDebugEnabled()) {
			_log.debug(
				"Screen name " + screenName + " and email address " +
					emailAddress);
		}

		if (Validator.isNull(screenName) || Validator.isNull(emailAddress)) {
			if (_log.isWarnEnabled()) {
				_log.warn(
					"Cannot add user because screen name and email address " +
						"are required");
			}

			return null;
		}

		User user = null;

		try {

			// Find corresponding portal user

			String authType = PrefsPropsUtil.getString(
				companyId, PropsUtil.COMPANY_SECURITY_AUTH_TYPE,
				PropsValues.COMPANY_SECURITY_AUTH_TYPE);

			if (authType.equals(CompanyConstants.AUTH_TYPE_SN)) {
				user = UserLocalServiceUtil.getUserByScreenName(
					companyId, screenName);
			}
			else {
				user = UserLocalServiceUtil.getUserByEmailAddress(
					companyId, emailAddress);
			}

			// Skip if is default user

			if (user.isDefaultUser()) {
				return user;
			}

			// Skip import if user fields has been already synced and if
			// import is part of a scheduled import

			Date ldapUserModifiedDate = null;

			String modifiedDate = LDAPUtil.getAttributeValue(
				attrs, "modifyTimestamp");

			try {
				DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");

				ldapUserModifiedDate = dateFormat.parse(modifiedDate);

				if (ldapUserModifiedDate.equals(user.getModifiedDate()) &&
					autoPassword) {

					if (_log.isDebugEnabled()) {
						_log.debug(
							"User is already syncronized, skipping user " +
								user.getEmailAddress());
					}

					return user;
				}
			}
			catch (ParseException pe) {
				if (_log.isDebugEnabled()) {
					_log.debug(
						"Unable to parse LDAP modify timestamp " +
							modifiedDate);
				}

				_log.debug(pe, pe);
			}

			Contact contact = user.getContact();

			Calendar birthdayCal = CalendarFactoryUtil.getCalendar();

			birthdayCal.setTime(contact.getBirthday());

			birthdayMonth = birthdayCal.get(Calendar.MONTH);
			birthdayDay = birthdayCal.get(Calendar.DATE);
			birthdayYear = birthdayCal.get(Calendar.YEAR);

			// User exists so update user information

			if (updatePassword) {
				user = UserLocalServiceUtil.updatePassword(
					user.getUserId(), password, password, passwordReset,
					true);
			}

			user = UserLocalServiceUtil.updateUser(
				user.getUserId(), password, user.isPasswordReset(), screenName,
				emailAddress, user.getLanguageId(), user.getTimeZoneId(),
				user.getGreeting(), user.getComments(), firstName, middleName,
				lastName, contact.getPrefixId(), contact.getSuffixId(),
				contact.getMale(), birthdayMonth, birthdayDay, birthdayYear,
				contact.getSmsSn(), contact.getAimSn(), contact.getIcqSn(),
				contact.getJabberSn(), contact.getMsnSn(), contact.getSkypeSn(),
				contact.getYmSn(), jobTitle, user.getOrganizationIds());

			if (ldapUserModifiedDate != null) {
				UserLocalServiceUtil.updateModifiedDate(
					user.getUserId(), ldapUserModifiedDate);
			}
		}
		catch (NoSuchUserException nsue) {

			// User does not exist so create

		}

		if (user == null) {
			try {
				if (_log.isDebugEnabled()) {
					_log.debug("Adding user to portal " + emailAddress);
				}

				user = UserLocalServiceUtil.addUser(
					creatorUserId, companyId, autoPassword, password, password,
					autoScreenName, screenName, emailAddress, locale, firstName,
					middleName, lastName, prefixId, suffixId, male,
					birthdayMonth, birthdayDay, birthdayYear, jobTitle,
					organizationIds, sendEmail);
			}
			catch (Exception e){
				_log.error(
					"Problem adding user with screen name " + screenName +
						" and email address " + emailAddress,
					e);
			}
		}

		// Import user groups and membership

		if (importGroupMembership && (user != null)) {
			String userMappingsGroup = userMappings.getProperty("group");

			if (userMappingsGroup != null) {
				Attribute attr = attrs.get(userMappingsGroup);

				if (attr != null){
					_importGroupsAndMembershipFromLDAPUser(
						companyId, ctx, user.getUserId(), attr);
				}
			}
		}

		return user;
	}
 
/**
	 * 将用户导出至LDAP
	 * @param user
	 * @throws Exception
	 */
	public static void exportToLDAP(User user) throws Exception {
		long companyId = user.getCompanyId();

		if (!isAuthEnabled(companyId) || !isExportEnabled(companyId)) {
			return;
		}

		LdapContext ctx = getContext(companyId);

		if (ctx == null) {
			return;
		}

		Properties userMappings = getUserMappings(companyId);
		Binding binding = getUser(user.getCompanyId(), user.getScreenName());
		String name = StringPool.BLANK;

		if (binding == null) {

			// Generate full DN based on user DN

			StringMaker sm = new StringMaker();

			sm.append(userMappings.getProperty("screenName"));
			sm.append(StringPool.EQUAL);
			sm.append(user.getScreenName());
			sm.append(StringPool.COMMA);
			sm.append(getUsersDN(companyId));

			name = sm.toString();

			// Create new user in LDAP

			LDAPUser ldapUser = (LDAPUser)Class.forName(
				PropsValues.LDAP_USER_IMPL).newInstance();

			ldapUser.setUser(user);

			ctx.bind(name, ldapUser);
		}
		else {

			// Modify existing LDAP user record

			name = getNameInNamespace(companyId, binding);

			Modifications mods = Modifications.getInstance();

			if (user.isPasswordModified() &&
				Validator.isNotNull(user.getPasswordUnencrypted())) {

				mods.addItem(
					userMappings.getProperty("password"),
					user.getPasswordUnencrypted());
			}

			mods.addItem(
				userMappings.getProperty("emailAddress"),
				user.getEmailAddress());

			ModificationItem[] modItems = mods.getItems();

			ctx.modifyAttributes(name, modItems);
		}

		ctx.close();
	}

 

9.Use LDAP Password Policy:是使用LDAP的密码策略,这个主要用在验证方面,不推荐使用。


  • 大小: 4.1 KB
  • 大小: 2.3 KB
  • 大小: 5.4 KB
  • 大小: 2.1 KB
  • 大小: 8.1 KB
  • 大小: 2.9 KB
  • 大小: 2.4 KB
  • 大小: 2.2 KB
  • 大小: 5.8 KB
分享到:
评论
6 楼 chirking 2008-12-09  
请问一下官方插件(如wiki)是怎么在liferay数据库中建立和链接自己的表的?
源代码中连接数据库的部分在哪?
实在是没弄明白啊,网上根本找不到这方面的资料
你能写一篇这方面的帖子么,谢谢了
5 楼 hawk315 2008-12-05  
搞定了,谢谢!
4 楼 Tyler_Zhou 2008-12-05  
hawk315 写道

我用5.1.2的版本。
配制完成后,重起Tomcat的时候报异常了。不知道,你这边是否也有异常?

启动导入错误,我出现过,是因为我配置写错了。你查一下看,liferay的默认的base dn配置是有问题的,最起码我的ldap服务建好后和我的是不对的,你查一下看。liferay导入是没有问题的。
3 楼 hawk315 2008-12-04  
我这边的截图如何发到这个上面?
2 楼 hawk315 2008-12-04  
提示我在导入操作的importLDAPUser方法里的
birthdayCal.setTime(contact.getBirthday());
这句空指针了。将其改成
if( null==contact.getBirthday() ){
   birthdayCal.setTime(new Date());
}else{
   birthdayCal.setTime(contact.getBirthday());
}
后,这一块没有异常了。
但是又有后面其他语句的异常。
我感觉Liferay不会有这样的BUG,怀疑是自己LDAP数据问题,可是又不知道如何去调。
故来请教。
1 楼 hawk315 2008-12-04  
我用5.1.2的版本。
配制完成后,重起Tomcat的时候报异常了。不知道,你这边是否也有异常?

相关推荐

    liferay + cas + ldap 集成配置

    标题 "Liferay + CAS + LDAP 集成配置" 涉及到的是在企业级内容管理系统 Liferay 中集成 Central Authentication Service (CAS) 和 Lightweight Directory Access Protocol (LDAP) 的过程。这种集成允许用户通过CAS...

    Liferay 6 入门教程

    "plugins开发指南13-liferay中使用ldap分析.pdf"讨论了Liferay与LDAP(轻量级目录访问协议)的集成,这对于大型企业需要与现有用户目录系统同步的场景非常有用。最后,"plugins开发指南19-liferay6中使用JSON.pdf...

    Liferay门户手册.pdf

    这一过程通常涉及到配置Liferay以使用LDAP服务器进行身份验证,可能需要调整Liferay的配置文件以适应LDAP服务器的特定设置。 ##### 4.4 集成应用安全单点登录 单点登录(Single Sign-On,SSO)允许用户在一个应用中...

    liferay开发手册

    5. **安全和身份管理**:理解Liferay的安全模型,包括用户认证、授权和角色分配,以及如何与其他身份验证系统(如LDAP)集成。 6. **社区和社交功能**:Liferay内置了社交网络特性,如好友、群组、论坛等,开发者...

    CAS4.2.4 连接Liferay6.2以上版本数据库用户表验证用户 project

    为了实现CAS与Liferay的集成,我们需要配置CAS服务器以连接到Liferay的数据库,并使用其中的用户信息进行身份验证。 首先,我们需要在CAS服务器的配置中添加Liferay数据库的相关信息。这通常涉及到修改`cas....

    liferay开发文档(20210921154012).pdf

    但是,从这段混乱的文字中,我们可以大致推测文档讨论的是关于Liferay的开发环境配置、核心概念、以及与Java相关的一些技术标准。我们可以尝试梳理这些内容,但请注意,因为原始文本的混乱,以下内容可能并不完全...

    liferay5.2.3 tomcat6 eclipse ide 开发文档

    本开发文档旨在为初学者和经验丰富的开发者提供全面指南,涵盖Liferay 5.2.3与Tomcat6在Eclipse IDE中的集成、配置和开发流程。通过本文档,读者将能够迅速掌握Liferay门户框架的基本操作,从安装部署到portlet开发...

    liferay6.rar_技术管理_Java_

    本压缩包"liferay6.rar"聚焦于Liferay 6版本的技术管理与Java开发实践,下面将详细阐述相关知识点。 一、Liferay 6概述 Liferay 6是Liferay Portal的一个重要版本,它引入了多项改进和新特性,如增强的用户体验、...

    lifery6.1+cas初始化环境搭建及门户解决方案

    1. **单一登录接口与多认证模式**:Liferay支持单一登录接口,并且提供了多种认证方式,如LDAP和SQL。 2. **用户管理**:管理员可以通过用户界面轻松管理用户、组和角色。 3. **个性化布局**:用户可以根据自己的...

    lliferay.tar.gz_系统设计方案_HTML_

    Liferay 是一个开源的企业级门户平台,常用于构建企业内部或对外的Web...对于`lliferay.tar.gz`中的具体文件,可能包含了Liferay的安装指南、示例portlet代码、配置示例等,这些都是学习和部署Liferay的重要参考资料。

Global site tag (gtag.js) - Google Analytics