Http协议与请求
Post请求
Post请求与Get请求的区别
Get请求的参数是直接放在url后面的,而Post请求是放在请求体中的
Get请求参数的长度会根据浏览器的不同实现有一定限制,而Post请求参数长度没有限制
Get请求方便测试,直接输入地址即可,而Post请求不方便测试,需要借助代码或者工具进行发送
Get请求和Post请求没有本质的区别,只是定义上的区别,比如如果你非要将get方式的参数放在请求体中,那么服务器也是可以接收处理的,同样,你也可以将post方式的参数拼在url后面
Post请求的使用场景
使用Post请求上传键值对
使用Post请求上传json串
使用Post请求上传单个文件
使用Post请求上传多个文件
使用Post方法上传键值对,代码如下:
public void asyncPost(String url,HashMap<String, String> params,TextHttpResponseHandler responseHandler){
RequestParams requestParams = new RequestParams(params);
asyncHttpClient.post(url, requestParams, responseHandler);
}
/**
* post提交key-value
* @param url2
*/
private void postKeyValue(String url) {
HashMap<String, String> params = new HashMap<String, String>();
params.put("username", "俊哥");
params.put("password", "111");
HttpHelper.get().asyncPost(url, params, new TextHttpResponseHandler() {
@Override
public void onSuccess(int arg0, Header[] arg1, String text) {
tv_result.setText(text);
}
@Override
public void onFailure(int arg0, Header[] arg1, String arg2, Throwable arg3) {
}
});
}
使用Post方式上传文件,代码如下:
public void asyncUploadFile(String url, String key, File file,TextHttpResponseHandler responseHandler) {
RequestParams requestParams = new RequestParams();
try {
requestParams.put(key, file);
asyncHttpClient.post(url,requestParams , responseHandler);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
private void uploadFile() {
try {
File file = new File(Environment.getExternalStorageDirectory()+"/dog.jpg");
HttpHelper.get().asyncUploadFile(upload, "file", file, new TextHttpResponseHandler() {
@Override
public void onSuccess(int arg0, Header[] arg1, String text) {
tv_result.setText(text);
}
@Override
public void onFailure(int arg0, Header[] arg1, String arg2, Throwable arg3) {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
Post请求相关注意事项:
传递中文参数问题,Get请求同样需要注意,需要对url进行编码,对应的类有URLEncoder和URLDecoder,否则会乱码,当然很多第三方http库已经处理该问题
常见Content-Type定义:
普通文本:text/plain
表单键值对:application/x-www-form-urlencoded
文件数据:application/octet-stream
json数据:application/json
xml数据:text/xml
Android中常见编码Base64和URL编码
URL编码:http协议中请求的url不支持中文和特殊字符(如&?),所以需要对url进行编码和解码,编码使用的是URLEncoder,解码使用的是URLDecoder;
//进行url编码
URLEncoder.encode(url)
//进行url解码
URLDecoder.decode(encodeUrl)
Base64:可以将二进制数据对象转为字符串,主要用于在http传输中将一些比较大的比如二进制数据,编码为字符串,适合放入url进行传递,而且具有非明文行。应用场景如下:
将文件进行base64编码为字符串后再上传,代码如下:
private void base64Image() {
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.PNG, 100, baos);
byte[] encode = Base64.encode(baos.toByteArray(), Base64.DEFAULT);
tv_result.setText(new String(encode));
}
将对象进行base64编码为字符串后,可以进行本地缓存,代码如下:
private void base64Object() {
Object obj = new Object();
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oo;
try {
oo = new ObjectOutputStream(bo);
oo.writeObject(obj);
} catch (IOException e) {
e.printStackTrace();
}
byte[] encode = Base64.encode(bo.toByteArray(), Base64.DEFAULT);
tv_result.setText(new String(encode));
}
Android中的数字摘要,加密和解密 数字摘要:是指通过算法将长数据变为短数据,通常用来标识数据的唯一性,是否被修改,常用的加密算法有md5和sha1,如安卓app的签名也是用这2种算法计算的; md5由于具有不可逆性,也被用来作为密码加密,并且通常情况下为了让加密过程变的不可预测,我们会进行加盐操作,代码如下: /** * 使用md5方式进行加密 * @return */
private String md5(String password) {
StringBuffer sb = new StringBuffer();
try {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
messageDigest.update(password.getBytes());
byte[] digest = messageDigest.digest();
for (int i = 0; i < digest.length; i++) {
String str = Integer.toHexString(digest[i] & 0xff);
if (str.length() == 1) {
str = str + "0";
}
sb.append(str);
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return sb.toString();
}
sha1也不可逆,比md5长度更长,所以更安全,但是加密的效率比md5要慢一些,如文件的秒传功能,以及相同的v4包冲突都是根据文件的sha1值进行比对的。 /** * 使用sha-1方式进行加密 * @return */
private String sha1(String password) {
StringBuffer sb = new StringBuffer();
try {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
messageDigest.update(password.getBytes());
byte[] digest = messageDigest.digest();
for (int i = 0; i < digest.length; i++) {
String str = Integer.toHexString(digest[i] & 0xff);
if (str.length() == 1) {
str = str + "0";
}
sb.append(str);
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return sb.toString();
}
加密和解密,一般分为对称加密和非对称加密
对称加密:
密钥可以自己指定,只有一把密钥,如果密钥暴露,文件就会被暴露,
常见对称加密算法有DES算法(Data Encryption Standard)和AES算法(Advanced Encryption Standard),
特点是加密速度很快,但是缺点是安全性较低,因为只要密钥暴漏,数据就可以被解密了。
非对称加密:有两把钥匙(密钥对),公钥和私钥,公钥的话给别人,私钥自己保存
常见非对称加密算法是RSA
2把密钥通常是通过程序生成,不能自己指定
特点是加密速度慢些,但是安全系数很高
加密和解密的规则是:公钥加密只能私钥解密,私钥加密只能公钥解密
应用场景举例:在集成支付宝支付sdk时,需要生成私钥和公钥,公钥需要设置到支付宝网站的管理后台,在程序中调用支付接口的时候,使用我们自己的私钥进行加密,这样支付宝由于有公钥可以解密,其他人即时劫持了数据,但是没有公钥,也无法解密。
代码实践,使用hmAndroidUtils中的工具类进行操作
DES加密和解密的代码如下:
String data = "我是俊哥";
String desKey = "青龙偃月刀";// 密钥,口号
boolean isDesEncrypt = false;
private void useDes() {
try {
if(isDesEncrypt){
//解密
text.setText(Des.decrypt(text.getText().toString(), desKey));
}else {
//加密
text.setText(Des.encrypt(data, desKey));
}
isDesEncrypt = !isDesEncrypt;
} catch (Exception e) {
e.printStackTrace();
}
}
RSA加密和解密的代码如下:
//1.生成密钥对,设计口号
try {
Map<String, Object> genKeyPair = RSACrypt.genKeyPair();
//2.获取公钥
publicKey = RSACrypt.getPublicKey(genKeyPair);
//3.获取私钥
privateKey = RSACrypt.getPrivateKey(genKeyPair);
} catch (Exception e) {
e.printStackTrace();
}
private boolean isRSAEncrypt = false;
protected void useRSA() {
try {
if(isRSAEncrypt){
//公钥解密
String str = text.getText().toString();
byte[] bs = RSACrypt.decryptByPublicKey(RSACrypt.decode(str), publicKey);
text.setText(new String(bs));
}else {
//私钥加密
byte[] bs = RSACrypt.encryptByPrivateKey(data.getBytes(), privateKey);
text.setText(RSACrypt.encode(bs));
}
isRSAEncrypt = !isRSAEncrypt;
} catch (Exception e) {
e.printStackTrace();
}
}