将 LDAP 属性映射到 Liferay 用户显示语言
Mapping LDAP attribute to Liferay user display language
我们正在使用 Liferay 6.2 GA4,它允许您仅映射几个基本属性以导入 LDAP 用户:
screenName, password, emailAddress, firstName, lastName, jobTitle
和 group
。如果你想映射一些自定义字段,你必须使用自定义映射。这两种情况都工作正常,但我们真正想要的是将 LDAP 属性 preferredLanguage
映射到用户 languageId
,因此 Liferay 中的用户语言是基于 LDAP 值设置的。
我们尝试过的:
在标准 ldap.user.mappings
中将 preferredLanguage
映射到 languageId
因此 portalpreferences
table 条目中的条目如下所示:
...<preference>
<name>ldap.user.mappings.21597</name>
<value>emailAddress=uid[$NEW_LINE$]firstName=givenName[$NEW_LINE$]group=memberOf[$NEW_LINE$]lastName=sn[$NEW_LINE$]languageId=preferredLanguage</value>
</preference>...
将它映射到 ldap.user.custom.mappings
所以 portalpreferences
table 条目是:
...<preference>
<name>ldap.user.custom.mappings.21597</name>
<value>...ourCustomAttributes...[$NEW_LINE$]languageId=preferredLanguage</value>
</preference>...
都不行。唯一有效的是在 Liferay 中创建自定义用户字段,例如custLanguage
并将 preferredLanguage
映射到该字段。但是我们不知道如何将值从 custLanguage
传递给用户显示设置 languageId
,因此该用户的语言会自动更改。
许多用户在使用 Liferay 语言 LDAP 导入时遇到问题,例如https://issues.liferay.com/browse/LPS-23143。我假设如果你可以添加 languageId
到忽略列表,你也可以导入它。
This question 与我们的问题相对应,但解决方案是使用自定义字段,我们不知道如何进一步详细说明。
所以我们的问题是:
- 是否可以将我们的自定义 LDAP 属性
preferredLanguage
直接映射到 Liferay 用户的 languageId
?
- 如果以上不可能,你必须使用自定义属性,我们应该如何将自定义用户语言属性的值传递到他的语言显示设置?
如评论中所述,我发现执行此类任务的唯一方法是编写自定义 LDAPImporterImpl
并将其放入 EXT 插件中。这是我的代码片段:
import com.liferay.portal.security.ldap.PortalLDAPImporterImpl
// other imports
public class CustomPortalLDAPImporterImpl extends PortalLDAPImporterImpl {
@Override
public User importLDAPUser(long ldapServerId, long companyId, LdapContext ldapContext, Attributes attributes, String password) throws Exception {
User user = super.importLDAPUser(ldapServerId, companyId, ldapContext, attributes, password);
String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
String baseDN = PrefsPropsUtil.getString(companyId, PropsKeys.LDAP_BASE_DN + postfix);
Attributes completeUserAttributes = getUserLdapAttributes(ldapContext, user, baseDN);
setUserAddress(user, completeUserAttributes);
setUserPhones(user, completeUserAttributes);
return user;
}
// ...
private Attributes getUserLdapAttributes(LdapContext ctx, User user, String baseDN) {
String searchFilter = "(&(objectClass=person)(sAMAccountName=" + user.getScreenName() + "))";
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration<SearchResult> results;
try {
log.debug("Searching LDAP with the following filter: " + searchFilter);
results = ctx.search(baseDN, searchFilter, searchControls);
SearchResult searchResult = null;
if(results.hasMoreElements()) {
searchResult = (SearchResult) results.nextElement();
if(results.hasMoreElements()) {
log.error("Matched multiple users for the user: " + user.getScreenName());
return null;
}
Attributes attributes = searchResult.getAttributes();
return attributes;
} else {
log.error("No LDAP record for username [" + user.getScreenName() + "] found.");
}
} catch (NamingException e) {
log.error("Error getting attributes for user [" + user.getScreenName() + "]: " + e.getMessage());
}
return null;
}
// ...
}
您还必须在 EXT 插件的 META-INF/ext-spring.xml
文件中定义此导入器:
<?xml version="1.0"?>
<beans
default-destroy-method="destroy"
default-init-method="afterPropertiesSet"
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd" >
<bean id="ldapToPortalConverter" class="com.liferay.portal.security.ldap.DefaultLDAPToPortalConverter" />
<bean id="portalToLDAPConverter" class="com.liferay.portal.security.ldap.DefaultPortalToLDAPConverter" />
<bean id="com.liferay.portal.security.ldap.PortalLDAPExporterUtil" class="com.liferay.portal.security.ldap.PortalLDAPExporterUtil">
<property name="portalLDAPExporter">
<bean class="com.liferay.portal.security.ldap.PortalLDAPExporterImpl">
<property name="portalToLDAPConverter" ref="portalToLDAPConverter" />
</bean>
</property>
</bean>
<bean id="com.liferay.portal.security.ldap.PortalLDAPImporterUtil" class="com.liferay.portal.security.ldap.PortalLDAPImporterUtil">
<property name="portalLDAPImporter">
<bean class="ch.openinteractive.familea.security.ldap.CustomPortalLDAPImporterImpl">
<property name="LDAPToPortalConverter" ref="ldapToPortalConverter" />
</bean>
</property>
</bean>
</beans>
如果有人提出更好、侵入性更小的解决方案,我会很高兴。
我们正在使用 Liferay 6.2 GA4,它允许您仅映射几个基本属性以导入 LDAP 用户:
screenName, password, emailAddress, firstName, lastName, jobTitle
和 group
。如果你想映射一些自定义字段,你必须使用自定义映射。这两种情况都工作正常,但我们真正想要的是将 LDAP 属性 preferredLanguage
映射到用户 languageId
,因此 Liferay 中的用户语言是基于 LDAP 值设置的。
我们尝试过的:
在标准
ldap.user.mappings
中将preferredLanguage
映射到languageId
因此portalpreferences
table 条目中的条目如下所示:...<preference> <name>ldap.user.mappings.21597</name> <value>emailAddress=uid[$NEW_LINE$]firstName=givenName[$NEW_LINE$]group=memberOf[$NEW_LINE$]lastName=sn[$NEW_LINE$]languageId=preferredLanguage</value> </preference>...
将它映射到
ldap.user.custom.mappings
所以portalpreferences
table 条目是:...<preference> <name>ldap.user.custom.mappings.21597</name> <value>...ourCustomAttributes...[$NEW_LINE$]languageId=preferredLanguage</value> </preference>...
都不行。唯一有效的是在 Liferay 中创建自定义用户字段,例如custLanguage
并将 preferredLanguage
映射到该字段。但是我们不知道如何将值从 custLanguage
传递给用户显示设置 languageId
,因此该用户的语言会自动更改。
许多用户在使用 Liferay 语言 LDAP 导入时遇到问题,例如https://issues.liferay.com/browse/LPS-23143。我假设如果你可以添加 languageId
到忽略列表,你也可以导入它。
This question 与我们的问题相对应,但解决方案是使用自定义字段,我们不知道如何进一步详细说明。 所以我们的问题是:
- 是否可以将我们的自定义 LDAP 属性
preferredLanguage
直接映射到 Liferay 用户的languageId
? - 如果以上不可能,你必须使用自定义属性,我们应该如何将自定义用户语言属性的值传递到他的语言显示设置?
如评论中所述,我发现执行此类任务的唯一方法是编写自定义 LDAPImporterImpl
并将其放入 EXT 插件中。这是我的代码片段:
import com.liferay.portal.security.ldap.PortalLDAPImporterImpl
// other imports
public class CustomPortalLDAPImporterImpl extends PortalLDAPImporterImpl {
@Override
public User importLDAPUser(long ldapServerId, long companyId, LdapContext ldapContext, Attributes attributes, String password) throws Exception {
User user = super.importLDAPUser(ldapServerId, companyId, ldapContext, attributes, password);
String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
String baseDN = PrefsPropsUtil.getString(companyId, PropsKeys.LDAP_BASE_DN + postfix);
Attributes completeUserAttributes = getUserLdapAttributes(ldapContext, user, baseDN);
setUserAddress(user, completeUserAttributes);
setUserPhones(user, completeUserAttributes);
return user;
}
// ...
private Attributes getUserLdapAttributes(LdapContext ctx, User user, String baseDN) {
String searchFilter = "(&(objectClass=person)(sAMAccountName=" + user.getScreenName() + "))";
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration<SearchResult> results;
try {
log.debug("Searching LDAP with the following filter: " + searchFilter);
results = ctx.search(baseDN, searchFilter, searchControls);
SearchResult searchResult = null;
if(results.hasMoreElements()) {
searchResult = (SearchResult) results.nextElement();
if(results.hasMoreElements()) {
log.error("Matched multiple users for the user: " + user.getScreenName());
return null;
}
Attributes attributes = searchResult.getAttributes();
return attributes;
} else {
log.error("No LDAP record for username [" + user.getScreenName() + "] found.");
}
} catch (NamingException e) {
log.error("Error getting attributes for user [" + user.getScreenName() + "]: " + e.getMessage());
}
return null;
}
// ...
}
您还必须在 EXT 插件的 META-INF/ext-spring.xml
文件中定义此导入器:
<?xml version="1.0"?>
<beans
default-destroy-method="destroy"
default-init-method="afterPropertiesSet"
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd" >
<bean id="ldapToPortalConverter" class="com.liferay.portal.security.ldap.DefaultLDAPToPortalConverter" />
<bean id="portalToLDAPConverter" class="com.liferay.portal.security.ldap.DefaultPortalToLDAPConverter" />
<bean id="com.liferay.portal.security.ldap.PortalLDAPExporterUtil" class="com.liferay.portal.security.ldap.PortalLDAPExporterUtil">
<property name="portalLDAPExporter">
<bean class="com.liferay.portal.security.ldap.PortalLDAPExporterImpl">
<property name="portalToLDAPConverter" ref="portalToLDAPConverter" />
</bean>
</property>
</bean>
<bean id="com.liferay.portal.security.ldap.PortalLDAPImporterUtil" class="com.liferay.portal.security.ldap.PortalLDAPImporterUtil">
<property name="portalLDAPImporter">
<bean class="ch.openinteractive.familea.security.ldap.CustomPortalLDAPImporterImpl">
<property name="LDAPToPortalConverter" ref="ldapToPortalConverter" />
</bean>
</property>
</bean>
</beans>
如果有人提出更好、侵入性更小的解决方案,我会很高兴。