zoukankan      html  css  js  c++  java
  • http升级https改造方案

     

    一、解决方案

    1、httpClient请求https版蓝鲸接口

    1)、原理

    https与http最大的区别在于SSL加密传输协议的使用。在自己写的JAVA HttpClient程序,想手动验证证书,可以在客户端绕过验证服务器证书的步骤,即则需要实现空的X509TrustManager接口。

    类中的验证方法返回void或者null,是为了绕过验证。正常的方法体如果检验出证书无法被信任,需要手动抛出异常:

    javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building

    failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

    并在chtch中处理异常,如果想要绕过验证,也就是说不要抛出异常就可以了,可以理解为信任了任何证书。

    2)、代码展示:HttpsClientUtil.java

    import org.apache.http.client.HttpClient;
    import org.apache.http.client.config.AuthSchemes;
    import org.apache.http.client.config.CookieSpecs;
    import org.apache.http.client.config.RequestConfig;
    import org.apache.http.config.Registry;
    import org.apache.http.config.RegistryBuilder;
    import org.apache.http.conn.socket.ConnectionSocketFactory;
    import org.apache.http.conn.socket.PlainConnectionSocketFactory;
    import org.apache.http.conn.ssl.NoopHostnameVerifier;
    import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;
    import java.security.KeyManagementException;
    import java.security.NoSuchAlgorithmException;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    import java.util.*;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.message.BasicHeader;
    import org.apache.http.util.EntityUtils;
    /**
     * @author xiehaiqing
     * @date 2019/03/26
     */
    public class HttpsClientUtil {
        /**
         * 在调用SSL之前需要重写验证方法,取消检测SSL
         * 创建ConnectionManager,添加Connection配置信息
         * @return HttpClient 支持https
         */
        public static HttpClient sslClient(){
            try {
                // 在调用SSL之前需要重写验证方法,取消检测SSL
                X509TrustManager trustManager = new X509TrustManager() {
                    @Override
                    public void checkClientTrusted(X509Certificate[] x509Certificates, String s)
                            throws CertificateException { }
                    @Override
                    public void checkServerTrusted(X509Certificate[] x509Certificates, String s)
                            throws CertificateException { }
                    @Override
                    public X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }
                };
                SSLContext ctx = SSLContext.getInstance(SSLConnectionSocketFactory.TLS);
                ctx.init(null, new TrustManager[]{trustManager}, null);
                SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(ctx, NoopHostnameVerifier.INSTANCE);
                //创建registry
                RequestConfig requestConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD_STRICT)
                        .setExpectContinueEnabled(Boolean.TRUE).setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST))
                        .setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC)).build();
                Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.INSTANCE)
                        .register("https", socketFactory).build();
                // 创建ConnectionManager,添加Connection配置信息
                PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
                CloseableHttpClient closeableHttpClient = HttpClients.custom().setConnectionManager(connectionManager).setDefaultRequestConfig(requestConfig).build();
                return closeableHttpClient;
            }catch (KeyManagementException ex){
                throw new RuntimeException(ex);
            }catch (NoSuchAlgorithmException e){
                throw new RuntimeException(e);
            }
        }
    
        /**
         * post请求
         * @param url
         * @param jsonStr
         * @return
         */
        public static String doPost(String url,String jsonStr){
            HttpClient httpClient = null;
            HttpPost httpPost = null;
            String result = null;
            try{
                httpClient = sslClient();
                httpPost = new HttpPost(url);
                httpPost.addHeader("Content-type","applicattion/json");
                StringEntity se = new StringEntity(jsonStr);
                se.setContentType("text/json");
                se.setContentEncoding(new BasicHeader("Content-type","application/json"));
                httpPost.setEntity(se);
                HttpResponse response = httpClient.execute(httpPost);
                if (response !=null){
                    HttpEntity entity = response.getEntity();
                    if (entity !=null){
                        result = EntityUtils.toString(entity,"utf-8");
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
            }
            return result;
        }
    }
    View Code

     展开源码 

    2、模拟https版本登录

    1)、原理

    icube模拟登陆,即是通过服务的登录链接,对用户输入的账号密码进行真实的验证,本功能使用了Jsoup解析的方式实现。

    具体逻辑为,先使用get请求链接的方式,生成登录所需的bklogin_csrftoken这一属性字段,然后在通过post携带用户输入的账号密码和该csrftoken字段进行登录请求,如果用户输入的账号密码正确,则在cookie中会有一个不为空的bk_token字段,即为登录成功,否则登录失败。对于https请求,需要在请求之前绕过证书验证,这里采用创建不验证证书链的信任管理器来实现。

    登录链接示例:https://xx.com/login/?c_url=

    2)代码展示

      1 import com.zork.opbd.datasource.Config;
      2 
      3 import com.zork.opbd.log.SystemLogHelper;
      4 
      5 import org.jsoup.Connection;
      6 
      7 import org.jsoup.Connection.*;
      8 
      9 import org.jsoup.Jsoup;
     10 
     11 import org.jsoup.nodes.Document;
     12 
     13 import org.jsoup.nodes.Element;
     14 
     15 import org.jsoup.select.Elements;
     16 
     17  
     18 
     19 import javax.net.ssl.*;
     20 
     21 import java.security.KeyManagementException;
     22 
     23 import java.security.NoSuchAlgorithmException;
     24 
     25 import java.security.SecureRandom;
     26 
     27 import java.security.cert.CertificateException;
     28 
     29 import java.security.cert.X509Certificate;
     30 
     31 import java.util.*;
     32 
     33 
     34 
     35 public class BKLoginUtils {
     36 
     37     public static String LOGIN_URL= Config.getInstance().BK_LOGIN_URL; //https://xx.com/login/?c_url=
     38 
     39     public final static String USER_AGENT="User-Agent";
     40 
     41     public final static String USER_AGENT_VALUE="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36";
     42 
     43     public final static String LOGINFORM = "#login-form";
     44 
     45     public final static String NAME = "name";
     46 
     47     public final static String VALUE = "value";
     48 
     49     public final static String USERNAME = "username";
     50 
     51     public final static String PASSWORD = "password";
     52 
     53     public final static String ID = "id";
     54 
     55     public final static String USER = "user";
     56 
     57     public final static String REFERER = "Referer";
     58 
     59     public final static String BKTOKEN = "bk_token";
     60 
     61  
     62 
     63  
     64 
     65     public static void main(String[] args) throws Exception {
     66 
     67         boolean admin = siMulateLogin("admin", "zork.8888");
     68 
     69         System.out.println(admin);
     70 
     71     }
     72 
     73  
     74 
     75     /**
     76 
     77      * 模拟登陆功能
     78 
     79      * @param userName
     80 
     81      * @param pwd
     82 
     83      * @return result
     84 
     85      */
     86 
     87     public static boolean siMulateLogin(String userName,String pwd){
     88 
     89         boolean result = false;
     90 
     91         try{
     92 
     93             checkQuietly();
     94 
     95             Connection con = Jsoup.connect(LOGIN_URL).timeout(30000).userAgent(USER_AGENT_VALUE);
     96 
     97             Response rs = con.execute();
     98 
     99             Document doc = Jsoup.parse(rs.body());
    100 
    101             List<Element> elements = doc.select(LOGINFORM);
    102 
    103             Elements allElements = elements.get(0).getAllElements();
    104 
    105             Iterator<Element> iterator = allElements.iterator();
    106 
    107             Map<String,String> datas = new HashMap<>();
    108 
    109             while (iterator.hasNext()){
    110 
    111                 //赋值
    112 
    113                 Element element = iterator.next();
    114 
    115                 if (element.attr(NAME).equals(USERNAME) && element.attr(ID).equals(USER)){
    116 
    117                     element.attr(VALUE,userName);
    118 
    119                 }
    120 
    121                 if (element.attr(NAME).equals(PASSWORD) && element.attr(ID).equals(PASSWORD)){
    122 
    123                     element.attr(VALUE,pwd);
    124 
    125                 }
    126 
    127                 //排除空值表单属性
    128 
    129                 if (element.attr(NAME).length()>0){
    130 
    131                     datas.put(element.attr(NAME),element.attr(VALUE));
    132 
    133                 }
    134 
    135             }
    136 
    137             Connection conn = Jsoup.connect(LOGIN_URL);
    138 
    139             conn.header(USER_AGENT,USER_AGENT_VALUE);
    140 
    141             conn.header(REFERER,LOGIN_URL);//注意,这一行必须要加,否则会验证失败
    142 
    143             Response login = conn.ignoreContentType(true).followRedirects(true).method(Method.POST).data(datas).cookies(rs.cookies()).execute();
    144 
    145             Map<String,String> cookies = login.cookies();
    146 
    147             Iterator<String> keyIter = cookies.keySet().iterator();
    148 
    149             while (keyIter.hasNext()){
    150 
    151                 String key = keyIter.next();
    152 
    153                 if (BKTOKEN.equals(key)){
    154 
    155                     if (!StringUtil.isNull(cookies.get(key))){
    156 
    157                         SystemLogHelper.info("获取bk_token成功,bk_token:"+cookies.get(key),true);
    158 
    159                         result = true;
    160 
    161                     }else {
    162 
    163                         SystemLogHelper.info("获取bk_token失败,登陆失败,请检查用户名或密码",true);
    164 
    165                     }
    166 
    167                 }
    168 
    169             }
    170 
    171         }catch (Exception e){
    172 
    173             e.printStackTrace();
    174 
    175         }
    176 
    177         return result;
    178 
    179     }
    180 
    181  
    182 
    183  
    184 
    185     /**
    186 
    187      * 信任管理器
    188 
    189      * 绕过证书验证
    190 
    191      */
    192 
    193     public static void checkQuietly(){
    194 
    195         try{
    196 
    197             //创建不验证证书链的信任管理器
    198 
    199             TrustManager[] trustAllCerts = {
    200 
    201                     new X509TrustManager() {
    202 
    203                         @Override
    204 
    205                         public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
    206 
    207  
    208 
    209                         }
    210 
    211                         @Override
    212 
    213                         public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
    214 
    215  
    216 
    217                         }
    218 
    219                         @Override
    220 
    221                         public X509Certificate[] getAcceptedIssuers() {
    222 
    223                             return null;
    224 
    225                         }
    226 
    227                     }
    228 
    229             };
    230 
    231             //安装所有的信任管理器
    232 
    233             SSLContext ssl = SSLContext.getInstance("SSL");
    234 
    235             ssl.init(null,trustAllCerts,new SecureRandom());
    236 
    237             HttpsURLConnection.setDefaultSSLSocketFactory(ssl.getSocketFactory());
    238 
    239             //不验证主机名
    240 
    241             HostnameVerifier hv = new HostnameVerifier() {
    242 
    243                 @Override
    244 
    245                 public boolean verify(String s, SSLSession sslSession) {
    246 
    247                     return true;
    248 
    249                 }
    250 
    251             };
    252 
    253             HttpsURLConnection.setDefaultHostnameVerifier(hv);
    254 
    255         } catch (NoSuchAlgorithmException | KeyManagementException e) {
    256 
    257             e.printStackTrace();
    258 
    259         }
    260 
    261  
    262 
    263     }
    264 
    265 }
    View Code

     

     

     

     

  • 相关阅读:
    ASPJSPNET 清空IE缓存
    asp.net __doPostBack详细解释,用法示例
    httpModules与httpHandlers
    mssql中的标量值函数和表函数的用法
    SQL利用Case When Then多条件判断
    .net发送邮件
    Cookie总结
    asp.net中web.config配置节点大全详解
    Java中打印输出
    Java中new关键字创建对象
  • 原文地址:https://www.cnblogs.com/guoguochong/p/10654358.html
Copyright © 2011-2022 走看看