Android实践:Https不再疑惑

近期由于公司的工作需要,需要将原有的http接口切换到https,故做了如下学习和整理。本文先简要说明https协议原理,然后https协议在浏览器和App的实践两方面进行讲述;
一、https协议原理
1.要理解https是什么,我们必须应该理解如下几个关键词,和它们之间的关系:
  http:超文本传输协议,广泛用于从WWW服务器传输超文本到本地浏览器的传输协议;
  SSL/TLS:最广泛的密码通信方案,综合运用了对称密码、消息认证码、公钥密码、数字签名、伪随机数生成密码等密码技术;
  https:在SSL/TLS之上承载HTTP,将两种协议进行叠加;
 
2.在继续讲解https之前,我们得先了解下几个密码学套件,对于比较好理解的对称密码和非对称密码就不进行详细的讲解了:
 
  单项散列函数:根据任意长度的消息计算出固定长度的散列值,来确定文件的完整性;
  
  消息认证码:是一种密钥相关联的单向散列函数。要计算MAC必须持有共享秘钥,消息变化MAC值就会不一致,故验证身份和完整性;
  
  数字签名:反用密钥对,使用自己私钥加密生成签名,验证方用你的公钥能解密即可验证加密方是你,故能验证身份和完整性;
  
  公钥证书:认证机构通过电话、邮件或本人确认后,使用机构的私钥对你的公钥进行签名,保证了你的公钥的正确性;
  
3.完成基本密码套件的学习,接下来我们继续介绍https。由上可知https的核心在于SSL/TLS,让主要解决了如下接个问题:
  机密性:信息传输过程中的被第三方窃听—采用对称密码加密,伪随机数生成器密钥,公钥密码或Diffe-Hellman进行公钥交换;
  完整性:信息传输过程中被中间人篡改—采用单向散列函的消息认证码进行完整性验证;
  认证性:信息传输的对方身份是否合法—对公钥加上数字签名所生成的证书,对通信对象进行认证;
4.在https的进行通信的过程中,它是如何有序的运用上面的密码学套件的呢?如下:
该部分是基于TLS1.0进行说明,TLS协议是由“TLS记录协议”和“TLS握手协议”这两层协议叠加而成:
 
  1.握手协议:除加密之外的各种工作,分为4个子协议:握手协议、密码规格变更协议、警告协议和应用数据协议;
    握手子协议:负责在客户端和服务器之间协商决定密码算法和共享秘钥;
    密码规格变更协议:负责向通信对象传达变更密码方式的信号;
    警告协议:负责在发生错误的时候将错误传达给对方;
    应用数据协议:将TLS上面承载的应用数据传达给通信对象的协议;
 
  2.记录协议:位于TLS握手协议的下层,负责使用对称密码对消息进行压缩、加密以及数据的认证;
    消息被分割成多个较短的片段,然后对每个片段进行压缩;
    压缩片段会被加上消息认证码,保证完整性,并进行数据的认证,可以识别出篡改。为了防止重放攻击,在计算消息认证码时加上了片段的编号;
    经过压缩的片段在加上消息认证码会一起通过对称密码进行加密;
    经过加密的数据再加上由数据类型、版本号、压缩后的长度组成的报头就是最终的报文数据;
 
经过以上的大概讲解,相信大家对https有了更深入的认识,并且也能更好的理解为什么在实践https的时候要生成各种密钥和信任库了。

二、https协议实践

理解上面的相关原理后,我们就开始实现HttpsServlet来模拟简单登录接口,然后通过浏览器和app的访问该https接口;
1.服务端http实现
我们首先实现服务端http协议的get和post通信,项目的结构和主要实现代码如下:

HttpsServlet.java:
public class HttpsServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doPost");
        doLoginRequest(req, resp);
    }


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doGet");
        doLoginRequest(req, resp);
    }


    //实现简单的登录逻辑
    private void doLoginRequest(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        PrintStream printStream = new PrintStream(resp.getOutputStream());
        HttpsResponse httpsResponse = new HttpsResponse();
        String userName = req.getParameter("userName");
        String passWord = req.getParameter("passWord");
        if ("123".equals(userName) && "123".equals(passWord)) {
            httpsResponse.setCode("000");
            httpsResponse.setMessage("login success!");
        } else {
            httpsResponse.setCode("004");
            httpsResponse.setMessage("login faild!");
        }
        printStream.println(JSON.toJSONString(httpsResponse));
    }
}
web.xml:
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
    <display-name>Archetype Created Web Application</display-name>
    <servlet>
        <servlet-name>HttpsServlet</servlet-name>
        <servlet-class>main.com.chengxiang.servlet.HttpsServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>HttpsServlet</servlet-name>
        <url-pattern>/HttpsServlet</url-pattern>
    </servlet-mapping>
</web-app>

实现客户端登录的get和post请求,项目目录结构如下:

NextActivity.java:

public class NextActivity extends AppCompatActivity {
    private EditText userNameEditText;
    private EditText passWorldEditText;
    private Button loginButton;
    private TextView responseTextView;


    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 1:
                    Bundle bundle = msg.getData();
                    HttpsResponse httpsResponse = (HttpsResponse) bundle.getSerializable("result");
                    responseTextView.setText(httpsResponse.toString());
                    break;
            }
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_next)
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值