系统环境差异造成的异常


Motivation

通过近期收到的反馈和自己的经历,我觉得有必要写这么一篇博文,记录一些由服务器和PC之间的差异引起的不好判断的问题、其原因及其解决方法。


异常1:访问Servlet报错404,排除了各种错误的可能,仍不能正确访问

安全组策略
简单地说就相当于一道防火墙,我们可以自己设定过滤规则。还可以进一步的理解为一套黑白名单系统。

之所以提到安全组策略,是因为,我们遇上这个问题的一个可能就是,云服务器的安全组策略中没有允许80端口或者8080端口访问。

以阿里云服务器为例,以下是操作步骤:
①登录阿里云官方网站,点击右上角的控制台
控制台

②点击左侧“云服务器ECS”选项卡
云服务器ECS

③点击下方自己的云服务器实例
云服务器实例

④点击右侧“管理”
管理

⑤点击左侧二级菜单中的“本实例安全组”
本实例安全组

⑥点击右侧“配置规则”
配置规则

⑦在此时弹出的页面中,选择左上方“入方向”选项卡
入方向
在列表中的第三行,看是否开放了80或8080端口,如果没有开放,至少可以说明你服务器连接不通的原因之一就在这了。否则,回去继续检查代码的问题。

⑧如果上一步你没有看到80或8080端口,点击页面右上方“添加安全组规则”按钮
添加安全组规则

⑨按照下图配置即可,之后按右下角“确定”按钮
规则

到这里,安全规则就添加完了,你也可以照猫画虎开放其他必要的端口,然后再测试一下,可能就通了,或者变了其他的报错信息,再具体排除。


异常2:用自己实现的MD5加密算法对用户密码进行加密,发现相同的密码明文在PC(开发用的电脑)上和服务器端得到的密文(即散列值)不同

加密函数代码如下:

public static String getCiphertext(String password) {
    try {
        byte[] btPassword = password.getBytes();
        // 获得MD5摘要算法的 MessageDigest 对象
        MessageDigest md5 = MessageDigest.getInstance("MD5");
        // 使用指定的字节更新摘要
        md5.update(btPassword);
        // 获得密文
        byte[] binaryCiphertext = md5.digest();
        // 把密文转换成十六进制的字符串形式
        return toString(binaryCiphertext);
    } catch (NoSuchAlgorithmException e) {
        return null;
    }
}

当执行以下代码时:

String palinText = "1234567890";
String cipherText = getCiphertext(palinText);
System.out.println(cipherText);

在服务器端得到的输出结果是:

28C2596CF7EFD7548B02854ABC210650

而PC上得到的输出结果是:

F54F990C541048704B7EB806A703DE04

这就很困惑了,在没写注册功能的时候,单独测试登录功能就比较麻烦,因为手动给数据库里填的值时机登录的时候验证通不过,暂时留着个已知Bug不管也很是不爽。

经过一番搜索,终于在一篇问答帖中找到了来自大神的答案:
关键在于

byte[] btPassword = password.getBytes();

getBytes()这个方法应该传入一个指定的字符集,如"UTF-8",否则会根据当前应用环境上下文中的字符集来编码,造成差异。
将这行代码改为:

byte[] btPassword = password.getBytes("UTF-8");

就可以发现,无论在什么环境下,相同明文经过MD5之后得到的散列值是一致的。


异常3:javax.crypto.BadPaddingException:Given final block not properly padded.

情境: 在Windows系统下运行正常的DES解密函数,部署到Linux服务器上之后报上述错误。

异常代码段:

            SecureRandom secureRandom = new SecureRandom(SECRET_KEY.getBytes());
            KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
            keyGenerator.init(secureRandom);
            key = keyGenerator.generateKey();

触发异常的原因: SecureRandom 的实现依赖操作系统本身的內部状态,该实现在 windows 上每次生成的 key 都相同,但是在Solaris 或部分Linux 系统上则不同。

解决方案: 先调用getInstance方法,然后调用setSeed方法。

            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
            secureRandom.setSeed(SECRET_KEY.getBytes());
            KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
            keyGenerator.init(secureRandom);
            key = keyGenerator.generateKey();

异常4:org.hibernate.engine.jdbc.spi.SqlExceptionHelper.logExceptions SQL Error: 1146, SQLState: 42S02

情境: 在Linux服务器下部署工程之后,访问时发生上述异常。

触发异常的原因: 操作系统的大小写敏感性决定数据库和表命名的大小写敏感,这就意味着数据库和表名在 Windows 中是大小写不敏感的,而在大多数类型的 Unix/Linux 系统中是大小写敏感的。

解决方案: 发现数据库中的对应表名是user,而SQL语句中写的是User,全部改成小写。


后记

自己的PC和服务器之间、Windows操作系统和Linux操作系统之间都存在着许多差异,这就会造成许多意料之外的异常,再次遇到的概率也很高,因此值得记录下来。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IMplementist

你的鼓励,是我继续写文章的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值