Java Веб-Сервис: Основная аутентификация клиента
Я создал веб-сервис JAX-WS на базе Glassfish, который требует базовой HTTP-аутентификации.
Теперь я хочу создать автономное клиентское Java-приложение для этого веб-сервиса, но у меня нет представления о том, как передать имя пользователя и пароль.
Всё работает с Web Service Explorer от Eclipse, и, изучая сетевой трафик, я заметил следующее:
POST /SnaProvisioning/SnaProvisioningV1_0 HTTP/1.1
Host: localhost:8080
Content-Type: text/xml; charset=utf-8
Content-Length: 311
Accept: application/soap+xml, application/dime, multipart/related, text/*
User-Agent: IBM Web Services Explorer
Cache-Control: no-cache
Pragma: no-cache
SOAPAction: ""
Authorization: Basic Z2VybWFuOmdlcm1hbg==
Connection: close
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:q0="http://ngin.ericsson.com/sna/types/v1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<q0:listServiceScripts/>
</soapenv:Body>
</soapenv:Envelope>
Как мне передать имя пользователя и пароль в заголовке "Authorization" с помощью Java-кода? Они хранятся в зашифрованном виде или что-то в этом роде? Каков алгоритм?
Без участия средств безопасности у меня есть работающий автономный Java-клиент:
SnaProvisioning myPort = new SnaProvisioning_Service().getSnaProvisioningV10Port();
myPort.listServiceScripts();
Чем-то похожим на то, что вы видите выше, является проблема и её детали. Как мне добавить аутентификацию?
5 ответ(ов)
По способу JAX-WS для базовой аутентификации вы можете использовать следующий код:
Service s = new Service();
Port port = s.getPort();
BindingProvider prov = (BindingProvider)port;
prov.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "myusername");
prov.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "mypassword");
port.call();
В этом примере создается экземпляр сервиса и порта, а затем через интерфейс BindingProvider
добавляются необходимые свойства для имени пользователя и пароля. После настройки аутентификации вы можете вызывать метод порта, который будет использовать указанные учетные данные.
Оказалось, что есть простой и стандартный способ достичь желаемого:
import java.net.Authenticator;
import java.net.PasswordAuthentication;
Authenticator myAuth = new Authenticator()
{
@Override
protected PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication("german", "german".toCharArray());
}
};
Authenticator.setDefault(myAuth);
В этом решении не используются никаких нестандартных "sun" классов или внешних зависимостей, и нет необходимости вручную кодировать что-либо.
Я понимаю, что BASIC аутентификация не является, скажем, самой безопасной, но мы также используем HTTPS.
Для клиента Axis2
может быть полезен следующий код, который демонстрирует, как настроить базовую аутентификацию:
...
serviceStub = new TestBeanServiceStub("<URL ВЕБ-СЕРВИСА>"); // Установите ваше значение
HttpTransportProperties.Authenticator basicAuthenticator = new HttpTransportProperties.Authenticator();
List<String> authSchemes = new ArrayList<String>();
authSchemes.add(Authenticator.BASIC);
basicAuthenticator.setAuthSchemes(authSchemes);
basicAuthenticator.setUsername("<ИмяПользователя>"); // Установите ваше значение
basicAuthenticator.setPassword("<Пароль>"); // Установите ваше значение
basicAuthenticator.setPreemptiveAuthentication(true);
serviceStub._getServiceClient().getOptions().setProperty(org.apache.axis2.transport.http.HTTPConstants.AUTHENTICATE, basicAuthenticator);
serviceStub._getServiceClient().getOptions().setProperty(org.apache.axis2.transport.http.HTTPConstants.CHUNKED, "false");
...
Этот код создает экземпляр класса TestBeanServiceStub
, настраивает необходимые параметры для аутентификации и добавляет их в клиент. Не забудьте заменить <URL ВЕБ-СЕРВИСА>
, <ИмяПользователя>
и <Пароль>
на ваши реальные данные.
В данном случае речь идет о базовой аутентификации, которая включает в себя заголовок с парой ключ/значение:
Authorization: Basic Z2VybWFuOmdlcm1hbg==
Здесь "Authorization" — это ключ заголовка, а значение заголовка представляет собой строку, к которой добавляются слово "Basic" и пробел перед закодированным в Base64 значением "Z2VybWFuOmdlcm1hbg==". Это значение соответствует логину и паролю, закодированным в Base64 и соединенным двоеточием.
Пример реализации на Java:
String name = "username";
String password = "secret";
String authString = name + ":" + password;
String authStringEnc = new BASE64Encoder().encode(authString.getBytes());
...
objectXXX.header("Authorization", "Basic " + authStringEnc);
В этом коде мы создаем строку authString
, которая содержит логин и пароль, разделенные двоеточием. Затем эта строка кодируется в формате Base64 и добавляется в заголовок запроса с ключом "Authorization". Убедитесь, что используете актуальную библиотеку для кодирования в Base64, так как BASE64Encoder
устарел в более поздних версиях Java. Вместо него можно использовать java.util.Base64
:
String authStringEnc = Base64.getEncoder().encodeToString(authString.getBytes());
Таким образом, происходит установка заголовка для базовой аутентификации в HTTP-запросе.
Если вы используете реализацию JAX-WS для вашего клиента, такую как Metro Web Services, следующий код демонстрирует, как передать имя пользователя и пароль в заголовках HTTP:
MyService port = new MyService();
MyServiceWS service = port.getMyServicePort();
Map<String, List<String>> credentials = new HashMap<String, List<String>>();
credentials.put("username", Collections.singletonList("username"));
credentials.put("password", Collections.singletonList("password"));
((BindingProvider)service).getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, credentials);
После этого последующие вызовы к сервису будут аутентифицированы. Обратите внимание, что пароль кодируется только с использованием Base64, поэтому я рекомендую использовать дополнительные механизмы, такие как клиентские сертификаты, для повышения уровня безопасности.
В чем разница между JSF, Servlet и JSP?
В чем разница между JPA и Hibernate? [закрыт]
Как распределяются потоки для обработки запросов Servlet?
Как заставить браузер скачать файл?
Можно ли подключиться к SQL Server с использованием Windows Authentication из веб-приложения Java EE?