java接口签名算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Map;

public class SignUtil {


public static final String SIGN_METHOD_MD5 = "md5";
public static final String SIGN_METHOD_HMAC = "hmac";
private static final String CHARSET_UTF8 = "utf-8";


/**
* 对TOP请求进行签名。
*/
public static String signTopRequest(Map<String, String> params, String secret, String signMethod) throws IOException {
// 第一步:检查参数是否已经排序
String[] keys = params.keySet().toArray(new String[0]);
Arrays.sort(keys);

// 第二步:把所有参数名和参数值串在一起
StringBuilder query = new StringBuilder();
if (SIGN_METHOD_MD5.equals(signMethod)) {
query.append(secret);
}
for (String key : keys) {
String value = params.get(key);
if (isNotEmpty(key) && isNotEmpty(value)) {
query.append(key).append(value);
}
}

// 第三步:使用MD5/HMAC加密
byte[] bytes;
if (SIGN_METHOD_HMAC.equals(signMethod)) {
bytes = encryptHMAC(query.toString(), secret);
} else {
query.append(secret);
bytes = encryptMD5(query.toString());
}

// 第四步:把二进制转化为大写的十六进制
return byte2hex(bytes);
}

/**
* 对字节流进行HMAC_MD5摘要。
*/
private static byte[] encryptHMAC(String data, String secret) throws IOException {
byte[] bytes = null;
try {
SecretKey secretKey = new SecretKeySpec(secret.getBytes(CHARSET_UTF8), "HmacMD5");
Mac mac = Mac.getInstance(secretKey.getAlgorithm());
mac.init(secretKey);
bytes = mac.doFinal(data.getBytes(CHARSET_UTF8));
} catch (GeneralSecurityException gse) {
throw new IOException(gse.toString());
}
return bytes;
}

/**
* 对字符串采用UTF-8编码后,用MD5进行摘要。
*/
private static byte[] encryptMD5(String data) throws IOException {
return encryptMD5(data.getBytes(CHARSET_UTF8));
}

/**
* 对字节流进行MD5摘要。
*/
private static byte[] encryptMD5(byte[] data) throws IOException {
byte[] bytes = null;
try {
MessageDigest md = MessageDigest.getInstance("MD5");
bytes = md.digest(data);
} catch (GeneralSecurityException gse) {
throw new IOException(gse.toString());
}
return bytes;
}

/**
* 把字节流转换为十六进制表示方式。
*/
private static String byte2hex(byte[] bytes) {
StringBuilder sign = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(bytes[i] & 0xFF);
if (hex.length() == 1) {
sign.append("0");
}
sign.append(hex.toUpperCase());
}
return sign.toString();
}

private static boolean isNotEmpty(String value) {
int strLen;
if (value == null || (strLen = value.length()) == 0) {
return false;
}
for (int i = 0; i < strLen; i++) {
if ((Character.isWhitespace(value.charAt(i)) == false)) {
return true;
}
}
return false;
}
public static void main(String[] args) throws Exception {
Map<String, String> params = new HashMap<String, String>();
// 公共参数
params.put("method", "taobao.item.seller.get");
params.put("app_key", appKey);
params.put("session", sessionKey);
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
params.put("timestamp", df.format(new Date()));
params.put("format", "json");
params.put("v", "2.0");
params.put("sign_method", "hmac");
// 业务参数
params.put("fields", "num_iid,title,nick,price,num");
params.put("num_iid", "123456789");
// 签名参数
params.put("sign", signTopRequest(params, appSecret, SIGN_METHOD_HMAC));
}
}
阅读全文 »

为什么有了https  还需要做签名验证?

当用户在浏览器当中加载受HTTPS保护的网站时,浏览器实际上只会验证两件事:网站是否提供了证书;证书是不是浏览器(操作系统)信任的根证书CA机构颁发的。实际上我们是在相信每个根CA机构都已尽全力来验证你要连接的服务器的身份。但是实际上有时候根CA机构会被骗。我们还相信每个根CA机构都能够保护自己的系统。但是实际上有时候根CA会被盗用。
安装个代理工具(fiddler)的证书,就可以用代理工具抓到https请求的内容,还可以篡改数据。
签名可以防止篡改数据,因为签名的密钥没有在网络中进行传输(服务器端线下颁发给客户端或者客户端自己输入的登陆密码作为密钥,甚至登陆使用的短信验证码也可以作为密钥)

https算法本质

https 采用 rsa+aes 结合
ras 为了 生成aes的密钥不被发现
aes 可以防止数据被偷窥

阅读全文 »

SSL

SSL - Secure Sockets Layer,现在应该叫”TLS”,但由于习惯问题,我们还是叫”SSL”比较多.http协议默认情况下是不加密内容的,这样就很可能在内容传播的时候被别人监听到,对于安全性要求较高的场合,必须要加密,https就是带加密的http协议,而https的加密是基于SSL的,它执行的是一个比较下层的加密,也就是说,在加密前,你的服务器程序在干嘛,加密后也一样在干嘛,不用动,这个加密对用户和开发者来说都是透明的.
OpenSSL - 简单地说,OpenSSL是SSL的一个实现,SSL只是一种规范.理论上来说,SSL这种规范是安全的,目前的技术水平很难破解,但SSL的实现就可能有些漏洞,如著名的”心脏出血”.OpenSSL还提供了一大堆强大的工具软件,强大到90%我们都用不到.

证书标准

X.509 - 这是一种证书标准,主要定义了证书中应该包含哪些内容.其详情可以参考RFC5280,SSL使用的就是这种证书标准.

编码格式

同样的X.509证书,可能有不同的编码格式,目前有以下两种编码格式.
PEM - Privacy Enhanced Mail,打开看文本格式,以”—–BEGIN…”开头, “—–END…”结尾,内容是BASE64编码.
查看PEM格式证书的信息:openssl x509 -in certificate.pem -text -noout
Apache和*NIX服务器偏向于使用这种编码格式.
DER - Distinguished Encoding Rules,打开看是二进制格式,不可读.
查看DER格式证书的信息:openssl x509 -in certificate.der -inform der -text -noout
Java和Windows服务器偏向于使用这种编码格式.

相关的文件扩展名

这是比较误导人的地方,虽然我们已经知道有PEM和DER这两种编码格式,但文件扩展名并不一定就叫”PEM”或者”DER”,常见的扩展名除了PEM和DER还有以下这些,它们除了编码格式可能不同之外,内容也有差别,但大多数都能相互转换编码格式.
CRT - CRT应该是certificate的三个字母,其实还是证书的意思,常见于*NIX系统,有可能是PEM编码,也有可能是DER编码,大多数应该是PEM编码,相信你已经知道怎么辨别.
CER - 还是certificate,还是证书,常见于Windows系统,同样的,可能是PEM编码,也可能是DER编码,大多数应该是DER编码.
KEY - 通常用来存放一个公钥或者私钥,并非X.509证书,编码同样的,可能是PEM,也可能是DER.
查看KEY的办法:openssl rsa -in mykey.key -text -noout
如果是DER格式的话,同理应该这样了:openssl rsa -in mykey.key -text -noout -inform der
CSR - Certificate Signing Request,即证书签名请求,这个并不是证书,而是向权威证书颁发机构获得签名证书的申请,其核心内容是一个公钥(当然还附带了一些别的信息),在生成这个申请的时候,同时也会生成一个私钥,私钥要自己保管好.做过iOS APP的朋友都应该知道是怎么向苹果申请开发者证书的吧.
查看的办法:openssl req -noout -text -in my.csr (如果是DER格式的话照旧加上-inform der,这里不写了)

证书编码的转换

PEM转为DER openssl x509 -in cert.crt -outform der -out cert.der
DER转为PEM openssl x509 -in cert.crt -inform der -outform pem -out cert.pem
(提示:上面例子是转换证书文件,如果要转换KEY文件也类似,只不过把x509换成rsa,要转CSR的话,把x509换成req)

阅读全文 »

1、rpm  本地安装软件

获取安装的rpm软件包

1、联网情况下使用 wget 命令 获取 rpm软件包
2、使用U盘上传软件包

安装rpm软件包

格式:rpm  [选项]  RPM包文件
常用选项:
-i:安装一个新的rpm软件包
-h:以“#”号显示安装的进度
-v:显示安装过程中的详细信息
–force:强制安装所指定的rpm软件包
–nodeps:安装软件时,忽略依赖关系
例子: rpm -ivh apache-1.3.6.i386.rpm

升级或更新rpm软件包

格式:rpm  [选项]  RPM包文件
常用选项:
-U:升级某个rpm软件,若原本未装,则进行安装
-F:更新某个rpm软件,若原本未装,则放弃安装
–nodeps:升级软件时,忽略依赖关系
例子: rpm -U apache-1.3.6.i386.rpm

卸载rpm软件包

格式:rpm  -e  软件名
–nodeps:卸载软件时,忽略依赖关系
例子: rpm -e apache

阅读全文 »

事务隔离级别

事务隔离级别的语义:当前事务执行过程中,通过select,update,delete 操作,对其他事务的影响,反过来也是如此,通俗的说就是 当前事务是否可以看到其他事务的操作结果。
数据库事务的隔离级别有4个,由低到高依次为Read uncommitted、Read committed、Repeatable read、Serializable,这四个级别可以逐个解决脏读、不可重复读、幻读这几类问题。
mysql 默认的隔离级别是:Repeatable read

如何查询当前数据库的隔离级别

select @@tx_isolation;
SELECT @@session.tx_isolation;
SELECT @@global.tx_isolation;
设置
set tx_isolation=’read-committed’;

阅读全文 »

表的3NF (范式)

表的范式,是首先符合1NF, 才能满足2NF , 进一步满足3NF。
1NF: 即表的列的具有原子性,不可再分解,即列的信息,不能分解, 只有数据库是关系型数据库(mysql/oracle/db2/informix/sysbase/sql server),就自动的满足1NF。
2NF: 表中的记录是唯一的, 就满足2NF, 通常我们设计一个主键来实现,主键一般不含业务逻辑。
3NF: 即表中不要有冗余数据, 就是说,表的信息,如果能够被推导出来,就不应该单独的设计一个字段来存放。
所谓的范式,是用来学习参考的,设计的时候根据情况,未必一定要遵守。因为在数据库数据量特别大,并且访问并发也大的情况下,可能要采用反范式设计来提高数据库响应速度。

阅读全文 »

优化数据访问

是否请求了不需要的数据

有些查询会请求超过实际需要的数据,然后多余的数据会被应用程序丢弃。这会给mysql服务器带来额外的负担,并增加网络开销,另外也会消耗应用服务器的CPU和内存资源。
比如:
1、查询不需要的记录
实际页面显示10条记录,但是查询去除100条记录,解决办法查询后面使用limit 10.
2、多表关联时返回全部列
如果只需要出现的演员,千万不要按照下面的写法:

1
select * from actor inner join film_actor using(actor_id) inner join film using(film_id) where film.title = 'Academy';

这将返回这三个表的全部数据列。正确的写法如下:

1
select actor.* from actor inner join film_actor using(actor_id) inner join film using(film_id) where film.title = 'Academy';

3、总是取出全部列
使用select * from table 的时候需要想一想所有的列是否都是需要的,尽量抛弃这种写法
4、重复查询相同的数据
不断地重复执行相同的查询,然后每次返回完全相同的数据。比较好的方案是查询的时候将这个数据缓存起来,需要的时候从缓存中取出。

阅读全文 »

索引类型

索引由很多类型,可以为不同场景提供更好的性能,在mysql中索引是存储引擎层而不是服务器层实现的。不同存储引擎的索引工作方式也不一样,也不是所有存储引擎支持所有索引类型,其底层实现也可能不同。

B-Tree索引

使用B-Tree数据结构来存储数据,大多数mysql引擎都支持这种索引,Archive引擎是个例外。
存储引擎以不同的方式使用B-Tree索引,性能也各不同,各有优劣。
例如,MyISAM使用前缀压缩使得索引更小,但InnoDB按照原数据格式进行存储。再如MyISAM索引通过数据的屋里位置引用被索引的行,而InnoDB根据主键引用被索引的行。
B-Tree索引对如下类型的查询有效(假设:key(name,dob)):
1、全值匹配
比如查找姓名为Allen的人,出生于1996年的人
2、匹配最左前缀
比如查找姓名为Allen的人,即只是用索引的第一列
3、匹配列前缀
比如查找所有以J开头的姓的人。这里也只使用了索引的第一列。
4、匹配范围值
比如查找姓在Allen和Barrymore之间的人。这里也只使用了索引的第一列。
5、匹配某一列并范围匹配另一列
比如查找姓名Allen的人,出生1996到2005的人
B-Tree支持“值访问索引的查询”,即查询只需要访问索引,而不需要访问数据行,也叫做“覆盖索引”。
因为索引树中的节点是有序的,所以除了按值查找之外,索引还可以用order by操作。

阅读全文 »

从前有三个屌丝,聚在一起做网络,提供免费的网络服务,砸锅卖铁,通宵达旦,除了卖肾啥都做了。3年后终于做到了五百万用户,对于年轻人来说,能把五百万人玩弄于鼓掌之间,已经是很牛逼轰轰的事了,不过用户越多,成本越高,每年服务器、带宽租金、房租水电、广告运营等成本,已经达到了十七八万,屌丝们不得不面对一个终极问题:如何盈利?

屌丝们定了三盘沙县水饺,围着一箱子的冰啤酒开始计算:按照最近一月的登陆情况来看,四百万个账号已经不活跃了,真正有商业价值的只有一百万人,如 果开通xx功能,收点高级会员费,让其中1%的人升级为高级会员,每年付30块钱年费,那么每年收入就是100万x1%x30元=30万元!不错嘛, 扣除十七八万的运营成本,还剩毛利润12万,每个屌丝年底能分到4万大洋,如果按照打工者的算法,这三个人每人月薪3333元,木有奖金,木有津贴、木有任何福利,上班还得带自家的电脑。

尽管如此,屌丝们还是激动得感谢苍天!我们终于要盈利啦!那一夜,人们看到三个发疯的屌丝在屋顶翩翩起舞。

韩寒说,中国人民是最有忍耐力的族群,一点好处就感激涕零。他一定不知道,IT创业界里的屌丝,才是这群傻逼中的战斗机。他们可以平静地忍受每年都持续亏钱,而且还能信心十足的对所有人说公司的状态非常好,如果有一天居然收支平衡了,他们会激动的彻夜难眠,比北朝鲜倒掉还开心。

阅读全文 »

散列

散列表的实现常常叫做散列(hashing)。散列是一种用于以常数平均时间执行插入、删除和查找的技术。但是,那些需要元素间任何排序信息的树操作将不会得到有效的支持。

散列表

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

哈希函数

给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。
所有散列函数都有如下一个基本特性:如果两个散列值是不相同的(根据同一函数),那么这两个散列值的原始输入也是不相同的。这个特性是散列函数具有确定性的结果。但另一方面,散列函数的输入和输出不是一一对应的,如果两个散列值相同,两个输入值很可能是相同的,但不绝对肯定二者一定相等(可能出现哈希碰撞)。输入一些数据计算出散列值,然后部分改变输入值,一个具有强混淆特性的散列函数会产生一个完全不同的散列值。

阅读全文 »