WS-security (usernametoken) для CXF - возможны ли зашифрованные пароли?
Я пытаюсь собраться вместе с реализацией WS-безопасности CXF (usernametoken). Я сделал все, как сказано на http://cxf.apache.org/docs/ws-security.html. Мой PasswordCallbackHandler, кажется, работает, но то, что беспокоит меня, является частью:
if (pc.getIdentifier().equals("joe")) {
// set the password on the callback. This will be compared to the
// password which was sent from the client.
pc.setPassword("password");
}
как сказал
Обратите внимание, что вплоть до CXF 2.3.x включительно проверка пароля в особом случае обычного текстового пароля (или любого другого, пока неизвестного типа пароля) делегируется классу обратного вызова, см. Org.apache.ws.security.processor.UsernameTokenProcessor#handleUsernameToken(), метод javadoc проекта WSS4J. В этом случае ServerPasswordCallback должен выглядеть примерно так:
так что до cxf 2.3.x было сделано так
if (pc.getIdentifer().equals("joe") {
if (!pc.getPassword().equals("password")) {
throw new IOException("wrong password");
}
}
Моя проблема: я не хочу pc.setPassword("plainTextPassword"), поскольку я хочу сохранить его в любом ресурсе. Этот дизайн до 2.3.x позволил бы мне сделать это, так как я мог зашифровать его вручную. Есть ли способы установить зашифрованный пароль в обратном вызове или выполнить аутентификацию на основе имени пользователя для сохраненных зашифрованных паролей?
Я использую cxf 2.5.x
2 ответа
Ответ (который я пробовал) находится на этой странице блога:
http://coheigea.blogspot.com/2011/06/custom-token-validation-in-apache-cxf.html
Суть в том, чтобы создать подкласс org.apache.ws.security.validate.UsernameTokenValidator и переопределить метод verifyPlaintextPassword. В этом методе передается UsernameToken (который предоставляет getName и getPassword). Бросьте исключение, если они не действительны.
Чтобы установить пользовательский валидатор в конфигурации пружины, добавьте, например,
<jaxws:properties>
<entry key="ws-security.ut.validator">
<bean class="com.example.webservice.MyCustomUsernameTokenValidator" />
</entry>
</jaxws:properties>
в
Обработчики обратного вызова предназначены для предоставления пароля в виде открытого текста или проверки пароля дайджеста, если известен пароль в виде открытого текста.
Но если вы не знаете открытый текст, т.е. его односторонний хэширование, то интерфейс обратного вызова не подходит, и вы должны создать класс, который реализует интерфейс Validator.
Вот мой пример реализации этого интерфейса, в котором используется репозиторий JPA, в котором пароль уже хранится в виде хэша BCrypt.
Используйте с ws-security.ut.validator
собственность задокументирована здесь
т.е. как свойство CXF<entry key="ws-security.ut.validator" value-ref="com.package.CustomUsernameTokenValidator" />
public class CustomUsernameTokenValidator implements Validator {
@Autowired
ProfileRepository profileRepository;
@Override
public Credential validate(Credential credential, RequestData requestData) throws WSSecurityException {
Profile profile = profileRepository.findByName(credential.getUsernametoken().getName());
if (profile != null) {
if (BCrypt.checkpw(credential.getUsernametoken().getPassword(), profile.getPassword())) {
return credential;
}
}
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
}
}