一、SpringLDAP單點登錄
在企業級應用中,單點登錄(Single Sign-On,SSO)是非常重要的。SpringLDAP提供了良好的支持,使得我們可以輕鬆地實現SSO。
我們可以使用LDAP存儲用戶信息,比如用戶名和密碼等。一旦用戶通過認證,我們可以在Web應用中啟動一個會話來保存用戶的狀態。這樣,當用戶訪問其他應用時,這些應用就可以從會話中獲取用戶信息,而不需要再次進行認證。
下面是使用SpringLDAP實現SSO的示例代碼:
<bean id="contextSourceTarget" class="org.springframework.ldap.core.support.LdapContextSource">
<property name="url" value="ldap://ldap.example.org:389/dc=example,dc=org" />
<property name="base" value="cn=users,dc=example,dc=org" />
<property name="userDn" value="uid=admin,cn=users,dc=example,dc=org" />
<property name="password" value="secret" />
</bean>
<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="contextSourceTarget" />
</bean>
<bean id="ldapAuthenticationProvider"
class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
<constructor-arg>
<bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
<constructor-arg ref="contextSourceTarget" />
<property name="userSearch">
<bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<constructor-arg index="0" value="cn=users" />
<constructor-arg index="1" value="(uid={0})" />
<constructor-arg index="2" ref="contextSourceTarget" />
</bean>
</property>
</bean>
</constructor-arg>
<constructor-arg>
<bean class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
<constructor-arg ref="contextSourceTarget" />
<constructor-arg value="cn=groups" />
<property name="groupRoleAttribute" value="cn" />
<property name="searchSubtree" value="true" />
<property name="defaultRole" value="ROLE_USER" />
</bean>
</constructor-arg>
</bean>
<security:authentication-manager>
<security:authentication-provider ref="ldapAuthenticationProvider" />
</security:authentication-manager>
<security:http>
<security:intercept-url pattern="/secure/**" access="ROLE_USER" />
<security:form-login login-page="/login.html"
authentication-failure-url="/login.html?error=true"
default-target-url="/secure/index.html" />
</security:http>
二、Spring LDAP Template
SpringLDAP提供了LdapTemplate
類,可以極大地簡化訪問LDAP的代碼編寫過程。對於LDAP的讀、寫、修改、刪除等操作,LdapTemplate都提供了相應的方法,讓我們省去了自己編寫相應代碼的繁瑣工作,並且它還自帶對象映射功能,將LDAP中的數據轉換為Java對象。
下面是使用LdapTemplate讀取LDAP中的數據的示例:
<bean id="contextSourceTarget" class="org.springframework.ldap.core.support.LdapContextSource">
<property name="url" value="ldap://ldap.example.org:389/dc=example,dc=org" />
<property name="userDn" value="uid=admin,cn=users,dc=example,dc=org" />
<property name="password" value="secret" />
</bean>
<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="contextSourceTarget" />
</bean>
<bean id="personDao" class="com.example.PersonDao">
<property name="ldapTemplate" ref="ldapTemplate" />
</bean>
public class PersonDao {
private LdapTemplate ldapTemplate;
public List<Person> getAllPersons() {
return ldapTemplate.search(
"", "(objectClass=person)", new PersonAttributesMapper());
}
private static final class PersonAttributesMapper implements AttributesMapper {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
Person person = new Person();
person.setFullname((String)attributes.get("fullName").get());
person.setLastname((String)attributes.get("sn").get());
person.setDescription((String)attributes.get("description").get());
return person;
}
}
}
三、SpringLDAP只讀
有時候我們只是需要從LDAP中讀取數據而不需要進行任何的修改。SpringLDAP提供的LdapTemplateReadOnly
類可以讓我們只讀取LDAP數據而不增加任何的負擔。
下面是使用LdapTemplateReadOnly讀取LDAP中的數據的示例:
<bean id="contextSourceTarget" class="org.springframework.ldap.core.support.LdapContextSource">
<property name="url" value="ldap://ldap.example.org:389/dc=example,dc=org" />
<property name="userDn" value="uid=admin,cn=users,dc=example,dc=org" />
<property name="password" value="secret" />
</bean>
<bean id="ldapTemplateReadOnly" class="org.springframework.ldap.core.LdapTemplateReadOnly">
<constructor-arg ref="contextSourceTarget" />
</bean>
<bean id="personDao" class="com.example.PersonDao">
<property name="ldapTemplate" ref="ldapTemplateReadOnly" />
</bean>
public class PersonDao {
private LdapTemplateReadOnly ldapTemplate;
public List<Person> getAllPersons() {
return ldapTemplate.search(
"", "(objectClass=person)",
new PersonAttributesMapper());
}
private static final class PersonAttributesMapper implements AttributesMapper {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
Person person = new Person();
person.setFullname((String)attributes.get("fullName").get());
person.setLastname((String)attributes.get("sn").get());
person.setDescription((String)attributes.get("description").get());
return person;
}
}
}
四、SpringLDAP測試
SpringLDAP提供了非常便利的測試框架,可以幫助我們在沒有真實的LDAP服務器的情況下進行單元測試。
下面是使用SpringLDAP測試框架對LDAP操作進行單元測試的示例:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:test-context.xml")
public class PersonDaoTest {
@Autowired
private PersonDao personDao;
@Test
public void testFindAll() {
List<Person> personList = personDao.getAllPersons();
assertEquals(personList.size(), 2);
}
}
<bean id="contextSourceTarget" class="org.springframework.ldap.core.support.LdapContextSource">
<property name="url" value="ldap://localhost:8389/dc=example,dc=org" />
<property name="userDn" value="uid=admin,cn=users,dc=example,dc=org" />
<property name="password" value="secret" />
<property name="pooled" value="false" />
<property name="baseEnvironmentProperties">
<props>
<prop key="java.naming.security.principal">cn=admin,dc=example,dc=org</prop>
<prop key="java.naming.security.credentials">password</prop>
</props>
</property>
</bean>
<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="contextSourceTarget" />
</bean>
<bean id="personDao" class="com.example.PersonDao">
<property name="ldapTemplate" ref="ldapTemplate" />
</bean>
五、SpringLDAP創建用戶
使用SpringLDAP,我們可以很方便地實現LDAP用戶的添加、刪除、修改等操作,下面是使用LdapTemplate添加LDAP用戶的示例代碼:
public void addUser(User user) {
Name dn = buildDn(user);
ldapTemplate.bind(dn, null, buildAttributes(user));
}
private Name buildDn(User user) {
return LdapNameBuilder.newInstance()
.add("ou", "users")
.add("uid", user.getUsername())
.build();
}
private Attributes buildAttributes(User user) {
BasicAttributes basicAttributes = new BasicAttributes();
BasicAttribute objectClass = new BasicAttribute("objectClass");
objectClass.add("top");
objectClass.add("person");
basicAttributes.put(objectClass);
basicAttributes.put("cn", user.getUsername());
basicAttributes.put("sn", user.getLastName());
basicAttributes.put("userPassword", user.getPassword());
return basicAttributes;
}
六、SpringLDAP配置詳解
在使用SpringLDAP時,我們需要進行相應的配置,下面是一份常用的SpringLDAP配置:
<bean id="contextSourceTarget" class="org.springframework.ldap.core.support.LdapContextSource">
<property name="url" value="ldap://ldap.example.org:389/dc=example,dc=org" />
<property name="userDn" value="uid=admin,cn=users,dc=example,dc=org" />
<property name="password" value="secret" />
<property name="pooled" value="false" />
<property name="baseEnvironmentProperties">
<props>
<prop key="java.naming.security.principal">cn=admin,dc=example,dc=org</prop>
<prop key="java.naming.security.credentials">password</prop>
</props>
</property>
</bean>
<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="contextSourceTarget" />
</bean>
<context:annotation-config />
<context:component-scan base-package="com.example" />
七、SpringLDAP Token
在SpringLDAP中,我們可以使用DirContextOperations
對象來獲取當前的用戶信息。
下面是使用DirContextOperations
對象獲取用戶信息的示例代碼:
@Autowired
private LdapTemplate ldapTemplate;
public void printCurrentUser() {
DirContextOperations ctx = (DirContextOperations) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username = ctx.getStringAttribute("uid");
System.out.println("Current user: " + username);
}
八、SpringLDAP驗證用戶名和密碼
在SpringLDAP中,我們可以使用LdapTemplate
類中的authenticate()
方法驗證用戶名和密碼是否正確。
下面是使用LdapTemplate
類驗證用戶名和密碼的示例代碼:
@Autowired
private LdapTemplate ldapTemplate;
public boolean authenticate(String username, String password) {
AndFilter filter = new AndFilter();
filter.and(new EqualsFilter("objectclass", "person")).and(new EqualsFilter("uid", username));
return ldapTemplate.authenticate("", filter.toString(), password);
}
原創文章,作者:GNFJ,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/146359.html