栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Java服务器授权+授权工具部分代码及思路

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java服务器授权+授权工具部分代码及思路

目标:

项目部署到服务器上,需要当前服务器授权后才能正常访问,控制项目授权日期、(某终端/通道)授权数量、用户登录访问菜单权限

注:

授权端:授权工具在自己手里,控制授权,在此我称之为授权工具

被授权端:jar包部署的服务器端,在此我称之为服务器

思路:

使用RSA-2048非对称加密方式,生成两对公钥私钥,公钥加密、私钥解密。

A公钥加密服务器的硬件信息生成机器码,

授权工具端通过上传A私钥文件解密服务器机器码。

获取到服务器硬件信息,再拼接有效日期、终端授权数量、菜单权限,授权工具端通过B公钥加密拼接内容生成授权License文件和授权记录(日志)文件。

服务器通过上传授权License文件,获取授权,使用时,通过B私钥解密并解析服务器硬件信息、有效日期、终端授权数量、菜单权限

步骤: 生成公钥私钥:
import sun.misc.base64Encoder;

import java.io.File;
import java.io.IOException;
import java.security.*;


public class KeyPairGenarete {
    
    private static final String ALGORITHM = "RSA";
    
    private static final int KEY_SIZE = 2048;

    public static void main(String[] args) throws Exception {
        // 随机生成一对密钥(包含公钥和私钥)
        KeyPair keyPair = KeyPairGenarete.generateKeyPair();
        // 获取 公钥 和 私钥
        PublicKey pubKey = keyPair.getPublic();
        PrivateKey priKey = keyPair.getPrivate();

        // 保存 公钥 和 私钥
        KeyPairGenarete.saveKeyForEncodedbase64(pubKey, Constants.CLIENTPUBLICKEY_FILEPATH);
        KeyPairGenarete.saveKeyForEncodedbase64(priKey, Constants.CLIENTPRIVATEKEY_FILEPATH);
    }
    
    public static KeyPair generateKeyPair() throws Exception {
        // 获取指定算法的密钥对生成器
        KeyPairGenerator gen = KeyPairGenerator.getInstance(ALGORITHM);

        // 初始化密钥对生成器(指定密钥长度, 使用默认的安全随机数源)
        gen.initialize(KEY_SIZE);

        // 随机生成一对密钥(包含公钥和私钥)
        return gen.generateKeyPair();
    }

    
    public static void saveKeyForEncodedbase64(Key key, String keyFile) throws IOException {
        // 获取密钥编码后的格式
        byte[] encBytes = key.getEncoded();

        // 转换为 base64 文本
        String encbase64 = new base64Encoder().encode(encBytes);

        // 保存到文件
        IOUtils.writeFile(encbase64, new File(keyFile));
    }


}
A公钥加密服务器的硬件信息生成机器码、前端通过接口复制机器码:

提供四种硬件信息可以随意选取拼接

package com.vikor.gateway.utils.license;

import org.springframework.beans.factory.annotation.Value;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStreamReader;

import static com.vikor.gateway.utils.license.Constants.CTClientPublicKey;
import static com.vikor.gateway.utils.license.Constants.CTServerPrivateKey;


public class LicenseCode {

    
    public static String getApplyCode(String no){
        try {//通过硬件信息+A公钥=加密后的硬件信息
            return RsaKey.Encrypt(no,CTClientPublicKey);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "缺少生成机器码相关文件";
    }

    
    public static String getbaseCode(){
        //cpu
        String CPU = getCPUSerial();
        //主板
        String boardSN = getMotherboardSN();

        StringBuilder sb = new StringBuilder(100);
        //硬件信息
        sb.append(CPU).append(",")
                .append(boardSN);
        return sb.toString();
    }

    
    public static String getMotherboardSN() {
        String result = "";
        try {
            File file = File.createTempFile("realhowto", ".vbs");
            file.deleteonExit();
            FileWriter fw = new FileWriter(file);
            String vbs = "Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")n"
                    + "Set colItems = objWMIService.ExecQuery _ n"
                    + "   ("Select * from Win32_baseBoard") n"
                    + "For Each objItem in colItems n"
                    + "    Wscript.Echo objItem.SerialNumber n"
                    + "    exit for  ' do the first cpu only! n" + "Next n";

            fw.write(vbs);
            fw.close();
            Process p = Runtime.getRuntime().exec(
                    "cscript //NoLogo " + file.getPath());
            BufferedReader input = new BufferedReader(new InputStreamReader(p
                    .getInputStream()));
            String line;
            while ((line = input.readLine()) != null) {
                result += line;
            }
            input.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result.trim();
    }

    
    public static String getCPUSerial() {
        String result = "";
        try {
            File file = File.createTempFile("tmp", ".vbs");
            file.deleteonExit();
            FileWriter fw = new FileWriter(file);
            String vbs = "Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")n"
                    + "Set colItems = objWMIService.ExecQuery _ n"
                    + "   ("Select * from Win32_Processor") n"
                    + "For Each objItem in colItems n"
                    + "    Wscript.Echo objItem.ProcessorId n"
                    + "    exit for  ' do the first cpu only! n" + "Next n";
            fw.write(vbs);
            fw.close();
            Process p = Runtime.getRuntime().exec(
                    "cscript //NoLogo " + file.getPath());
            BufferedReader input = new BufferedReader(new InputStreamReader(p
                    .getInputStream()));
            String line;
            while ((line = input.readLine()) != null) {
                result += line;
            }
            input.close();
            file.delete();
        } catch (Exception e) {
            e.fillInStackTrace();
        }
        if (result.trim().length() < 1 || result == null) {
            result = "无CPU_ID被读取";
        }
        return result.trim();
    }
 
    public synchronized static String getHardDiskSN(String drive) {
        String result = "";
        try {
            File file = File.createTempFile("realhowto", ".vbs");
            file.deleteonExit();
            FileWriter fw = new FileWriter(file);

            String vbs = "Set objFSO = CreateObject("scripting.FileSystemObject")n"
                    + "Set colDrives = objFSO.Drivesn"
                    + "Set objDrive = colDrives.item(""
                    + drive
                    + "")n"
                    + "Wscript.Echo objDrive.SerialNumber"; // see note
            fw.write(vbs);
            fw.close();
            Process p = Runtime.getRuntime().exec(
                    "cscript //NoLogo " + file.getPath());
            BufferedReader input = new BufferedReader(new InputStreamReader(p
                    .getInputStream()));
            String line;
            while ((line = input.readLine()) != null) {
                result += line;
            }
            input.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result.trim();
    }
    
    public static String getMac() {
        try {
            byte[] mac = NetworkInterface.getByInetAddress(InetAddress.getLocalHost()).getHardwareAddress();
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < mac.length; i++) {
                if (i != 0) {
                    sb.append("-");
                }
                String s = Integer.toHexString(mac[i] & 0xFF);
                sb.append(s.length() == 1 ? 0 + s : s);
            }
            return sb.toString().toUpperCase();
        } catch (Exception e) {
            return "";
        }

    }
}

API接口:

import java.io.UnsupportedEncodingException;

import static com.vikor.gateway.utils.license.CheckAuthorizeCode.*;
import static com.vikor.gateway.utils.license.Constants.*;
import static com.vikor.gateway.utils.license.LicenseCode.getApplyCode;
import static com.vikor.gateway.utils.license.LicenseCode.getbaseCode;


@Component
@RestController
@Api(tags = "授权")
@RequestMapping(value = "license")
public class LicenseController extends baseController {

    @Resource
    private LicenseService licenseService;

    //获取硬件信息
    private String code = getbaseCode();

    @GetMapping(value = "/license")
    @ApiOperation(value = "机器码", tags = "授权")
    public AjaxResult applyCode() {
        return success(getApplyCode(code));
    }

用户登录验证授权

系统设置页面展示

 授权工具端通过上传A私钥文件解密服务器机器码

注:用java swing写的小工具代码太多了,就不展示了

 获取到服务器硬件信息,再拼接有效日期、终端授权数量、菜单权限,授权工具端通过B公钥加密拼接内容生成授权License文件和授权记录(日志)文件。
package com.company.java;

import org.apache.commons.codec.digest.DigestUtils;

import java.io.*;
import java.util.Date;

import static com.company.java.Constants.CONF;
import static com.company.java.RsaKey.toHexString;



public class EncoderFile {
    public static Boolean licenseWrite( String applyCode,String licenseDate,int channelNum,String path,String projectName,String projectId,String menuPermission,String isMenuPermission) throws Exception {
        boolean flag = true;
        String filePath = Constants.PATH +"license/"+ projectName +"/"+ Constants.DateFormat.format(new Date());
        //授权文件
        File licenseFile = FileWrite(filePath, Constants.LICENSE_NAME);
        //日志
        File logFile = FileWrite(filePath, Constants.LOG_NAME);
        String Content =
                "项目编码 = "+projectName+",n" +
                "项目名称 = "+projectId+",n" +
                "有效日期 = "+licenseDate+",n" +//2校验日期
                "终端授权数量 = "+channelNum+",n" + //日期采用yyyy-MM-dd日期
                "菜单权限 = "+menuPermission+",n" +
                "加密菜单权限文件 = "+isMenuPermission+",n" +
                "机器码 = "+applyCode;

        //保存授权记录
        mywrite(logFile,Content);

        String string = RsaKey.Decrypt(applyCode,path)+","+licenseDate+","+channelNum+","+menuPermission;
        try {
            string = RsaKey.Encrypt(string, Constants.SERVERPUBLICKEY_FILEPATH);
        } catch (Exception e) {
            flag = false;
            System.out.println("flag"+flag);
            e.printStackTrace();
        }
        mywrite(licenseFile,string);

        if (isMenuPermission.equals("是")){
            byte[] configByte = IOUtils.readFile(new File(CONF)).getBytes("UTF-8");
            String hexString = toHexString(configByte).toUpperCase();
            //配置文件
            File menuFile = FileWrite(filePath, Constants.CONFNAME);
            IOUtils.writeFile(hexString,menuFile);
        }

        System.out.println("flag"+flag);
        return flag;

    }
    
    public static void mywrite(File licenseFile , String write){
        File file = licenseFile;    //1、建立连接
        OutputStream os = null;
        try {
            //2、选择输出流,以追加形式(在原有内容上追加) 写出文件 必须为true 否则为覆盖
            os = new FileOutputStream(file);
            byte[] data = write.getBytes();    //将字符串转换为字节数组,方便下面写入

            os.write(data, 0, data.length);    //3、写入文件
            os.flush();    //将存储在管道中的数据强制刷新出去
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            System.out.println("文件没有找到!");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("写入文件失败!");
        }finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    System.out.println("关闭输出流失败!");
                }
            }
        }
    }

    public static String myread(File licenseFile ){

        StringBuilder sb = new StringBuilder();
        try {
            // 读取字符文件
            BufferedReader in = new BufferedReader(new FileReader(licenseFile));
            try {
                String s;
                while ((s = in.readLine()) != null) {
                    sb.append(s + "n");
                }
            }finally{
                in.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    
    public static File FileWrite(String filePath,String filename) throws Exception {
        File file = new File(filePath+filename);
        if (!file.exists()) {
            file.getParentFile().mkdirs();
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return file;
    }
}
服务器通过上传授权License文件,获取授权,使用时,通过B私钥解密并解析服务器硬件信息、有效日期、终端授权数量、菜单权限
package com.vikor.gateway.utils.license;

import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;



public class CheckAuthorizeCode {
    
    public static boolean AuthorizeCode(String licensePath) throws Exception {
        File file = new File(licensePath);
        //获取硬盘信息
        String code = LicenseCode.getbaseCode();
        //读取授权码文件,获取授权码
        String encoder = myread(file).trim();

        //解析授权码,与本机的硬件信息进行比较,这里仅仅只是用的字符串contains方法
        String en = LicenseCode.getPlaintext(encoder);
        String[] split = en.split(",");

        if(!file.exists()){
            return false;
        }

        if(StringUtils.isEmpty(encoder)){
            return false;
        }

        if (!en.contains(code)) {
            return false;
        }

        if (!LicenseDateUtils.authorize_date(split[2])) {
            return false;
        }
        return true;
    }


    public static String myread(File licenseFile ){

        StringBuilder sb = new StringBuilder();
        try {
            // 读取字符文件
            BufferedReader in = new BufferedReader(new FileReader(licenseFile));
            // 为什么单独在这里加上try块而不是直接使用外边的try块?
            // 需要考虑这么一种情况,如果文件没有成功打开,则finally关闭文件会出问题
            try {
                String s;
                while ((s = in.readLine()) != null) {
                    sb.append(s + "n");
                }
            }finally{
                in.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sb.toString();
    }
    public static void FileWrite(MultipartFile file, String path) throws Exception {
        File fileW = new File(path);
        if (!fileW.exists()) {
            fileW.getParentFile().mkdirs();
            try {
                fileW.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //获取文件字节数组
        byte [] bytes = file.getBytes();
        //写入指定文件夹
        OutputStream out = new FileOutputStream(fileW);
        out.write(bytes);
    }
}

controll层

    
    @GetMapping(value = "/checkLicense")
    @ApiOperation(value = "验证授权", tags = "授权")
    public AjaxResult checkLicense() throws Exception {
        if (AuthorizeCode(fileRootPath+LICENSEPATH))
            return success("授权成功");
        return error("授权已到期");
    }

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/338367.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号