javascript
spring ldap_Spring 3,Spring Web Services 2和LDAP安全
spring ldap
今年的開局很好,其中另一個(gè)“截止日期不會(huì)改變” /“跳過所有繁文tape節(jié)” / “狂野西部”類型的項(xiàng)目中,我必須弄清楚并使用相對(duì)而言實(shí)現(xiàn)一些功能。新的庫和技術(shù)需要進(jìn)行更改,Spring 3并不是新增功能,但是在Java 5,weblogic 10(.01)和Spring 2.5.6緩慢的企業(yè)環(huán)境中,這是相對(duì)的。由于一般的時(shí)間限制,我在這篇文章中沒有過多地介紹“ fluff”,只是使用多個(gè)XSD和LDAP安全性來創(chuàng)建和保護(hù)Spring 3和Spring WS 2 Web服務(wù)。
代碼:
服務(wù)端點(diǎn):ExampleServiceEndpoint
這是將在后面的配置中使用Web服務(wù)公開的類。
代碼:CustomValidationCallbackHandler
這是我編寫的用于擴(kuò)展AbstactCallbackHandler的自定義代碼,它允許我們使用LDAP。
根據(jù)下面的CallbackHandler中的注釋,最好有一個(gè)緩存管理器,例如Hazelcast或Ehcache來緩存經(jīng)過身份驗(yàn)證的用戶,這取決于安全/性能方面的考慮。
下面的Digest Validator可以直接在Sun庫中使用,我只是想了解它是如何工作的。
package javaitzen.spring.ws;import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException; import com.sun.xml.wss.impl.callback.PasswordValidationCallback; import com.sun.xml.wss.impl.misc.Base64; import org.springframework.beans.factory.InitializingBean; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.util.Assert; import org.springframework.ws.soap.security.callback.AbstractCallbackHandler;import javax.security.auth.callback.Callback; import javax.security.auth.callback.UnsupportedCallbackException; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.util.Properties;public class CustomValidationCallbackHandler extends AbstractCallbackHandler implements InitializingBean {private Properties users = new Properties();private AuthenticationManager ldapAuthenticationManager;@Overrideprotected void handleInternal(final Callback callback) throws IOException, UnsupportedCallbackException {if (callback instanceof PasswordValidationCallback) {final PasswordValidationCallback passwordCallback = (PasswordValidationCallback) callback;if (passwordCallback.getRequest() instanceof PasswordValidationCallback.DigestPasswordRequest) {final PasswordValidationCallback.DigestPasswordRequest digestPasswordRequest =(PasswordValidationCallback.DigestPasswordRequest) passwordCallback.getRequest();final String password = users.getProperty(digestPasswordRequest.getUsername());digestPasswordRequest.setPassword(password);passwordCallback.setValidator(new CustomDigestPasswordValidator());}if (passwordCallback.getRequest() instanceof PasswordValidationCallback.PlainTextPasswordRequest) {passwordCallback.setValidator(new LDAPPlainTextPasswordValidator());}} else {throw new UnsupportedCallbackException(callback);}}/*** Digest Validator.* This code is directly from the sun class, I was just curious how it worked.*/private class CustomDigestPasswordValidator implements PasswordValidationCallback.PasswordValidator {public boolean validate(final PasswordValidationCallback.Request request) throws PasswordValidationCallback.PasswordValidationException {final PasswordValidationCallback.DigestPasswordRequest req = (PasswordValidationCallback.DigestPasswordRequest) request;final String passwd = req.getPassword();final String nonce = req.getNonce();final String created = req.getCreated();final String passwordDigest = req.getDigest();final String username = req.getUsername();if (null == passwd)return false;byte[] decodedNonce = null;if (null != nonce) {try {decodedNonce = Base64.decode(nonce);} catch (final Base64DecodingException bde) {throw new PasswordValidationCallback.PasswordValidationException(bde);}}String utf8String = "";if (created != null) {utf8String += created;}utf8String += passwd;final byte[] utf8Bytes;try {utf8Bytes = utf8String.getBytes("utf-8");} catch (final UnsupportedEncodingException uee) {throw new PasswordValidationCallback.PasswordValidationException(uee);}final byte[] bytesToHash;if (decodedNonce != null) {bytesToHash = new byte[utf8Bytes.length + decodedNonce.length];for (int i = 0; i < decodedNonce.length; i++)bytesToHash[i] = decodedNonce[i];for (int i = decodedNonce.length;i < utf8Bytes.length + decodedNonce.length;i++)bytesToHash[i] = utf8Bytes[i - decodedNonce.length];} else {bytesToHash = utf8Bytes;}final byte[] hash;try {final MessageDigest sha = MessageDigest.getInstance("SHA-1");hash = sha.digest(bytesToHash);} catch (final Exception e) {throw new PasswordValidationCallback.PasswordValidationException("Password Digest could not be created" + e);}return (passwordDigest.equals(Base64.encode(hash)));}}/*** LDAP Plain Text validator.*/private class LDAPPlainTextPasswordValidator implementsPasswordValidationCallback.PasswordValidator {/*** Validate the callback against the injected LDAP server.* Probably a good idea to have a cache manager - ehcache / hazelcast injected to cache authenticated users.** @param request the callback request* @return true if login successful* @throws PasswordValidationCallback.PasswordValidationException**/public boolean validate(final PasswordValidationCallback.Request request) throws PasswordValidationCallback.PasswordValidationException {final PasswordValidationCallback.PlainTextPasswordRequest plainTextPasswordRequest =(PasswordValidationCallback.PlainTextPasswordRequest) request;final String username = plainTextPasswordRequest.getUsername();final Authentication authentication;final Authentication userPassAuth = new UsernamePasswordAuthenticationToken(username, plainTextPasswordRequest.getPassword());authentication = ldapAuthenticationManager.authenticate(userPassAuth);return authentication.isAuthenticated();}}/*** Assert users.** @throws Exception error*/public void afterPropertiesSet() throws Exception {Assert.notNull(users, "Users is required.");Assert.notNull(this.ldapAuthenticationManager, "A LDAP Authentication manager is required.");}/*** Sets the users to validate against. Property names are usernames, property values are passwords.** @param users the users*/public void setUsers(final Properties users) {this.users = users;}/*** The the authentication manager.** @param ldapAuthenticationManager the provider*/public void setLdapAuthenticationManager(final AuthenticationManager ldapAuthenticationManager) {this.ldapAuthenticationManager = ldapAuthenticationManager;} } 服務(wù)配置:
端點(diǎn),CallbackHandler和LDAP身份驗(yàn)證管理器的配置。
應(yīng)用程序上下文–服務(wù)器端:
安全上下文–服務(wù)器端:
xwss:SecurityConfiguration xmlns:xwss="http://java.sun.com/xml/ns/xwss/config"><xwss:RequireTimestamp maxClockSkew="60" timestampFreshnessLimit="300"/><!-- Expect plain text tokens from the client --><xwss:RequireUsernameToken passwordDigestRequired="false" nonceRequired="false"/><xwss:Timestamp/><!-- server side reply token --><xwss:UsernameToken name="server" password="server1" digestPassword="false" useNonce="false"/> </xwss:SecurityConfiguration> Web XML:
這里沒有什么特別的,只是Spring WS MessageDispatcherServlet。
客戶端配置:
要測(cè)試或使用該服務(wù),您需要:
應(yīng)用程序上下文–客戶端測(cè)試:
安全上下文–客戶端:
<xwss:SecurityConfiguration xmlns:xwss="http://java.sun.com/xml/ns/xwss/config"><xwss:RequireTimestamp maxClockSkew="60" timestampFreshnessLimit="300"/><!-- Expect a plain text reply from the server --><xwss:RequireUsernameToken passwordDigestRequired="false" nonceRequired="false"/><xwss:Timestamp/><!-- Client sending to server --><xwss:UsernameToken name="example" password="pass" digestPassword="false" useNonce="false"/> </xwss:SecurityConfiguration> 與Java一樣,在jar和版本方面可能會(huì)有一些細(xì)微差別,因此下面是我使用的pom的一部分。
依賴關(guān)系:
參考: Spring 3,Spring Web Services 2和LDAP安全。 來自我們的JCG合作伙伴 ? Zen博客中的Zen領(lǐng)域的 Brian Du Preez。
翻譯自: https://www.javacodegeeks.com/2012/02/spring-3-spring-web-services-2-ldap.html
spring ldap
總結(jié)
以上是生活随笔為你收集整理的spring ldap_Spring 3,Spring Web Services 2和LDAP安全的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么样才能让路由器中继信号腾达路由器如何
- 下一篇: JAX-RS和JSON-P集成