这个域名应该是citrix的,连到internet才会解析
在 2013年10月21日下午5:27,yao hu <huyao...@gmail.com>写道: > 我们在访问实例console或者下载模板时,cloudstack都会返回一个 > https://192-168-45-248.realhostip.com > 这种类似的url,有没有人知道是谁负责解析realhostip.com这个域名的了??? > > > 在 2013年10月16日下午3:06,Wei ZHOU <ustcweiz...@gmail.com>写道: > > > 那你签名的时候也用encodeBase64URLSafeString试试 > > api的参数在apiservlet/apiserver.java里有对参数特殊字符的检查 > > console没有这块。我猜想也是为了安全。 > > > > > > 在 2013年10月16日上午4:54,yao hu <huyao...@gmail.com>写道: > > > > > 我这是内网开发环境,给你也不能用,你自己用你的secret key试一下, > > > 我现在的疑问是,客户端生成签名的方法是一样的,为什么服务器端验证时 > > > 用的方法不一样,是bug还是有什么我们不知道的特殊作用。 > > > > > > > > > 在 2013年10月16日上午10:31,Gavin Lee <gavin....@gmail.com>写道: > > > > > > > 你能把你的SecretKey贴出来吗?这样我也试一下生产Signature。 > > > > encodeBase64URLSafeString应该都会调到的。 > > > > > > > > > > > > 2013/10/11 yao hu <huyao...@gmail.com> > > > > > > > > > 1. 问题现象 > > > > > > > > > > 用apikey访问实例console时,浏览器提示无效的session或者api key,导致访问失败。 > > > > > > > > > > 测试版本:win7+cygwin+xenserver 6.1.0+cloudstack 4.1.1 > > > > > > > > > > 测试操作步骤: > > > > > > > > > > 1. 用api key和secret key构造一个访问实例console的url > > > > > > > > > > > > > > > > > > > > > > > > > http://localhost:8080/client/console?cmd=access&vm=b194369f-e0d4-45d8-a50f-09ec51095e68&apikey=fmS7oyThP6MGxN5X_CgeOCxQIqgTu5QFDz46r2Pv5kLp88EYYBquSu6_3s3d9MXdbUHPpxj5qDDy1jvhEpQWvQ&signature=y3dNHn580NJiCVRGwrBTR4JHImo%3D > > > > > > > > > > 2. 把上面构造的url粘贴到浏览器地址栏,并访问,提示如下信息 > > > > > > > > > > [image: 内嵌图片 1] > > > > > > > > > > 2. 问题分析 > > > > > > > > > > 问题出现后,一开始是怀疑构造url的脚本有错,后面又尝试构造其它api的url来验证脚本是否正确。如构造调用listAccounts > > > > API的url > > > > > ,其url如下: > > > > > > > > > > > > > > > > > > > > > > > > > http://localhost:8080/client/api?command=listAccounts&apikey=fmS7oyThP6MGxN5X_CgeOCxQIqgTu5QFDz46r2Pv5kLp88EYYBquSu6_3s3d9MXdbUHPpxj5qDDy1jvhEpQWvQ&signature=ALhJtw%2Bzi7Rcmo%2Bkk3xH3cTJgp4%3D > > > > > > > > > > 在浏览器中访问该url后,能正确返回结果,这就说明构造url的脚本是没有错的。 > > > > > > > > > > > > 接着,调试了访问实例console这部分的源代码,并定位到失败的地方是在ConsoleProxyServlet.java文件的 > > > > > verifyRequest函数,其主要代码如下: > > > > > > > > > > private boolean verifyRequest(Map<String, Object[]> > > requestParameters) > > > { > > > > > > > > > > try { > > > > > > > > > > ...省略部分代码 > > > > > > > > > > unsignedRequest = unsignedRequest.toLowerCase(); > > > > > > > > > > > > > > > > > > > > Mac mac = Mac.getInstance("HmacSHA1"); > > > > > > > > > > SecretKeySpec keySpec = new > > SecretKeySpec(secretKey.getBytes(), > > > > > "HmacSHA1"); > > > > > > > > > > mac.init(keySpec); > > > > > > > > > > mac.update(unsignedRequest.getBytes()); > > > > > > > > > > byte[] encryptedBytes = mac.doFinal(); > > > > > > > > > > String computedSignature = > > > > > Base64.encodeBase64URLSafeString(encryptedBytes); > > > > > > > > > > boolean equalSig = signature.equals(computedSignature); > > > > > > > > > > if (!equalSig) { > > > > > > > > > > s_logger.debug("User signature: " + signature + " is > > not > > > > > equaled to computed signature: " + computedSignature); > > > > > > > > > > } > > > > > > > > > > ... 省略部分代码 > > > > > > > > > > return equalSig; > > > > > > > > > > } catch (Exception ex) { > > > > > > > > > > s_logger.error("unable to verifty request signature", ex); > > > > > > > > > > } > > > > > > > > > > return false; > > > > > > > > > > } > > > > > > > > > > > > > > 这个函数中红色字体部分在验证签名时失败。其中,signature是客户端url中传进来的参数,computedSignature是服务端根据api > > > > > key和secret key计算出来的。signature与computedSignature比较时不相同,导致函数返回false。 > > > > > > > > > > 由于用api > key调用其它api时是能正确得到结果的,故又调试了其它api的调用流程,并定位到其验证signature的代码,在文件 > > > > > ApiServer.java的verifyRequest函数中,其主要代码如下: > > > > > > > > > > public boolean verifyRequest(Map<String, Object[]> > requestParameters, > > > > Long > > > > > userId) throws ServerApiException { > > > > > > > > > > try { > > > > > > > > > > ...省略部分代码 > > > > > > > > > > unsignedRequest = unsignedRequest.toLowerCase(); > > > > > > > > > > > > > > > > > > > > Mac mac = Mac.getInstance("HmacSHA1"); > > > > > > > > > > SecretKeySpec keySpec = new > > > > > SecretKeySpec(secretKey.getBytes(), "HmacSHA1"); > > > > > > > > > > mac.init(keySpec); > > > > > > > > > > mac.update(unsignedRequest.getBytes()); > > > > > > > > > > byte[] encryptedBytes = mac.doFinal(); > > > > > > > > > > String computedSignature = > > > > > Base64.encodeBase64String(encryptedBytes); > > > > > > > > > > boolean equalSig = > signature.equals(computedSignature); > > > > > > > > > > if (!equalSig) { > > > > > > > > > > s_logger.debug("User signature: " + signature > + > > " > > > is > > > > > not equaled to computed signature: " + computedSignature); > > > > > > > > > > } > > > > > > > > > > ...省略部分代码 > > > > > > > > > > return equalSig; > > > > > > > > > > } catch (Exception ex) { > > > > > > > > > > s_logger.error("unable to verifty request signature", > > > ex); > > > > > > > > > > } > > > > > > > > > > return false; > > > > > > > > > > } > > > > > > > > > > > > 这个函数的红色部分对signature进行了验证,signature与computedSignature进行比较时相同,故能通过验证,函数返回 > > > > > true。 > > > > > > > > > > 仔细比较这两个verifyRequest函数验证signature部分的代码,我们可以发现前面的verifyRequest函数在计算 > > > > > computedSignature时,使用的是Base64.encodeBase64URLSafeString > > > > > > > > > > 函数,而后面那个使用的是Base64.encodeBase64String,就这说明,客户端生成的signature可以通过 > > > > > Base64.encodeBase64String的验证。接着,把Base64.encodeBase64URLSafeString > > > > > > > > > > 替换为Base64.encodeBase64String,重新编译源代码并部署,再次通过api > > > > key来访问实例console,这次是能成功访问的。 > > > > > > > > > > > > > > > 为何这两个verifyRequest函数中使用两个不同的encode方法?是bug?还是用 > > > > > Base64.encodeBase64URLSafeString有特别的意义? > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > -- > > > > Gavin > > > > > > > > > >