如何将 cookie 从 WebViewClient 保存到 URLConnection、浏览器或 Android 中的其他文件下载技术

发布于 2024-10-21 00:58:26 字数 1001 浏览 2 评论 0 原文

我们有一个启用 .net forms auth 的网站,用户可以通过 Android 应用程序中的 WebViewClient 访问该网站。该网站的功能之一是能够登录并下载一些 PDF 文件,但您需要登录才能下载 PDF。

我们目前正在实现 shouldOverrideUrlLoading ,并在满足正确条件时通过以下代码下载 pdf。

URL u = new URL(url);
URLConnection conn = u.openConnection();
int contentLength = conn.getContentLength();

DataInputStream stream = new DataInputStream(u.openStream());

byte[] buffer = new byte[contentLength];
stream.readFully(buffer);
stream.close();

DataOutputStream fos = new DataOutputStream(new FileOutputStream("/sdcard/download/file.pdf"));
fos.write(buffer);
fos.flush();
fos.close();

从 IIS 日志中可以明显看出,IIS 不认为该请求已登录,并将其重定向到登录页面。

我们需要的是一种在文件下载请求中保留 auth cookie 来下载文件的方法,但我们不知道如何保留 cookie。

对我们来说另一个可行的解决方案是在 WebViewClient 和 Android 浏览器之间保留 auth cookie。如果我们能做到这一点,我们只需通过浏览器中的默认操作打开 PDF 文件即可。

编辑:看起来我可以通过以下方式手动设置身份验证 cookie

conn.setRequestProperty("Cookie", "");

现在我只需要弄清楚如何从 WebViewClient 中读取身份验证 cookie

We have a .net forms auth enabled site that the user visits via a WebViewClient in our android app. One of the features of the site is the ability to login and download some PDF files, however you need to be logged in to download the PDFs.

We are currently implementing shouldOverrideUrlLoading and are downloading the pdf via the following code when the correct condition is met.

URL u = new URL(url);
URLConnection conn = u.openConnection();
int contentLength = conn.getContentLength();

DataInputStream stream = new DataInputStream(u.openStream());

byte[] buffer = new byte[contentLength];
stream.readFully(buffer);
stream.close();

DataOutputStream fos = new DataOutputStream(new FileOutputStream("/sdcard/download/file.pdf"));
fos.write(buffer);
fos.flush();
fos.close();

From the IIS logs, its apparent that IIS does not consider this request to be logged in and redirects it to the login page.

What we need is a way to download the file with the auth cookie persisted in the file download request but we are at a loss as to how to persist the cookie.

Another viable solution for us is to persist the auth cookie between the WebViewClient and the android browser. If we could do that, we'd just open the PDF file via the default action in the browser.

Edit: It looks like I can set the auth cookie manually via

conn.setRequestProperty("Cookie", "");

Now I just need to figure out how to read the auth cookie out of the WebViewClient

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

∞觅青森が 2024-10-28 00:58:26

由于您使用的是 ASP.NET Forms 身份验证,因此您需要从 forms auth cookie。 com/reference/android/webkit/WebView.html" rel="noreferrer">WebViewURLConnection。幸运的是,这非常简单。此代码位于 shouldOverrideUrlLoading

string url = "http://site/generatePdfBehindFormsAuth";

// get an instance of a cookie manager since it has access to our auth cookie
CookieManager cookieManager = CookieManager.getInstance();

// get the cookie string for the site.  This looks something like ".ASPXAUTH=data"
String auth = cookieManager.getCookie(url).toString();

URLConnection conn = (URLConnection)new URL(url).openConnection();

// Set the cookie string to be sent for download.  In our case we're just copying the
//   entire cookie string from the previous connection, so all values stored in 
//   cookies are persisted to this new connection.  This includes the aspx auth 
//   cookie, otherwise it would not be authenticated
//   when downloading the file.  
conn.setRequestProperty("Cookie", auth);
conn.setDoOutput(true);
conn.connect();

// get the filename from the servers response, its typical value is something like:
//   attachment; filename="GeneratedPDFFilename.pdf"
String filename = conn.getHeaderField("Content-Disposition").split("\"")[1];

// by default, we'll store the pdf in the external storage directory
String fileRoot = "/sdcard/";

// Complete the download
FileOutputStream f = new FileOutputStream(new File(fileRoot, filename));
InputStream in = conn.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
while ( (len1 = in.read(buffer)) > 0 ) 
{
    f.write(buffer,0, len1);
}
f.close();
in.close();

注意:需要注意的一件事是,您不应该拨打getContentLength 在您的 < a href="http://developer.android.com/reference/java/net/URLConnection.html" rel="noreferrer">URLConnection。经过4个小时的调试,wireshark终于表明,如果你调用 getContentLength,将为获取内容长度的请求发送 cookie,但不会为后续请求发送 cookie,即使在同一 URLConnection 实例上< /强>。也许我很天真,这是设计使然(文档没有表明这是设计使然),但我无法通过调用 setRequestProperty 调用后getContentLength。如果我尝试这么做,我就会被强行逼近。

Since you're using ASP.NET Forms authentication, you'll need to copy the forms auth cookie from the WebView to the URLConnection. Luckily this is pretty straight forward. This code lives in an implementation of shouldOverrideUrlLoading

string url = "http://site/generatePdfBehindFormsAuth";

// get an instance of a cookie manager since it has access to our auth cookie
CookieManager cookieManager = CookieManager.getInstance();

// get the cookie string for the site.  This looks something like ".ASPXAUTH=data"
String auth = cookieManager.getCookie(url).toString();

URLConnection conn = (URLConnection)new URL(url).openConnection();

// Set the cookie string to be sent for download.  In our case we're just copying the
//   entire cookie string from the previous connection, so all values stored in 
//   cookies are persisted to this new connection.  This includes the aspx auth 
//   cookie, otherwise it would not be authenticated
//   when downloading the file.  
conn.setRequestProperty("Cookie", auth);
conn.setDoOutput(true);
conn.connect();

// get the filename from the servers response, its typical value is something like:
//   attachment; filename="GeneratedPDFFilename.pdf"
String filename = conn.getHeaderField("Content-Disposition").split("\"")[1];

// by default, we'll store the pdf in the external storage directory
String fileRoot = "/sdcard/";

// Complete the download
FileOutputStream f = new FileOutputStream(new File(fileRoot, filename));
InputStream in = conn.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
while ( (len1 = in.read(buffer)) > 0 ) 
{
    f.write(buffer,0, len1);
}
f.close();
in.close();

NOTE: One thing to be aware of is that you should NOT make a call to getContentLength on your URLConnection. After 4 hours of debugging, wireshark finally showed that, if you call getContentLength, the cookie would be sent for the request that gets the content length, but the cookie will not be sent for subsequent requests, even on the same instance of URLConnection. Maybe I am naive and this is by design (the documentation does not indicate that it is by design), but I was unable to manually set the cookie for the subsequent file request by calling setRequestProperty after calling getContentLength. If I attempted to do that, I'd get a force close.

秋心╮凉 2024-10-28 00:58:26

您看过 CookieSyncManager 类吗?我相信这是保存从服务器接收到的 cookie 并重新使用它们所需要的。

http://developer.android.com/reference/android/webkit/CookieSyncManager.html

Have you looked at the CookieSyncManager class? I believe this is what is needed to persist cookies received from the server and re-use them.

http://developer.android.com/reference/android/webkit/CookieSyncManager.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文