要验证的请求,我用Authenticator.setDefault
这是VM宽...
如果我想单独不同的web服务 并且每一个都知道自己的身份验证凭据。
对于每个请求,我是否需要Authenticator.setDefault
?
如果存在并发连接的混合Web服务,这可能不起作用...如何处理多个身份验证
3
A
回答
-1
缺少答案往往意味着没有人知道,这告诉我没有答案。
我一直在想同样的事情,我想答案是它不能通过java.net来完成。我认为你需要一次限制你的http访问到一台服务器,或者查看其他包,比如org.apache.http.client。
0
这是我实施的解决方案,它的作用就像一个魅力!
import java.net.*;
import java.util.*;
import java.util.logging.*;
import java.util.regex.*;
/**
* Authenticator which keeps credentials to be passed to the requester
* based on the concatenation of the authority and the URL that requires
* authentication.
*
* If the configured credentials are not found, the Authenticator will
* use the embedded credentials if present.
*
* Embedded credentials are in the form of <pre><b>user</b>:<b>password</b><i>@host:port/<url-path></i></pre>
*
* @author Michael Fortin 2011-09-23
*/
public class Authenticator extends java.net.Authenticator {
private Logger log = Logger.getLogger(this.getClass().getName());
private Map<String, PasswordAuthentication> authInfos;
private Pattern embeddedAuthInfoPattern;
@Override
protected PasswordAuthentication getPasswordAuthentication() {
String requesterInfo = String.format("%s%s", getRequestingURL().getAuthority(), getRequestingURL().getPath());
log.fine(String.format("%s at \"%s\" is requesting %s password authentication for \"%s\"", getRequestorType(), getRequestingPrompt(), getRequestingScheme(), requesterInfo));
PasswordAuthentication pa = null;
if ((pa = authInfos.get(requesterInfo)) == null && (pa = getEmbeddedPA(getRequestingURL().getAuthority())) == null) {
log.warning(String.format("No authentication information for \"%s\"", requesterInfo));
}
return pa;
}
public void setAuthInfos(Map<String, PasswordAuthentication> authInfos) {
this.authInfos = authInfos;
}
public void setEmbeddedAuthInfoPattern(String pattern) {
this.embeddedAuthInfoPattern = Pattern.compile(pattern);
}
private PasswordAuthentication getEmbeddedPA(String authInfo) {
if (authInfo != null) {
Matcher matcher = embeddedAuthInfoPattern.matcher(authInfo);
if (matcher.find()) {
return new PasswordAuthentication(matcher.group(1), matcher.group(2).toCharArray());
}
}
return null;
}
}
2
迈克的反应大厦上面我有以下的解决方案,因为虽然我非常赞赏的总体思路(这就是为什么我把它抄了;-),我看到几个问题吧:
- 如果JDK通过java.net.Authenticator中的两个不通过URL的静态请求方法之一请求身份验证,那么Mike的解决方案将抛出NullPointerException(然后getRequestingURL()将返回null)。
- 它要求您传入解构URL的外部正则表达式模式。这非常容易出错,并且JDK中的URL类实现了此解析,所以我更愿意使用它。
- 它需要某个外部类构建PasswordAuthentication对象的映射,然后进行设置。它没有实现系统中其他组件可以使用的注册机制。我也把它变成了一个单身人士。
- 更多的风格:我不建议重复类名称(Authenticator),所以我将它重命名为DefaultAuthenticator。
下面的解决方案我认为解决了这些问题。
/**
* Authenticator which keeps credentials to be passed to the requestor based on authority of the requesting URL. The
* authority is <pre>user:[email protected]:port</pre>, where all parts are optional except the host.
* <p>
* If the configured credentials are not found, the Authenticator will use the credentials embedded in the URL, if
* present. Embedded credentials are in the form of <pre>user:[email protected]:port</pre>
*
* @author Michael Fortin 2011-09-23
*/
public final class DefaultAuthenticator extends Authenticator {
private static final Logger LOG = Logger.getLogger(DefaultAuthenticator.class.getName());
private static DefaultAuthenticator instance;
private Map<String, PasswordAuthentication> authInfo = new HashMap<String, PasswordAuthentication>();
private DefaultAuthenticator() {
}
public static synchronized DefaultAuthenticator getInstance() {
if (instance == null) {
instance = new DefaultAuthenticator();
Authenticator.setDefault(instance);
}
return instance;
}
// unit testing
static void reset() {
instance = null;
Authenticator.setDefault(null);
}
@Override
protected PasswordAuthentication getPasswordAuthentication() {
String requestorInfo = getRequestorInfo();
LOG.info(getRequestorType() + " at \"" + getRequestingPrompt() + "\" is requesting " + getRequestingScheme()
+ " password authentication for \"" + requestorInfo + "\"");
if (authInfo.containsKey(requestorInfo)) {
return authInfo.get(requestorInfo);
} else {
PasswordAuthentication pa = getEmbeddedCredentials(getRequestingURL());
if (pa == null) {
LOG.warning("No authentication information");
}
return pa;
}
}
/**
* Register the authentication information for a given URL.
*
* @param url - the URL that will request authorization
* @param auth - the {@link PasswordAuthentication} for this URL providing the credentials
*/
public void register(URL url, PasswordAuthentication auth) {
String requestorInfo = getRequestorInfo(url.getHost(), url.getPort());
authInfo.put(requestorInfo, auth);
}
/**
* Get the requestor info based on info provided.
*
* @param host - hostname of requestor
* @param port - TCP/IP port
* @return requestor info string
*/
private String getRequestorInfo(String host, int port) {
String fullHostname;
try {
InetAddress addr = InetAddress.getByName(host);
fullHostname = addr.getCanonicalHostName();
} catch (UnknownHostException e) {
fullHostname = host;
}
if (port == -1) {
return fullHostname;
} else {
return fullHostname + ":" + port;
}
}
/**
* Get the requestor info for the request currently being processed by this Authenticator.
*
* @return requestor info string for current request
*/
private String getRequestorInfo() {
String host;
InetAddress addr = getRequestingSite();
if (addr == null) {
host = getRequestingHost();
} else {
host = addr.getCanonicalHostName();
}
return getRequestorInfo(host, getRequestingPort());
}
/**
* Get the credentials from the requesting URL.
*
* @param url - URL to get the credentials from (can be null, method will return null)
* @return PasswordAuthentication with credentials from URL or null if URL contains no credentials or if URL is
* null itself
*/
PasswordAuthentication getEmbeddedCredentials(URL url) {
if (url == null) {
return null;
}
String userInfo = url.getUserInfo();
int colon = userInfo == null ? -1 : userInfo.indexOf(":");
if (colon == -1) {
return null;
} else {
String userName = userInfo.substring(0, colon);
String pass = userInfo.substring(colon + 1);
return new PasswordAuthentication(userName, pass.toCharArray());
}
}
}
虽然我在这里,让我给你我的单元测试(JUnit 4)。
/**
* @author Paul Balm - May 10 2012
*/
public class DefaultAuthenticatorTest {
private static final Logger LOG = Logger.getLogger(DefaultAuthenticatorTest.class.getName());
@Before
public void setUp() throws Exception {
DefaultAuthenticator.reset();
DefaultAuthenticator.getInstance();
}
@After
public void tearDown() {
DefaultAuthenticator.reset();
}
@Test
public void testRequestAuthenticationFromURL() throws MalformedURLException, UnknownHostException {
Map<String, String[]> urls = generateURLs();
for (String urlStr : urls.keySet()) {
String[] userInfo = urls.get(urlStr);
LOG.info("Testing: " + urlStr);
URL url = new URL(urlStr);
request(userInfo[1], userInfo[2], url, true);
}
}
@Test
public void testRequestAuthenticationRegistered() throws UnknownHostException, MalformedURLException {
Map<String, String[]> urls = generateURLs();
for (String urlStr : urls.keySet()) {
String[] userInfo = urls.get(urlStr);
LOG.info("Testing: " + urlStr);
URL url = new URL(urlStr);
DefaultAuthenticator.reset();
DefaultAuthenticator auth = DefaultAuthenticator.getInstance();
String userName = userInfo[1];
String password = userInfo[2];
if (password != null) {
// You can't register a null password
auth.register(url, new PasswordAuthentication(userName, password.toCharArray()));
}
request(userName, password, url, false);
}
}
/**
* Generate a bunch of URLs mapped to String array. The String array has the following elements:
* - user info part of URL,
* - expected user,
* - expected password
*
* Note that the keys of the maps must be strings and not URL objects, because of the way URL.equals is
* implemented. This method does not consider the credentials.
*
* @throws MalformedURLException
*/
Map<String, String[]> generateURLs() {
String[] hosts = new String[]{ "127.0.0.1", "localhost.localdomain"};
List<String[]> userData = new ArrayList<String[]>();
// normal cases
userData.add(new String[] { "user:[email protected]", "user", "pass" }); // results in: http://user:[email protected][host]
userData.add(new String[] { "", null, null });
// unexpected cases
userData.add(new String[] { "@", null, null });
userData.add(new String[] { ":@", "", "" });
userData.add(new String[] { "user:@", "user", "" });
userData.add(new String[] { ":[email protected]", "", "pass" });
Map<String, String[]> urls = new HashMap<String, String[]>();
for (String[] userInfo : userData) {
for (String host : hosts) {
String s = "http://" + userInfo[0] + host;
urls.put(s, userInfo);
}
}
LOG.info("" + urls.size() + " URLs prepared");
return urls;
}
private void request(String expectedUser, String expectedPass, URL url, boolean inURL)
throws UnknownHostException {
String host = url.getHost();
InetAddress addr = InetAddress.getAllByName(host)[0];
int port = url.getPort();
String protocol = url.getProtocol();
String prompt = ""; // prompt for the user when asking for the credentials
String scheme = "basic"; // or digest
RequestorType reqType = RequestorType.SERVER;
PasswordAuthentication credentials =
Authenticator.requestPasswordAuthentication(addr, port, protocol, prompt, scheme);
// If the credentials are in the URL, you can't find them using this method because we're not passing the URL
checkCredentials(url, inURL ? null : expectedUser, inURL ? null : expectedPass, credentials);
credentials = Authenticator.requestPasswordAuthentication(host, addr, port, protocol, prompt, scheme);
// If the credentials are in the URL, you can't find them using this method because we're not passing the URL
checkCredentials(url, inURL ? null : expectedUser, inURL ? null : expectedPass, credentials);
credentials = Authenticator.requestPasswordAuthentication(host, addr, port, protocol, prompt, scheme, url, reqType);
checkCredentials(url, expectedUser, expectedPass, credentials);
}
private void checkCredentials(URL url, String expectedUser, String expectedPass, PasswordAuthentication credentials) {
if (expectedUser == null) {
Assert.assertNull(url.toString(), credentials);
} else {
Assert.assertNotNull(url.toString(), credentials);
Assert.assertEquals(url.toString(), expectedUser, credentials.getUserName());
if (expectedPass == null) {
Assert.assertNull(url.toString(), credentials.getPassword());
} else {
Assert.assertArrayEquals(url.toString(), expectedPass.toCharArray(), credentials.getPassword());
}
}
}
}
相关问题
- 1. RestKit - 处理身份验证
- 2. 如何处理ASP.NET身份验证
- 3. 身份验证管理器中的交换机身份验证处理程序
- 4. 多个身份验证方案和WWW身份验证挑战
- 5. 处理Active Directory身份验证的多个域
- 6. 处理与多个会员供应商的身份验证
- 7. Tweepy多个身份验证处理程序
- 8. 在Okhttp中处理身份验证
- 9. Python身份验证和HTTP cookie处理
- 10. 使用HttpWebRequest处理身份验证(.NET)
- 11. 基本身份验证URL处理
- 12. 处理身份验证错误
- 13. AppEngine WebService身份验证处理
- 14. 在iOS中处理http身份验证
- 15. 处理Dropbox身份验证响应
- 16. curl身份验证头处理
- 17. 处理RestKit身份验证挑战
- 18. 身份验证请求事件处理程序 - 自定义身份验证IIS
- 19. Google如何管理多个域之间的身份验证?
- 20. 如何在Katana中编写多个身份验证处理程序?
- 21. 使用Windows身份验证的简单身份验证代理
- 22. cefsharp代理身份验证
- 23. Java代理身份验证
- 24. 身份验证代理
- 25. org.apache.http.impl.client.CloseableHttpClient代理身份验证
- 26. 管理员身份验证
- 27. Clickonce身份验证代理
- 28. Paramiko身份验证验证(原来是Python异常处理)
- 29. 如何使用Oracle身份管理器进行身份验证?
- 30. 如何使用Selenium WebDriver处理HtmlUnitDriver的身份验证?