Java中的每代理身份验证

时间:2015-04-01 17:11:19

标签: java http authentication proxy socks

我正在尝试在我的Java应用程序中支持经过身份验证的代理。我的理解是java.net.Proxy类不支持身份验证,您需要自己处理身份验证。

我已经创建了java.net.Proxy类的子类,它接受了两个额外的参数,用户名和密码。

实现HTTP代理身份验证非常简单,方法getHttpProxyAuthenticationHeader只返回base64编码的身份验证信息,传递给HttpUrlConnection或类似的。

我遇到了Sock代理问题。我找不到有关向Socks服务器发送身份验证的任何文档。我不确定是否需要使用诸如authenticateSocksProxy(OutputStream流)之类的方法在我的类中实现SOCKS身份验证协议,然后调用

authedProxy.authenticateSocksProxy(outputstream);

之前使用套接字

outputstream.writeBytes(myData.getBytes());

另一种选择是返回认证数据的byte [],然后手动写入数据,而不是写入认证数据的类。

我认为java.net.Authenticator或System.setProperty方法没有任何用处,因为我的实现需要在每个连接的基础上工作并且是线程安全的。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:2)

取自JSocks项目来源: https://code.google.com/p/jsocks-mirror/source/browse/trunk/src/java/net/sourceforge/jsocks/socks/UserPasswordAuthentication.java

我认为它足够清晰,可以理解完整的过程:

 /**
  SOCKS5 User Password authentication scheme.
*/
public class UserPasswordAuthentication implements Authentication{

   /**SOCKS ID for User/Password authentication method*/
   public final static int METHOD_ID = 2;

   String userName, password;
   byte[] request;

   /**
     Create an instance of UserPasswordAuthentication.
     @param userName User Name to send to SOCKS server.
     @param password Password to send to SOCKS server.
   */
   public UserPasswordAuthentication(String userName,String password){
     this.userName = userName;
     this.password = password;
     formRequest();
   }
   /** Get the user name.
   @return User name.
   */
   public String getUser(){
     return userName;
   }
   /** Get password
   @return Password
   */
   public String getPassword(){
     return password;
   }
   /**
    Does User/Password authentication as defined in rfc1929.
    @return An array containnig in, out streams, or null if authentication
    fails.
   */
   public Object[] doSocksAuthentication(int methodId,
                                         java.net.Socket proxySocket)
                   throws java.io.IOException{

      if(methodId != METHOD_ID) return null;

      java.io.InputStream in = proxySocket.getInputStream();
      java.io.OutputStream out = proxySocket.getOutputStream();

      out.write(request);
      int version = in.read();
      if(version < 0) return null; //Server closed connection
      int status = in.read();
      if(status != 0) return null; //Server closed connection, or auth failed.

      return new Object[] {in,out};
   }

//Private methods
//////////////////

/** Convert UserName password in to binary form, ready to be send to server*/
   private void formRequest(){
      byte[] user_bytes = userName.getBytes();
      byte[] password_bytes = password.getBytes();

      request = new byte[3+user_bytes.length+password_bytes.length];
      request[0] = (byte) 1; 
      request[1] = (byte) user_bytes.length;
      System.arraycopy(user_bytes,0,request,2,user_bytes.length);
      request[2+user_bytes.length] = (byte) password_bytes.length;
      System.arraycopy(password_bytes,0,
                       request,3+user_bytes.length,password_bytes.length);
   }
}