引言
VPC提供了丰富的API接口,让网络工程是可以通过API调用的方式管理网络资源。用程序和软件管理自动化管理网络资源是一件显著提升运维效率和网络生产力的事情。产品经理教你写代码系列文章的目标是不懂代码的网络工程师能一步一步的学会用API管理网络。
另外通过文章标题大家也可以看出来,产品经理教你写代码肯定是一个业余班,里面的代码很多写的都不规范,可能也有很多Bug。专业选手可以参考的有限,请适度喷,手下留情。
其实如果只是想用单个API调用,可以用下面这个线上工具: https://api.aliyun.com/
第一步:利其器
工欲善其事必先利其器,对于工程师来讲,一定要有得心应手的工具。我个人十分推荐Eclipse作为我们的开发IDE。
从如下链接即可下载:
https://www.eclipse.org/downloads/
第二步:创建一个Java工程
创建一个java工程
第三步:创建代码文件
在工程的SRC中创建代码的源文件,比如ApiDemo.java
第四步:导入一个核心的jar包
很多同学再使用API的时候都会遇到一个特别大的问题,就是API URL拼接完成要按阿里云的格式生成一个“签名”,阿里云有一个规定的签名实现算法,类似于下面这种:https://help.aliyun.com/document_detail/35735.html
这个东东肯定会难倒一片初学者。 第一个文章其实就是告诉大家,怎么把这个签名生成出来,怎么把API URL生成出来。
签名的生成涉及到加密算法,需要将一个核心的JAR导入到工程中。
下载 org.apache.commons.codec.binary.Base64
可以在百度中直接搜索“org.apache.commons.codec.binary.Base64”
或者通过如下URL下载:
http://commons.apache.org/proper/commons-codec/download_codec.cgi
或者在本文末尾的附件中下载
build path中添加外部JAR包
第五步:将下面的代码拷贝到源文件ApiDemo.java中
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.HashMap;
import java.util.Arrays;
import org.apache.commons.codec.binary.Base64;
import java.text.SimpleDateFormat;
import java.util.Map;
import java.util.SimpleTimeZone;
import java.util.UUID;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.swing.JButton;
import javax.swing.JTextField;
import java.awt.*;
import javax.swing.*;import java.awt.event.*;
public class ApiDemo extends JFrame {
private static final String ENCODING = "UTF-8";
private static final String ALGORITHM = "HmacSHA1";
private static final String HTTP_METHOD = "GET";
//不同的产品API version不一样
private static final String urlAPIVersion = "2016-04-28";
private static final String urlSecALG = "HMAC-SHA1";
private static final String urlSecVer = "1.0";
private String urlAccKeyID = "";
private String ulrSeckey = "";
private static String urlSecNonce = UUID.randomUUID().toString();
private static final String urlFromat = "xml";
private String ulrTimeStamp =formatIso8601Date(new Date());
private static final String ISO8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
private static String formatIso8601Date(Date date) {
SimpleDateFormat df = new SimpleDateFormat(ISO8601_DATE_FORMAT);
df.setTimeZone(new SimpleTimeZone(0, "GMT"));
return df.format(date);
}
public String CreatApiURL(String strAccKeyID,String strSeckey,String strcmd) throws Exception {
urlAccKeyID=strAccKeyID;
ulrSeckey =strSeckey;
ulrSeckey = ulrSeckey+"&";
String urlNonce = UUID.randomUUID().toString();
String phrase =strcmd;
Date date = new Date();
SimpleDateFormat df = new SimpleDateFormat(ISO8601_DATE_FORMAT);
df.setTimeZone(new SimpleTimeZone(0, "GMT"));
ulrTimeStamp = df.format(date);
Map<String, String> parameters = new HashMap<String, String>();
// 加入公共请求参数
parameters.put("Format", urlFromat);
parameters.put("Version", urlAPIVersion);
parameters.put("SignatureMethod", urlSecALG);
parameters.put("SignatureNonce", urlNonce);
parameters.put("SignatureVersion", urlSecVer);
parameters.put("AccessKeyId", urlAccKeyID);
parameters.put("Timestamp", ulrTimeStamp);
String delims1 = ";";
String[] tokens1 = phrase.split(delims1);
for (int i = 0; i < tokens1.length; i++)
{
String delims2 = "=";
String[] tokens2 = tokens1[i].split(delims2);
parameters.put(tokens2[0], tokens2[1]);
}
// 对参数进行排序
String[] sortedKeys = parameters.keySet().toArray(new String[]{});
Arrays.sort(sortedKeys);
final String SEPARATOR = "&";
// 生成stringToSign字符串
StringBuilder stringToSign = new StringBuilder();
stringToSign.append(HTTP_METHOD).append(SEPARATOR);
String value = "/";
try {
value = URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") ;
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
stringToSign.append(value).append(SEPARATOR);
StringBuilder canonicalizedQueryString = new StringBuilder();
for(String key : sortedKeys) {
// 这里注意对key和value进行编码
String value1 = key;
try {
value1 = URLEncoder.encode(value1, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") ;
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String value2 = parameters.get(key);
try {
value2 = URLEncoder.encode(value2, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") ;
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
canonicalizedQueryString.append("&")
.append(value1).append("=")
.append(value2);
}
// 这里注意对canonicalizedQueryString进行编码
String value3 = canonicalizedQueryString.toString().substring(1);
try {
value3 = URLEncoder.encode(value3, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") ;
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
stringToSign.append(value3);
Mac mac = null;
try {
mac = Mac.getInstance(ALGORITHM);
} catch (NoSuchAlgorithmException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
mac.init(new SecretKeySpec(ulrSeckey.getBytes(ENCODING), ALGORITHM));
} catch (InvalidKeyException | UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
byte[] signData = null;
try {
signData = mac.doFinal(stringToSign.toString().getBytes(ENCODING));
} catch (IllegalStateException | UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String signature = new String(Base64.encodeBase64(signData));
value = signature;
try {
value = URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") ;
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String urlSignature = value;
StringBuilder urlReq = new StringBuilder();
//vpc的调用入口,如果是云监控的入口,则是http://metrics.cn-beijing.aliyuncs.com/的形式
urlReq.append("https://vpc.aliyuncs.com");
urlReq.append("?Signature=");
urlReq.append(urlSignature);
for(String key : sortedKeys) {
urlReq.append("&")
.append(key)
.append("=")
.append(parameters.get(key));
}
System.out.println(urlReq.toString());
return urlReq.toString();
}
public ApiDemo() throws Exception {
setSize(400,700);
setLayout(new FlowLayout(FlowLayout.CENTER,10,30));
JPanel panel=new JPanel();
JTextField textField_AccID=new JTextField(30);
JTextField textField_Acckey=new JTextField(30);
JTextField textField_Cmd=new JTextField(30);
JTextField textField_URL=new JTextField(30);
JButton button=new JButton(" 生成OPEN API URL ");
JLabel AccID=new JLabel("请输入Access Key ID:");
JLabel AccKey=new JLabel("请输入Access Key Secret:");
JLabel Cmd=new JLabel("请输入命令:");
JLabel Cmd_tishi1=new JLabel("格式为: 参数名称1=参数描述1;参数名称2=参数描述2 ");
JLabel Cmd_tishi2=new JLabel("如:Action=DescribeEipAddresses;RegionId=cn-beijing");
JLabel URLResult=new JLabel(" Open API URL生成结果: ");
button.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
// TODO 自动生成的方法存根
urlAccKeyID=textField_AccID.getText();
ulrSeckey =textField_Acckey.getText();
String strCmd = textField_Cmd.getText();
String strApiUrl = "";
try {
strApiUrl = CreatApiURL(urlAccKeyID,ulrSeckey,strCmd);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
textField_URL.setText(strApiUrl);
}
});
getContentPane().add(panel);
getContentPane().add(AccID);
getContentPane().add(textField_AccID);
getContentPane().add(AccKey);
getContentPane().add(textField_Acckey);
getContentPane().add(Cmd);
getContentPane().add(Cmd_tishi1);
getContentPane().add(Cmd_tishi2);
getContentPane().add(textField_Cmd);
getContentPane().add(button);
getContentPane().add(URLResult);
getContentPane().add(textField_URL);
setLocationRelativeTo(null);
setVisible(true);
setDefaultCloseOperation(3);
}
public static void main(String[] args) throws Exception {
ApiDemo API_GEN = new ApiDemo();
}
}
第六步:运行程序
这个是一个以图形化界面来展示拼接URL的小程序
要使用Open API 必须要用AK。具体的AK如何获取,参考下图的入口进到AK管理界面获取。
查询命令必须要按 :参数名称1=参数描述1;参数名称2=参数描述2 这种格式,;需要在英文状态下输入,输入不要有空格
将生成的URL粘贴到浏览器后回车,显示效果如下:
第七步:导出一个可以运行的JAR包
如果希望能多次运行程序,可以将上述功能导出为可允许的jar文件