springboot实现Web系统License授权认证

springboot实现Web系统License授权认证在我们做系统级框架的时候,我们要一定程度上考虑系统的使用版权,不能随便一个人拿去在任何环境都能用,所以我们需要给我们系统做一个授权认证机制,只有上传了我们下发的lic文件并验证通过,才能正常使用,下面就开始一步一步实现这个功能1.生成机器码我们首先要做的就是对软件部署的环境的唯一性进行限制,这里使用的是macadderss,当然你也可以换成cpu序列编号,并无太大影响,先上代码pri…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

在我们做系统级框架的时候,我们要一定程度上考虑系统的使用版权,不能随便一个人拿去在任何环境都能用,所以我们需要给我们系统做一个授权认证机制,只有上传了我们下发的lic文件并验证通过,才能正常使用,下面就开始一步一步实现这个功能

1.生成机器码

我们首先要做的就是对软件部署的环境的唯一性进行限制,这里使用的是macadderss,当然你也可以换成cpu序列编号,并无太大影响,先上代码

private static String getMac() {
        try {
            Enumeration<NetworkInterface> el = NetworkInterface
                    .getNetworkInterfaces();
            while (el.hasMoreElements()) {
                byte[] mac = el.nextElement().getHardwareAddress();
                if (mac == null)
                    continue;
                String hexstr = bytesToHexString(mac);
                return getSplitString(hexstr, "-", 2).toUpperCase();
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
        return null;
    } 

public static String getMachineCode() throws Exception{
        Set<String> result = new HashSet<>();
        String mac = getMac();
        result.add(mac);
        Properties props = System.getProperties();
        String javaVersion = props.getProperty("java.version");
        result.add(javaVersion);
        String javaVMVersion = props.getProperty("java.vm.version");
        result.add(javaVMVersion);
        String osVersion = props.getProperty("os.version");
        result.add(osVersion);
        String code = Encrpt.GetMD5Code(result.toString());
        return getSplitString(code, "-", 4);

    }

这里进行的操作是取出机器码,与java版本,jvm,操作系统参数进行混合,并进行MD5操作

2.进行lic文件的生成

springboot实现Web系统License授权认证

springboot实现Web系统License授权认证

这是我生成证书与进行授权证书的界面,可以看到授权证书主要包含三个要素,机器码,是否永久有效标识,证书时效,我们会将这些数据写入文本中并进行加密处理,看下生成证书的代码

public static void getLicense(String isNoTimeLimit, String licenseLimit, String machineCode, String licensePath, String priavateKeyPath) throws Exception{
        String[] liccontent = {
                "LICENSEID=yanpeng19940119@gmail.com",
                "LICENSENAME=YBLOG使用证书",
                MessageFormat.format("LICENSETYPE={0}",isNoTimeLimit),
                MessageFormat.format("EXPIREDAY={0}",licenseLimit), //日期采用yyyy-MM-dd日期格式
                MessageFormat.format("MACHINECODE={0}",machineCode),
                ""
        };

        //将lic内容进行混合签名并写入内容
        StringBuilder sign = new StringBuilder();
        for(String item:liccontent){
            sign.append(item+"yblog");
        }
        liccontent[5] = MessageFormat.format("LICENSESIGN={0}",Encrpt.GetMD5Code(sign.toString()));
        FileUtil.createFileAndWriteLines(licensePath,liccontent);
        //将写入的内容整体加密替换
        String filecontent =FileUtil.readFileToString(licensePath);
        String encrptfilecontent = Encrpt.EncriptWRSA_Pri(filecontent,priavateKeyPath);
        File file = new File(licensePath);
        file.delete();
        FileUtil.createFile(licensePath,encrptfilecontent);
    }

这里我们是将一些信息与特定标识进行拼接然后加密,使用的是RSA加密,我们使用私钥加密公钥解密,保证验证的开放性与生成证书的私密性,密钥可以使用java自带的keytool工具进行生成,教程地址:http://note.youdao.com/noteshare?id=09e2bfc902b21a335a4505f7946a45c9,在lic文件最后我们加上一个LICENSESIGN参数,对其他信息进行一次加密,防止信息被篡改,生成文件后再对文本进行整体加密

这里生成密钥的长度为2048而非1024,所以解密块长度为256,这里需要注意下,公钥加密方法为,为了方便大家,这里提供下具体加密代码

private static final int MAX_ENCRYPT_BLOCK = 117;
private static final int MAX_DECRYPT_BLOCK=256; 
public static String EncriptWRSA_Pri(String data,String path) throws Exception{
        String encryptData ="";

        FileInputStream in = new FileInputStream(path);
        KeyStore ks = KeyStore.getInstance("JKS");// JKS: Java KeyStoreJKS,可以有多种类型
        ks.load(in, "123".toCharArray());
        in.close();

        String alias = "yblogkey"; // 记录的别名
        String pswd = "123"; // 记录的访问密码
        java.security.cert.Certificate cert = ks.getCertificate(alias);
        //获取私钥
        PrivateKey privateKey = (PrivateKey) ks.getKey(alias, pswd.toCharArray());
        //私钥加密
        Cipher cipher = Cipher.getInstance("rsa");
        SecureRandom random = new SecureRandom();
        cipher.init(Cipher.ENCRYPT_MODE, privateKey, random);

        try {
            //  Cipher cipher = Cipher.getInstance("RSA");
            //   cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            int length = data.getBytes().length;
            int offset = 0;
            byte[] cache;
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            int i = 0;
            while(length - offset > 0){
                if(length - offset > MAX_ENCRYPT_BLOCK){
                    cache = cipher.doFinal(data.getBytes(), offset, MAX_ENCRYPT_BLOCK);
                }else{
                    cache = cipher.doFinal(data.getBytes(), offset, length - offset);
                }
                outStream.write(cache, 0, cache.length);
                i++;
                offset = i * MAX_ENCRYPT_BLOCK;
            }
            return encode.encode(outStream.toByteArray());
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return encryptData;
    }

 public static String DecriptWithRSA_Pub(String data,String path) throws Exception{
        X509Certificate x509Certificate = (X509Certificate) getCertificate(path);
        // 获得公钥
        PublicKey publicKey = x509Certificate.getPublicKey();

        Cipher cipher = Cipher.getInstance("rsa");
        SecureRandom random = new SecureRandom();

        byte[] bEncrypt = decoder.decodeBuffer(data);
        //公钥解密
        cipher.init(Cipher.DECRYPT_MODE, publicKey, random);
        String decryptData = "";
        // byte[] plainData = cipher.doFinal(bEncrypt);
        //  System.out.println("11111:"+new String(plainData));
        int inputLen = bEncrypt.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段解密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(bEncrypt, offSet, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(bEncrypt, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        return  new String(decryptedData);
    }

3.验证lic

我们会在系统中注册一个拦截器,未通过系统授权认证会自动跳转到lic文件上传界面,springboot接收文件与常规java有一些不同,使用的MultipartFile对象,会获取到上传文件的数组,进行操作,看下保存上传lic文件代码

@RequestMapping(value="/login/licenseauth",method= RequestMethod.POST)
    @ResponseBody
    public Map<Object,Object> licenseauth(MultipartHttpServletRequest multiReq){
        Map<Object,Object>  map = new HashMap<Object,Object>();
        try {
            String savePath = ResourceUtils.getURL("src/main/resources/static/lic").getPath();
            MultipartFile file = multiReq.getFile("file");
            String filename = file.getOriginalFilename();
            File uploadfile = new File(savePath + "\\" + filename);
            if (!uploadfile.exists()){
                //获取item中的上传文件的输入流
                InputStream in = file.getInputStream();
                //创建一个文件输出流
                FileOutputStream out = new FileOutputStream(savePath + "\\" + filename);
                //创建一个缓冲区
                byte buffer[] = new byte[1024];
                //判断输入流中的数据是否已经读完的标识
                int len = 0;
                //循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
                while((len=in.read(buffer))>0){
                    //使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中
                    out.write(buffer, 0, len);
                }
                //关闭输入流
                in.close();
                //关闭输出流
                out.close();
            }
            map.put("executestatus","1");

        }catch (Exception e){
            e.printStackTrace();
            map.put("executestatus","0");
        }

        return map;
    }

有了上传文件,我们就可以通过系统内置的公钥对lic文件的机器码,授权时间进行验证,确定是否能正常访问系统

public static boolean authLicense() throws Exception{
        boolean isauth = false;
        String pubkpath = ResourceUtils.getURL("src/main/resources/static/lic/").getPath()+"yblog.crt";
        String licpath = ResourceUtils.getURL("src/main/resources/static/lic/").getPath();
        File lic = new File(licpath);
        String[] filelist = lic.list();
        if (filelist.length>0){
            for (int i = 0; i < filelist.length; i++) {
                if (filelist[i].contains(".lic")){
                    File readfile = new File(licpath + filelist[i]);
                    if (readfile.isFile()) {
                        String liccontent = FileUtil.readFileToString(readfile);
                        String decriptliccontent = Encrpt.DecriptWithRSA_Pub(liccontent,pubkpath);
                        HashMap<String, String> props = genDataFromArrayByte(decriptliccontent.getBytes());
                        String licenseid = props.get("LICENSEID");
                        String licensename= props.get("LICENSENAME");
                        String licensetype = props.get("LICENSETYPE");
                        String liclimit = props.get("EXPIREDAY");
                        String machinecode = props.get("MACHINECODE");
                        String lincensesign = props.get("LICENSESIGN");
                        //验证签名
                        String allinfogroup = "LICENSEID="+licenseid+"yblog"+"LICENSENAME="+licensename+"yblog"+
                                "LICENSETYPE="+licensetype+"yblog"+"EXPIREDAY="+liclimit+"yblog"+"MACHINECODE="+machinecode+"yblogyblog";
                        if (lincensesign.equals(Encrpt.GetMD5Code(allinfogroup))){
                            //验证机器码
                            if (getMachineCode().equals(machinecode)){
                                SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
                                Date bt=new Date();
                                Date et=sdf.parse(liclimit);
                                //验证时间
                                if(bt.compareTo(et)<=0){
                                    isauth = true;
                                    System.out.println("注册文件:"+filelist[i]+",已通过验证");
                                    break;
                                }else{
                                    System.out.println("证书过期");
                                }
                            }else{
                                System.out.println("机器码不一致");
                            }
                        }else{
                            System.out.println("签名不一致");
                        }
                    }
                }
            }
        }else{
            System.out.println("未上传证书");
        }
        return isauth;
    }

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/164390.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • velocity调用java静态方法_java模板引擎

    velocity调用java静态方法_java模板引擎跟学习其它技术一样,首先到官网去下载必要的包,下载地址:http://velocity.apache.org/download.cgi目前使用的是velocity1.6.3,由于自己的E文水平一般,在使用之前也到网上搜索了相关文章,然后根据前辈们的指导和自己的实践结合.记录下此文,以便以后能快速回忆.一、在eclipse中新建一个工程,把包velocity-1.6.3.jar到在WEB-INF…

    2022年10月20日
    2
  • 让未登录的用户跳转到登录页面_网页登录后又跳转登录页面

    让未登录的用户跳转到登录页面_网页登录后又跳转登录页面开发使用的是SpringBoot和Shiro,然后遇到了这个问题,记录一哈。1.处理ajax异步请求:如果不想每个ajax都判断返回数据,然后进行未登录跳转的话,可以修改JQuery的默认设置(c

    2022年8月3日
    16
  • 中兴B760换中兴B860_中兴机顶盒B860没有无线网络

    中兴B760换中兴B860_中兴机顶盒B860没有无线网络开启adb方式:在主页长按5s以上返回,松开后接着按左键就会弹出adb打开界面,有的是会显示二维码,打开wifi:在设置界面连续按左键10次,就会叫你输入密码,一般是10086(当地联系移动的电话号码)。就可以了……

    2025年8月21日
    3
  • 什么是 Promethues | 普罗米修斯( 集群监控系统 )

    什么是 Promethues | 普罗米修斯( 集群监控系统 )Promethues监控系统Prometheus是个啥Prometheus是由SoundCloud开发的开源监控报警系统和时序列数据库(TSDB)。Prometheus使用Go语言开发,是GoogleBorgMon监控系统的开源版本。监控系统什么是监控系统1、监控系统在这里特指对数据中心的监控,主要针对数据中心内的硬件和软件进行监控和告警2、随着技术不断迭代,越来越复杂的数据中心环境对监控系统提出了更越来越高的要求:需要监控不同的对象,例如容器,分布式存储,SDN网络,分布式系统

    2022年7月19日
    25
  • bootefi分多大合适_华硕secure boot在哪

    bootefi分多大合适_华硕secure boot在哪一、DM36X的BOOT过程介绍DM36x的BOOT过程和DM6446、DM6467完全是一样的,因为都是ARM926EJS架构,里边都有一个RBL,这RBL在芯片出厂的时候都烧写在ROM里,芯片上电复位后RBL在运行,然后读取BOOTMODE引脚的电平状态,决定是从NANDFLASH还是从MMC/SD、UART、USB、SPI、EMAC、HPI中之一的方式BOOT,具体见SPRS

    2022年8月13日
    11
  • URL转发基础!_URL怎么用

    URL转发基础!_URL怎么用 1、什么是URL转发?所谓URL转发是当你访问一个域名时,将会自动跳转到您所指定的另一个网络地址(URL)。假设abc.com是您要访问的域名,则通过URL转发服务可以实现当访问http://www.abc.com时,自动转向访问另外一个URL,如:http://www.otherdomain.com/somedir/other.htm。URL转发服务尤其对于拥有一个主网站并同时拥有多个域

    2022年10月10日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号