我无法为 https 连接正确设置 user-agent 属性。根据我收集到的信息,可以通过 -Dhttp.agent VM 选项或通过 URLConnection.setRequestProperty() 设置 http-header 属性。 .但是,通过 VM 选项设置用户代理会导致“Java/[version]”附加到 http.agent 的任何值。同时 setRequestProperty() 只适用于 http 连接,不适用于 https(至少我试过的时候是这样)。
java.net.URL url = new java.net.URL( "https://www.google.com" );
java.net.URLConnection conn = url.openConnection();
conn.setRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 5.1; rv:19.0) Gecko/20100101 Firefox/19.0");
conn.connect();
java.io.BufferedReader serverResponse = new java.io.BufferedReader(new java.io.InputStreamReader(conn.getInputStream()));
System.out.println(serverResponse.readLine());
serverResponse.close();
我通过使用 WireShark 检查 http 通信发现/验证了问题。有什么办法解决这个问题吗?
更新:附加信息
看来我对通信的了解还不够深入。代码从代理后面运行,因此观察到的通信是针对代理的,通过 -Dhttps.proxyHost 设置,而不是目标网站 (google.com)。总之,在 https 连接期间,方法是 CONNECT,而不是 GET。这是 https 通信尝试的 wireshark 捕获。就像我上面提到的,用户代理是通过 -Dhttp.agent 设置的,因为 URLConnection.setRequestProperty() 没有效果(user-agent = Java/1.7.0) .在这种情况下,请注意附加的 Java/1.7.0。问题仍然存在,为什么会发生这种情况,我该如何解决?
CONNECT www.google.com:443 HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:19.0) Gecko/20100101 Firefox/19.0 Java/1.7.0
Host: www.google.com
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Proxy-Connection: keep-alive
HTTP/1.1 403 Forbidden
X-Bst-Request-Id: MWPwwh:m7d:39175
X-Bst-Info: ch=req,t=1366218861,h=14g,p=4037_7213:1_156,f=PEFilter,r=PEBlockCatchAllRule,c=1905,v=7.8.14771.200 1363881886
Content-Type: text/html; charset=utf-8
Pragma: No-cache
Content-Language: en
Cache-Control: No-cache
Content-Length: 2491
顺便说一句,请求被禁止,因为代理过滤用户代理,Java/1.7.0 导致拒绝。我已将 Java/1.7.0 附加到 http 连接的用户代理,但代理也拒绝连接。我希望我不会发疯 :)。
最佳答案
I've found/verified the problem by inspecting http communictions using WireShark. Is there any way around this
这是不可能的。通过 SSL 套接字进行的通信完全被加密协议(protocol)所掩盖,无法随意观察。使用数据包捕获软件,您将能够查看 SSL 连接的启动和加密数据包的交换,但这些数据包的内容只能在连接的另一端(服务器)提取。如果不是这种情况,那么整个 HTTPS 协议(protocol)将损坏,因为它的全部目的是保护 HTTP 通信免受中间人类型的攻击(在这种情况下MITM 是数据包嗅探器)。
.n....E... .........../..5..3..9..2..8.. ..............@........................Ql.{...b....OsR..!.4.$.T...-.-.T....Q...M..Ql.{...LM..L...um.M...........s. ...n...p^0}..I..G4.HK.n......8Y...............E...A..>...0...0......... ).s.......0 ..*.H.. .....0F1.0...U....US1.0...U. . Google Inc1"0 ..U....Google Internet Authority0.. 130327132822Z. 131231155850Z0h1.0...U....US1.0...U... California1.0...U... Mountain View1.0...U. . Google Inc1.0...U....www.google.com0..0
理论上,了解您的 User-Agent header 是否实际被排除的唯一方法是您是否可以访问 Google 服务器,但实际上 HTTPS 规范或 Java 中没有任何内容它的实现排除了通常通过 HTTP 发送的 header 。
GET / HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:19.0) Gecko/20100101 Firefox/19.0
Host: www.google.com
Accept: text/html, image/gif, image/jpeg, *; q=.2, /; q=.2
Connection: keep-alive
两个示例捕获都是使用完全相同的代码生成的:
URL url = new URL(target);
URLConnection conn = url.openConnection();
conn.setRequestProperty("User-Agent",
"Mozilla/5.0 (Windows NT 5.1; rv:19.0) Gecko/20100101 Firefox/19.0");
conn.connect();
BufferedReader serverResponse = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
System.out.println(serverResponse.readLine());
serverResponse.close();
除了 HTTPS 的目标是“https://www.google.com”,而 HTTP 的目标是“http://www.google.com”。
根据您更新的问题,使用 -Dhttp.agent 属性确实将“Java/version”附加到用户代理 header ,如 following documentation 所述:
http.agent (default: “Java/<version>”)
Defines the string sent in the User-Agent request header in http requests. Note that the string “Java/<version>” will be appended to the one provided in the property (e.g. if -Dhttp.agent=”foobar” is used, the User-Agent header will contain “foobar Java/1.5.0” if the version of the VM is 1.5.0). This property is checked only once at startup.
“违规”代码位于 sun.net.www.protocol.http.HttpURLConnection 的静态 block 初始值设定项中:
static {
// ...
String agent = java.security.AccessController
.doPrivileged(new sun.security.action.GetPropertyAction(
"http.agent"));
if (agent == null) {
agent = "Java/" + version;
} else {
agent = agent + " Java/" + version;
}
userAgent = agent;
// ...
}
解决此“问题”的一种下流方法是这段代码,我 1000% 建议您不要使用:
protected void forceAgentHeader(final String header) throws Exception {
final Class<?> clazz = Class
.forName("sun.net.www.protocol.http.HttpURLConnection");
final Field field = clazz.getField("userAgent");
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, header);
}
将此覆盖与 https.proxyHost、https.proxyPort 和 http.agent 设置一起使用可获得所需的结果:
CONNECT www.google.com:443 HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:19.0) Gecko/20100101 Firefox/19.0
Host: www.google.com
Accept: text/html, image/gif, image/jpeg, *; q=.2, /; q=.2
Proxy-Connection: keep-alive
但是,是的,不要那样做。使用 Apache HttpComponents 更安全:
final DefaultHttpClient client = new DefaultHttpClient();
HttpHost proxy = new HttpHost("127.0.0.1", 8888, "http");
HttpHost target = new HttpHost("www.google.com", 443, "https");
client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
HttpProtocolParams
.setUserAgent(client.getParams(),
"Mozilla/5.0 (Windows NT 5.1; rv:19.0) Gecko/20100101 Firefox/19.0");
final HttpGet get = new HttpGet("/");
HttpResponse response = client.execute(target, get);
关于java - 在 https 连接 header 中设置用户代理属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15845075/
我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以
我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2
我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog
我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类
对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www