我正在考虑使用有效的序列号实现 MySQL 数据库,如果检查返回 true,将根据用户输入检查并授予应用程序的使用,但我知道这太基本了,因为用户(将使用基于 localhost应用程序)可以轻松破解数据库并添加他自己的连续剧(或者如果他们认为应用程序来自“魔术盒子”,至少告诉对 PHP 和 SQL 有基本了解的其他人)。
由于我以前没有这样做过,有没有流行的方法?或者更好的是,如果你能给我一些想法就更好了。
我正在考虑使用有效的序列号实现 MySQL 数据库,如果检查返回 true,将根据用户输入检查并授予应用程序的使用,但我知道这太基本了,因为用户(将使用基于 localhost应用程序)可以轻松破解数据库并添加他自己的连续剧(或者如果他们认为应用程序来自“魔术盒子”,至少告诉对 PHP 和 SQL 有基本了解的其他人)。
由于我以前没有这样做过,有没有流行的方法?或者更好的是,如果你能给我一些想法就更好了。
AFAIK 如果他们有纯文本的 PHP 源代码,他们可以绕过您设置的任何保护措施。
也就是说,有一些服务,例如 ionCube (google it),它会混淆(编译?)代码,并且需要一个密钥(来自某个远程服务器)来解锁代码以执行。
或者,您可以为客户托管软件,这样他们就无法直接访问应用程序。
您可以实现“回拨”,发送用户在其网站上输入的序列号。然后,您在数据库中检查该序列号,并发送适当的回复,无论用户是否可以访问他的系统。当用户登录他们的网站时,您可以这样做。
这样做的问题是,由于在没有使用 Zend Guard 等工具加密/编码的情况下更改 php 文件非常容易,因此用户可以通过将调用更改为不进行来规避这一点,并始终返回 true。或者他们可以更改他们的网络服务器的主机文件,将请求重新路由到他们拥有的服务器,并在那里放置一个文件来伪造您的检查并且始终返回 true。
为了防止这种情况,您必须加密您的 php 文件并实施质询-响应系统来检查它们的序列号。
如果我明白你的意思。:-P
永远不会有任何 100% 不可破解的方法。如果您有时间和专业知识,任何事情都可以进行逆向工程。
但是,为了最大限度地提高不被破解的机会,您可以做的是使用某种预编译器/混淆器,例如Zend Guard或ionCube(以及其他)来保护您的代码。其中大多数(全部?)都带有预构建的许可功能,这绝对是推荐的方法。
这些的问题是它们不是免费的......
编辑
考虑一下,您可以在非常选择的一组环境中安全地自己实施类似的事情。如果您正在开发一些可以分发HipHop二进制文件的东西,那么您可以实现一些东西,而不必担心它会被那些不太清楚自己在做什么的人破解。HipHop 可以从 github 免费下载。
尽管如此,远程数据库检查仍然不是一个好主意,因为人们可以嗅探网络流量并对密钥进行逆向工程,或者学习如何欺骗响应(简单的主机文件编辑可以拦截网络流量)。您最好对每个实例的密钥进行硬编码,并在每次调用时使用某种算法对其进行验证——这个站点和谷歌可能会在这里为您提供帮助。
因此,您的主机上有一个 MySAL 数据库,并且客户应用程序连接到它,对吗?
起初我会在数据库和客户之间添加一个层。像 SOAP 之类的 http 远程接口或使用 json 的东西。
您应该加密与它的连接 (https) 或至少使用一些质询响应方法。
但是,当您的应用程序是开源的时,总会有绕过它的方法。即使不是;-)。
看看这里http://dev.michaelnorris.co.uk/tests/random_string.php
<?php
function makePin($lenth=10) {
// makes a random alpha numeric string of a given lenth
$aZ09 = array_merge(range('A', 'Z'), range('a', 'z'),range(0, 9));
//$aZ09 = array_merge(range('A', 'Z'), range(0, 9));
$out ='';
for($c=0;$c < $lenth;$c++) {
$out .= $aZ09[mt_rand(0,count($aZ09)-1)];
}
return $out;
}
$obscure = makePin();
echo $obscure;
?>
我认为这实际上对你更好。看看这里http://dev.michaelnorris.co.uk/tests/random_password.php
我不能把这个例子归功于这个例子,因为我是从其他我不记得的在线来源将它混合在一起的,但无论如何它都在这里。
<?php
// just so we know it is broken
error_reporting(E_ALL);
//string passType can be alpha, numeric, or alphanumeric defaults to alphanumeric int $length is the length of the password, defaults to eight
class randomPassword{
function __construct($passType='alphanumeric', $length=8, $rangeLength=9){
$this->setLength($length);
$this->setRangeLength($rangeLength);
$this->passType = $this->setPassType($passType);
}
function setRangeLength($rangeLength){
$this->rangeLength=$rangeLength;
}
// set the length of the password
private function setLength($length){
$this->length=$length;
}
// set the type of password
private function setPassType($passType){
return $passType.'Chars';
}
// return an array of numbers
private function numericChars(){
return range(0, $this->rangeLength);
}
// return an array of chars
private function alphaChars(){
return range('a', 'z');
}
// return an array of alphanumeric chars
private function alphaNumericChars(){
return array_merge($this->numericChars(), $this->alphaChars());
}
// return a string of chars
private function makeString(){
// here we set the function to call based on the password type
$funcName = $this->passType;
return implode($this->$funcName());
}
// shuffle the chars and return $length of chars
public function makePassword(){
return substr(str_shuffle($this->makeString()), 1, $this->length);
}
} // end class
function randomPassword($length) {
// create an array of chars to use as password
$chars = implode(array_merge(range(0,9), range('a', 'z')));
// randomly snarf $length number of array keys
return substr(str_shuffle($chars), 1, $length);
}
/*
try
{
$obj = new randomPassword('alphanumeric', 16, 100);
echo $obj->makePassword().'<br />';
}
catch(Exception $ex)
{
echo $ex->getMessage();
}
*/
echo strtoupper(randomPassword(5)).'-'.strtoupper(randomPassword(5)).'-'.strtoupper(randomPassword(5)).'-'.strtoupper(randomPassword(5)).'-'.strtoupper(randomPassword(5)).'-'.strtoupper(randomPassword(5));
?>