帆软报表设计器源代码。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

268 lines
7.0 KiB

package com.fr.design.mainframe;
import com.fr.config.MarketConfig;
import com.fr.design.DesignerEnvManager;
import com.fr.general.SiteCenter;
import com.fr.general.http.HttpClient;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.stable.core.UUID;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
/**
* 限定以"-"分割得到数组长度=4;
* 至少包含10个以上不同的字符
* 每7位字符, 要求可以被7整除
* 限定同一个字符, 不可以出现10次以上
* 限定不能出现7个字符内全是字母的情况
*
* @author neil
*
* @date: 2015-4-8-上午8:49:05
*/
public class ActiveKeyGenerator {
//没网的情况, 返回认证错误, 下次启动再去认证
public static final int AUTH_ERROR = -1;
//认证成功
public static final int AUTH_SUCCESS = 0;
//认证失败
public static final int AUTH_FAILED = 1;
private static final int CONNECT_LEN = 4;
private static final int KEY_LEN = 5;
private static final int MIN_NUM_COUNT = 10;
private static final int MAGIC_NUM = 7;
private static final String SPLIT_CHAR = "-";
private static final int MAX_TRY_COUNT = 100;
/**
* 生成激活码, 用于从老的激活码生成新的
*
* @return 8.0新的激活码
*
*/
public static String generateActiveKey(){
for (int i = 0; i < MAX_TRY_COUNT; i++) {
String key = UUID.randomUUID().toString();
char[] keyChar = key.toCharArray();
int len = keyChar.length;
int[] numArray = new int[len];
if(invalidEachCharCount(len, keyChar, numArray)){
continue;
}
if(isCharAllNum(len, numArray, keyChar)){
continue;
}
String activeKey = new String(keyChar);
//跑出来的key, 自己再去认证下
if(!localVerify(activeKey)){
continue;
}
return activeKey;
}
return StringUtils.EMPTY;
}
/**
* 验证key合法性, 包括本地和在线验证
*
* @param key 激活码
* @param timeout 验证超时时间
*
* @return 是否合法
*
*/
public static boolean verify(String key, int timeout){
return localVerify(key) && onLineVerify(key, timeout);
}
/**
* 在线校验激活码(超时也算验证通过, 但是会在下次联网时继续验证)
*
* @param key 激活码
*
* @return 是否验证通过
*
*/
public static boolean onLineVerify(String key){
return onLineVerify(key, -1);
}
//准备验证的HttpClient
private static HttpClient prepareVerifyConnect(DesignerEnvManager envManager, int timeout, String key){
HashMap<String, String> para = new HashMap<String, String>();
para.put("uuid", envManager.getUUID());
para.put("key", key);
para.put("username", MarketConfig.getInstance().getBbsUsername());
HttpClient hc = new HttpClient(SiteCenter.getInstance().acquireUrlByKind("verify.code"), para);
if (timeout != -1) {
hc.setTimeout(timeout);
}
return hc;
}
/**
* 在线校验激活码(超时也算验证通过, 但是会在下次联网时继续验证)
*
* @param key 激活码
* @param timeout 超时时间
*
* @return 是否验证通过
*
*/
public static boolean onLineVerify(String key, int timeout){
DesignerEnvManager envManager = DesignerEnvManager.getEnvManager();
HttpClient hc = prepareVerifyConnect(envManager, timeout, key);
//先关闭掉在线验证, 服务器扛不住, 先内网跑并发测试下性能, 确定了问题在开放.
if (true || !hc.isServerAlive()) {
//连不上服务器的话, 先算通过, 下次重启还会继续在线验证
return true;
}
boolean res = Boolean.valueOf(hc.getResponseText());
if (res) {
//联网验证通过了, 就把验证通过的状态存起来, 下次就不用联网验证了.
envManager.setActiveKeyStatus(AUTH_SUCCESS);
} else {
//如果没验证通过, 清空掉当前activekey.当他重启后, 重新输入激活码
envManager.setActivationKey(StringUtils.EMPTY);
}
return res;
}
/**
* 本地校验激活码
*
* @param key 激活码
*
* @return 是否验证通过
*
*/
public static boolean localVerify(String key){
if(StringUtils.isEmpty(key) || invalidSplitLength(key)){
return false;
}
char[] keyChar = key.toCharArray();
int len = keyChar.length;
int[] numArray = new int[len];
if(invalidEachCharCount(len, keyChar, numArray)){
return false;
}
int count = len / MAGIC_NUM;
if (count != KEY_LEN) {
return false;
}
//检测余数
return validRemain(count, numArray);
}
//是否全字母
private static boolean isCharAllNum(int len, int[] numArray, char[] keyChar){
int count = len / MAGIC_NUM;
for (int j = 0; j < count; j++) {
int temp = 0;
for (int k = 0; k < MAGIC_NUM; k++) {
temp = temp + numArray[k + j * MAGIC_NUM];
}
if(temp == 0){
return true;
}
updateRemain(temp, numArray, j, keyChar);
}
return false;
}
//是否符合规定的split格式
private static boolean invalidSplitLength(String key){
return key.split(SPLIT_CHAR).length != CONNECT_LEN;
}
//获取char对应的int值
private static int getCharIntValue(char charStr){
if (!StableUtils.isNum(charStr)) {
return 0;
}
return Character.getNumericValue(charStr);
}
//校验余数
private static boolean validRemain(int count, int[] numArray){
for (int j = 0; j < count; j++) {
int temp = 0;
for (int k = 0; k < MAGIC_NUM; k++) {
temp = temp + numArray[k + j * MAGIC_NUM];
}
if (temp == 0){
return false;
}
if(temp % MAGIC_NUM != 0){
return false;
}
}
return true;
}
//判断是否存在不合法(过多)的某一个字符
private static boolean invalidEachCharCount(int len, char[] keyChar, int[] numArray){
HashMap<Character, Integer> hs = new HashMap<Character, Integer>();
for (int j = 0; j < len; j++) {
int count = hs.containsKey(keyChar[j]) ? hs.get(keyChar[j]) + 1 : 1;
hs.put(keyChar[j], count);
numArray[j] = getCharIntValue(keyChar[j]);
}
if (hs.size() <= MIN_NUM_COUNT) {
return true;
}
Iterator<Entry<Character, Integer>> it = hs.entrySet().iterator();
while (it.hasNext()) {
Entry<Character, Integer> entry = it.next();
if(entry.getValue() > MIN_NUM_COUNT){
return true;
}
}
return false;
}
//更新余数
private static void updateRemain(int temp, int[] numArray, int j, char[] keyChar){
//余数
int remain = temp % MAGIC_NUM;
int lastMagicIndex = MAGIC_NUM - 1 + j * MAGIC_NUM;
int newNum = numArray[lastMagicIndex] - remain;
while(newNum <= 0){
newNum += MAGIC_NUM;
}
keyChar[lastMagicIndex] = (char)(newNum + '0');
}
public static void main(String[] args) {
String a = "671b3b43-cfb4-40e7-9ca8-fe71ba33b8e3";
String key = generateActiveKey();
boolean verify = localVerify(key);
System.out.println(verify);
}
}