【问题标题】:Using HTTP Basic-Auth with Google App Engine URLFetch service将 HTTP Basic-Auth 与 Google App Engine URLFetch 服务结合使用
【发布时间】:2010-11-23 09:18:41
【问题描述】:

如何指定用户名和密码以使用 App Engine 的 URLFetch 服务(在 Java 中)发出 Basic-Auth 请求?

看来我可以设置 HTTP 标头:

URL url = new URL("http://www.example.com/comment");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("X-MyApp-Version", "2.7.3");        

Basic-Auth 的适当标头是什么?

【问题讨论】:

  • 那么,这真的是 App Engine 问题吗?只需查看 HTTP RFC 以了解如何进行基本身份验证(提示 - 'Authorization')。
  • 我希望 App Engine 可能有一个类似于 Apache HttpClient 的便利包装器,这样我就不必手动设置(和 base64 编码)Authorization 标头。

标签: java google-app-engine basic-authentication


【解决方案1】:

这是基于 http 的基本身份验证标头:

授权:基本 base64 编码(用户名:密码)

例如:

GET /private/index.html HTTP/1.0
Host: myhost.com
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

您需要这样做:

URL url = new URL("http://www.example.com/comment");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Authorization",
"Basic "+codec.encodeBase64String(("username:password").getBytes());

为此,您需要获取 base64 编解码器 API,例如 Apache Commons Codec

【讨论】:

  • 这就是我最终要做的。由于我将 username:password 作为属性放在 appengine-web.xml 中,我只是将编码版本直接放在那里,所以我什至不需要编解码器。 (你可以使用 openssl 命令行: echo -n "username:password" | openssl enc -base64 )
  • +1 这也解决了我即将遇到的 HTTP 身份验证问题。谢谢。哦,getBytes() 需要另一个 ) 来关闭 setRequestProperty。
【解决方案2】:

对于那些有兴趣在 Python 中执行此操作的人(就像我一样),代码如下所示:

result = urlfetch.fetch("http://www.example.com/comment",
                        headers={"Authorization": 
                                 "Basic %s" % base64.b64encode("username:pass")})

【讨论】:

  • 我相信代码应该如下: result = urlfetch.fetch( "yourserver.com/page/init.php, headers = { "Authorization": "Basic %s" % base64.encodestring("username:password" )[:-1] });
  • 更新为使用 base64.b64encode。我知道它有效,因为它是我在真实代码中实际使用的。
【解决方案3】:

你在像这样调用 openConnection() 之前设置了一个 Authenticator,

Authenticator.setDefault(new Authenticator() {
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(username, password.toCharArray());
    }
});

由于只有一个全局默认身份验证器,因此当您有多个用户在多个线程中执行 URLFetch 时,这并不能很好地工作。如果是这样,我会使用 Apache HttpClient。

编辑:我错了。 App Engine 不允许身份验证器。即使允许,我们也会遇到全局验证器实例的多线程问题。即使您无法创建线程,您的请求仍可能在不同的线程中得到处理。所以我们只是使用这个函数手动添加标题,

import com.google.appengine.repackaged.com.google.common.util.Base64;
    /**
     * Preemptively set the Authorization header to use Basic Auth.
     * @param connection The HTTP connection
     * @param username Username
     * @param password Password
     */
    public static void setBasicAuth(HttpURLConnection connection,
            String username, String password) {
        StringBuilder buf = new StringBuilder(username);
        buf.append(':');
        buf.append(password);
        byte[] bytes = null;
        try {
            bytes = buf.toString().getBytes("ISO-8859-1");
        } catch (java.io.UnsupportedEncodingException uee) {
            assert false;
        }

        String header = "Basic " + Base64.encode(bytes);
        connection.setRequestProperty("Authorization", header);
    }

【讨论】:

  • App Engine 上只有一个线程...(顺便问一下,是否有任何文档可以保证是这种情况?)
  • 我们遇到了一些问题,我以为是线程问题。下周回到办公室时,我将与实施此功能的人核实。
  • 刚刚与将我们的应用程序移植到 Google 的人进行了交谈。查看我的编辑。
【解决方案4】:

使用HttpURLConnection 给了我一些问题(由于某种原因,我尝试连接的服务器不接受身份验证凭据),最后我意识到使用 GAE 的低级 URLFetch API 实际上要容易得多( com.google.appengine.api.urlfetch) 像这样:

URL fetchurl = new URL(url);

String nameAndPassword = credentials.get("name")+":"+credentials.get("password");
String authorizationString = "Basic " + Base64.encode(nameAndPassword.getBytes());

HTTPRequest request = new HTTPRequest(fetchurl);
request.addHeader(new HTTPHeader("Authorization", authorizationString));

HTTPResponse response = URLFetchServiceFactory.getURLFetchService().fetch(request);
System.out.println(new String(response.getContent()));

这行得通。

【讨论】:

  • 这应该是公认的答案,你也可以设置超时时间:FetchOptions fetchOptions = FetchOptions.Builder.withDeadline(10); HTTPRequest req = new HTTPRequest(fetchurl, HTTPMethod.GET, fetchOptions);
【解决方案5】:
【解决方案6】:

注意第一个答案:setRequestProperty 应该获取不带冒号的属性名称(“Authorization”而不是“Authorization:”)。

【讨论】:

    猜你喜欢
    • 2012-02-26
    • 2015-10-24
    • 1970-01-01
    • 1970-01-01
    • 2020-04-29
    • 2020-05-26
    • 2014-08-26
    • 2014-03-29
    • 1970-01-01
    相关资源
    最近更新 更多