前因
公司让百度定制了一个产品,因为某些原因需要调用百度的接口。(这里本来可以用百度的SKD,大师因为是定制化的产品,接口也是高度定制化的,所以没法傻瓜式的操作使用SDK。需要自己生成签名)经过几日钻研之后,终于成功了。然后我把代码简单的封装了一下。
百度云鉴权认证机制
百度云签名算法实现
参考博客:菜鸟吉吉 -百度云API鉴权-java
代码
先添加百度云的sdk
<dependency>
<groupId>com.baidubce</groupId>
<artifactId>bce-java-sdk</artifactId>
<version>0.10.181</version>
</dependency>
因为需求中需要用临时凭证来生成签名算法,所以我封装了一个工具类来完成两种不同签名的算法(临时的和非临时的)。
生成临时凭证
private static final String STS_ENDPOINT = "http://sts.bj.baidubce.com";
private static final String ENDPOINT = "bj.bcebos.com";
private static final String ACCESS_KEY_ID = "ac5d5e37ff554d24a216aa91eb7f5358";
private static final String SECRET_ACCESS_KEY = "07c72a187cfc42648a0f89d6cefff5f2";
public static void main(String[] args) {
BceCredentials credentials = new DefaultBceCredentials(ACCESS_KEY_ID, SECRET_ACCESS_KEY);
StsClient client = new StsClient(
new BceClientConfiguration().withEndpoint(STS_ENDPOINT).withCredentials(credentials));
GetSessionTokenResponse response = client.getSessionToken(new GetSessionTokenRequest());
//临时凭证的ak
String accessKeyId = response.getAccessKeyId();
//临时凭证的sk
String secretAccessKey = response.getSecretAccessKey();
//临时凭证的sessionToken
String sessionToken = response.getSessionToken();
}
签名生成工具类
/**
* 生成百度智能云的鉴权签名工具类。适用于百度所有产品
* @date 2021/11/6 14:14
*/
public class AuthorizationStrUtils {
/**
* 生成的签名放入传入的headers中
* @date 2021/11/6 14:34
* @param access_key_id ak
* @param secret_access_key sk
* @param url 需要调用的url 例:http://bj.bcebos.com/v1/test
* @param headers 请求头列表。主账号请求头必须包含 Host ,临时凭证需要比主账号多一个参数 x-bce-security-token
* @param httpMethodName 请求方法 GET,POST,PUT,DELETE等等
* @param parameters 请求参数列表 没有就为null
* @return java.util.Map
**/
public static Map createAuthorization(String access_key_id, String secret_access_key, String url,
Map<String,String> headers ,HttpMethodName httpMethodName,
Map<String, String> parameters){
BceV1Signer v1Signer = new BceV1Signer();
try {
URI uri = new URI(url);
InternalRequest internalRequest = new InternalRequest(httpMethodName , uri);
//设置请求参数
if (parameters == null){
parameters = Maps.newHashMap();
}
internalRequest.setParameters(parameters);
//设置请求头时间 -此时间是格林威治时间 转成的百度云需要的格式
headers.put("x-bce-date",DateUtils.formatAlternateIso8601Date(new Date()));
internalRequest.setHeaders(headers);
//选择签名运算项,临时凭证需要多一个token来运算
SignOptions signOptions = new SignOptions();
if (headers.containsKey("x-bce-security-token")){
signOptions.setHeadersToSign(Sets.newHashSet("host","x-bce-date","x-bce-security-token"));
v1Signer.sign(internalRequest, new DefaultBceSessionCredentials(access_key_id, secret_access_key,headers.get("x-bce-security-token")),signOptions);
}else {
signOptions.setHeadersToSign(Sets.newHashSet("host","x-bce-date"));
v1Signer.sign(internalRequest, new DefaultBceCredentials(access_key_id, secret_access_key),signOptions);
}
String authorization = internalRequest.getHeaders().get("Authorization");
headers.put("Authorization",authorization);
} catch (URISyntaxException e) {
e.printStackTrace();
}
return headers;
}
}
调用工具类生成签名
//请求路径
String url = "http://bj.bcebos.com/v1/test";
//请求头在发起请求的时候可以复用
Map<String,String> headers = Maps.newHashMap();
//host一般是固定的,具体参考官方文档
headers.put("Host","bj.bcebos.com");
//放入临时凭证的sessionToken ,不是临时的凭证就不需要放入了
headers.put("x-bce-security-token",sessionToken);
AuthorizationStrUtils.createAuthorization(accessKeyId,
secretAccessKey,
url,
headers,
HttpMethodName.GET,
null);
//设置请求类型
headers.put("Content-Type","application/json; charset=utf-8");
//发起GET请求 这里用到了自己封装的http工具类,有兴趣的同学可以网上搜一搜
String result = HttpClientUtils.doGet("http://bj.bcebos.com/v1/test", headers, new HashMap<>());
System.out.println(result);
有了签名之后就可以用下面这个工具来验证我们的签名正确性了!不过注意需要把签名运算中唯一的变量 x-bce-date 给写死,不然每次生成的签名会不一样。👇
最后
其实光看官方文档的介绍还是会走很多弯路的,所以算是把百度云的SDK二次封装分享给大家,让同学们少掉几根头发。