搜索词>>base64解码 耗时0.0040
  • Base64编码和解码_java8编程Base64编码和解码API使用

    Base64编码和解码_java8编程Base64编码和解码API使用Base64编码和解码_java8编程Base64编码和解码API使用
  • Java编程中base64图片与文件图片的相互转化工具

    Java编程中处理图片文件与base64串的图片相互转化工具类,方便在编程中处理前端传递过来的base64图片。1.依赖包,maven引入 <pre> <code class="language-xml"> <!--Base64Encoder等工具类 --> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.10</version> </dependency> <!--/Base64Encoder等工具类 --></code></pre> 2.Java编程代码: <pre> <code class="language-java">package com.leftso.common; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import javax.imageio.ImageIO; import org.apache.commons.codec.binary.Base64; /** * 图片与base64编码的互转工具 * * @author leftso * */ public class ImageBase64Util { public static void main(String[] args) { try { File image = new File("C:\\Users\\fghfghdf\\Desktop\\temp\\2.png"); String imageStr = image2Base64(new FileInputStream(image)); System.out.println(imageStr); File out = new File("C:\\Users\\fghfghdf\\Desktop\\temp\\3.png"); base642Image(imageStr, new FileOutputStream(out)); } catch (Exception e) { e.printStackTrace(); } } /** * 图片文件转换为base64编码的串 * * @param imageFileInputStream * 图片文件输入流 * @return 编码后的base64串 * @throws IOException * 可能出现IO异常 */ public static String image2Base64(InputStream imageFileInputStream) throws IOException { byte[] data = new byte[imageFileInputStream.available()]; imageFileInputStream.read(data); imageFileInputStream.close(); Base64 base64 = new Base64(); return base64.encodeAsString(data); } /** * base64串转换为图片文件 * * @param base64Image * 图片base64串 * @param outputStream * 输出流 * @throws IOException * 可能出现IO异常 */ public static void base642Image(String base64Image, OutputStream outputStream) throws IOException { Base64 base64 = new Base64(); // 解码 byte[] imageArr = base64.decode(base64Image); InputStream sbs = new ByteArrayInputStream(imageArr); BufferedImage bufferImg = ImageIO.read(sbs); ImageIO.write(bufferImg, "PNG", outputStream); } } </code></pre> <br /> <strong><span style="color:#FF0000">注意<br /> 前端传递过来的图片,一般会有一个前缀,如下<br /> "data:image/jpeg;base64," <br /> 解码之前去掉,否则错误。</span></strong><br />  
  • powerdesigner16.5 x64破解文件/64位补丁_powerdesigner16 64位下载_ powerdesigner16 64bit下载

    powerdesigner16.5X64破解文件,powerdesigner16 64位下载powerdesigner16 64bit下载,powerdesigner16 64位补丁PowerDesigner是一款功能非常强大的建模工具软件powerdesigner16.5X64破解文件,powerdesigner16 64位下载powerdesigner16 64bit下载,powerdesigner16 64位补丁PowerDesigner是一款功能非常强大的建模工具软件,足以与Rose比肩,同样是当今最著名的建模软件之一。Rose是专攻UML对象模型的建模工具,之后才向数据库建模发展,而PowerDesigner则与其正好相反,它是以数据库建模起家,后来才发展为一款综合全面的Case工具。PowerDesigner主要分为7种建模文件:1.  概念数据模型 (CDM)对数据和信息进行建模,利用实体-关系图(E-R图)的形式组织数据,检验数据设计的有效性和合理性。2.  逻辑数据模型 (LDM)PowerDesigner 15 新增的模型。逻辑模型是概念模型的延伸,表示概念之间的逻辑次序,是一个属于方法层次的模型。具体来说,逻辑模型中一方面显示了实体、实体的属性和实体之间的关系,另一方面又将继承、实体关系中的引用等在实体的属性中进行展示。逻辑模型介于概念模型和物理模型之间,具有物理模型方面的特性,在概念模型中的多对多关系,在逻辑模型中将会以增加中间实体的一对多关系的方式来实现。逻辑模型主要是使得整个概念模型更易于理解,同时又不依赖于具体的数据库实现,使用逻辑模型可以生成针对具体数据库管理系统的物理模型。逻辑模型并不是在整个步骤中必须的,可以直接通过概念模型来生成物理模型。3.  物理数据模型 (PDM)基于特定DBMS,在概念数据模型、逻辑数据模型的基础上进行设计。由物理数据模型生成数据库,或对数据库进行逆向工程得到物理数据模型。4.  面向对象模型 (OOM)包含UML常见的所有的图形:类图、对象图、包图、用例图、时序图、协作图、交互图、活动图、状态图、组件图、复合结构图、部署图(配置图)。OOM 本质上是软件系统的一个静态的概念模型。5.  业务程序模型 (BPM)BPM 描述业务的各种不同内在任务和内在流程,而且客户如何以这些任务和流程互相影响。 BPM 是从业务合伙人的观点来看业务逻辑和规则的概念模型,使用一个图表描述程序,流程,信息和合作协议之间的交互作用。6.  信息流模型(ILM)ILM是一个高层的信息流模型,主要用于分布式数据库之间的数据复制。7.  企业架构模型(EAM):从业务层、应用层以及技术层的对企业的体系架构进行全方面的描述。包括:组织结构图、业务通信图、进程图、城市规划图、应用架构图、面向服务图、技术基础框架图。正所谓“工欲善其事必先利其器”,PowerDesigner就是一把强大的“神器”,若能运用自如,再身怀“绝世武功”,那你基本就遇神杀神遇佛杀佛了!PowerDesigner 16.5 64/32补丁下载PowerDesigner 16.5 64位程序下载
  • java编程之java jwt token什么是JWT?(一)

    本文讲解什么是JWT,JWT的构成和JWT算法?,Java编程,JWT<h2>一、什么是JWT?了解JWT,认知JWT</h2>   首先jwt其实是三个英语单词JSON Web Token的缩写。通过全名你可能就有一个基本的认知了。token一般都是用来认证的,比如我们系统中常用的用户登录token可以用来认证该用户是否登录。jwt也是经常作为一种安全的token使用。<br /> <br /> <strong>JWT的定义:</strong><br />   JWT是一种用于双方之间传递安全信息的简洁的、URL安全的表述性声明规范。JWT作为一个开放的标准(RFC 7519),定义了一种简洁的,自包含的方法用于通信双方之间以Json对象的形式安全的传递信息。因为数字签名的存在,这些信息是可信的,JWT可以使用HMAC算法或者是RSA的公私秘钥对进行签名。<br /> <strong>JWT特点:</strong> <ul> <li> <p><strong>简洁(Compact)</strong>: 可以通过URL,POST参数或者在HTTP header发送,因为数据量小,传输速度也很快</p> </li> <li> <p><strong>自包含(Self-contained)</strong>:负载中包含了所有用户所需要的信息,避免了多次查询数据库</p> </li> </ul> <h2>二、JWT构成或者说JWT是什么样的?</h2> <strong>2.1.JWT结构</strong><br /> JWT主要包含三个部分之间用英语句号'.'隔开 <ol> <li>Header 头部</li> <li>Payload 负载</li> <li>Signature 签名</li> </ol> <strong>注意,顺序是 header.payload.signature</strong><br /> 最终的结构有点像这样: <pre> <code>leftso.com.blog </code></pre> 当然真实的jwt不可能是这么简单的明文<br /> <br /> <strong>2.2.JWT的头部(Header)</strong><br /> 在header中通常包含了两部分:token类型和采用的加密算法。如下: <pre> <code class="language-json">{ "alg": "HS256", "typ": "JWT" } </code></pre> 上面的JSON内容指定了当前采用的加密方式为HS256,token的类型为jwt<br /> <br /> 将上面的内容进行base64编码,可以得到我们JWT的头部,编码后如下:<br /> (本站提供了在线的base64编码/解码的工具,可供读者测试) <pre> <code>ewogICJhbGciOiAiSFMyNTYiLAogICJ0eXAiOiAiSldUIgp9ICA=</code></pre> <br /> <strong>2.3.JWT的负载(Payload)</strong><br /> 负载(Payload)为JWT的第二部分。JWT的标准所定义了一下几个基本字段 <ol> <li><code>iss</code>: 该JWT的签发者</li> <li><code>sub</code>: 该JWT所面向的用户</li> <li><code>aud</code>: 接收该JWT的一方</li> <li><code>exp</code>(expires): 什么时候过期,这里是一个Unix时间戳</li> <li><code>iat</code>(issued at): 在什么时候签发的</li> </ol> <br /> 除了标准定义的字段外,我们还要定义一些我们在业务处理中需要用到的字段,例如用户token一般可以包含用户登录的token或者用户的id,一个简单的例子如下: <pre> <code class="language-json">{ "iss": "Lefto.com", "iat": 1500218077, "exp": 1500218077, "aud": "www.leftso.com", "sub": "leftso@qq.com", "user_id": "dc2c4eefe2d141490b6ca612e252f92e", "user_token": "09f7f25cdb003699cee05759e7934fb2" }</code></pre> 上面的user_id、user_token都是我们自己定义的字段<br /> <br /> 现在我们需要将负载这整个部分进行base64编码,编码后结果如下: <pre> <code>ewogICAgImlzcyI6ICJMZWZ0by5jb20iLAogICAgImlhdCI6IDE1MDAyMTgwNzcsCiAgICAiZXhwIjogMTUwMDIxODA3NywKICAgICJhdWQiOiAid3d3LmxlZnRzby5jb20iLAogICAgInN1YiI6ICJsZWZ0c29AcXEuY29tIiwKICAgICJ1c2VyX2lkIjogImRjMmM0ZWVmZTJkMTQxNDkwYjZjYTYxMmUyNTJmOTJlIiwKICAgICJ1c2VyX3Rva2VuIjogIjA5ZjdmMjVjZGIwMDM2OTljZWUwNTc1OWU3OTM0ZmIyIgp9</code></pre> <br /> <strong>2.4.</strong><strong>Signature(签名)</strong><br /> 签名其实是对JWT的头部和负载整合的一个签名验证<br /> 首先需要将头部和负载通过.链接起来就像这样:header.Payload,上述的例子链接起来之后就是这样的: <pre> <code>ewogICJhbGciOiAiSFMyNTYiLAogICJ0eXAiOiAiSldUIgp9ICA=.ewogICAgImlzcyI6ICJMZWZ0by5jb20iLAogICAgImlhdCI6IDE1MDAyMTgwNzcsCiAgICAiZXhwIjogMTUwMDIxODA3NywKICAgICJhdWQiOiAid3d3LmxlZnRzby5jb20iLAogICAgInN1YiI6ICJsZWZ0c29AcXEuY29tIiwKICAgICJ1c2VyX2lkIjogImRjMmM0ZWVmZTJkMTQxNDkwYjZjYTYxMmUyNTJmOTJlIiwKICAgICJ1c2VyX3Rva2VuIjogIjA5ZjdmMjVjZGIwMDM2OTljZWUwNTc1OWU3OTM0ZmIyIgp9</code></pre> <br /> 由于HMacSHA256加密算法需要一个key,我们这里key暂时用leftso吧<br /> <br /> 加密后的内容为: <pre> <code>686855c578362e762248f22e2cc1213dc7a6aff8ebda52247780eb6b5ae91877</code></pre> <br /> 其实加密的内容也就是JWT的签名,类似我们对某个文件进行MD5加密然后接收到文件进行md5对比一样.只是这里的HMacSHA256算法需要一个key,当然这个key应该是使用者和接收者都知道的。<br /> <br /> 对上面的签名内容进行base64编码得到最终的签名 <pre> <code>Njg2ODU1YzU3ODM2MmU3NjIyNDhmMjJlMmNjMTIxM2RjN2E2YWZmOGViZGE1MjI0Nzc4MGViNmI1YWU5MTg3Nw==</code></pre> <br /> <strong>2.5最终的JWT</strong> <pre> <code>ewogICJhbGciOiAiSFMyNTYiLAogICJ0eXAiOiAiSldUIgp9ICA=.ewogICAgImlzcyI6ICJMZWZ0by5jb20iLAogICAgImlhdCI6IDE1MDAyMTgwNzcsCiAgICAiZXhwIjogMTUwMDIxODA3NywKICAgICJhdWQiOiAid3d3LmxlZnRzby5jb20iLAogICAgInN1YiI6ICJsZWZ0c29AcXEuY29tIiwKICAgICJ1c2VyX2lkIjogImRjMmM0ZWVmZTJkMTQxNDkwYjZjYTYxMmUyNTJmOTJlIiwKICAgICJ1c2VyX3Rva2VuIjogIjA5ZjdmMjVjZGIwMDM2OTljZWUwNTc1OWU3OTM0ZmIyIgp9.Njg2ODU1YzU3ODM2MmU3NjIyNDhmMjJlMmNjMTIxM2RjN2E2YWZmOGViZGE1MjI0Nzc4MGViNmI1YWU5MTg3Nw==</code></pre> <br /> 通过上面的一个简单的说明您是否对JWT有一个简单额认知了呢?接下来我将讲解JWT在Java编程中的使用<br /> <br /> 未完待续中...<br /> <br />  
  • Office 2016 64位/32位官方原版免费下载

    office 2016 64位/32位官方原版免费下载,这里提供Microsoft office 2016 官方原版下载。office 2016官方原版下载
  • yum安装jdk1.8-CentOS6.5

    yum安装jdk1.8-CentOS6.5,centos6,jdk8<h2 style="text-align:left">一、yum<span style="font-family:宋体">安装</span>jdk8</h2> <h3>1.1<span style="font-family:宋体">查看当前可以安装的版本</span></h3> <p><span style="font-family:宋体">命令</span>:</p> <p>[root@localhost ~]# yum list|grep jdk</p> <p>copy-jdk-configs.noarch                      1.3-1.el6                   base  </p> <p>java-1.6.0-openjdk.x86_64                    1:1.6.0.41-1.13.13.1.el6_8  base  </p> <p>java-1.6.0-openjdk-demo.x86_64               1:1.6.0.41-1.13.13.1.el6_8  base  </p> <p>java-1.6.0-openjdk-devel.x86_64              1:1.6.0.41-1.13.13.1.el6_8  base  </p> <p>java-1.6.0-openjdk-javadoc.x86_64            1:1.6.0.41-1.13.13.1.el6_8  base  </p> <p>java-1.6.0-openjdk-src.x86_64                1:1.6.0.41-1.13.13.1.el6_8  base  </p> <p>java-1.7.0-openjdk.x86_64                    1:1.7.0.141-2.6.10.1.el6_9  updates</p> <p>java-1.7.0-openjdk-demo.x86_64               1:1.7.0.141-2.6.10.1.el6_9  updates</p> <p>java-1.7.0-openjdk-devel.x86_64              1:1.7.0.141-2.6.10.1.el6_9  updates</p> <p>java-1.7.0-openjdk-javadoc.noarch            1:1.7.0.141-2.6.10.1.el6_9  updates</p> <p>java-1.7.0-openjdk-src.x86_64                1:1.7.0.141-2.6.10.1.el6_9  updates</p> <p>java-1.8.0-openjdk.x86_64                    1:1.8.0.131-0.b11.el6_9     updates</p> <p>java-1.8.0-openjdk-debug.x86_64              1:1.8.0.131-0.b11.el6_9     updates</p> <p>java-1.8.0-openjdk-demo.x86_64               1:1.8.0.131-0.b11.el6_9     updates</p> <p>java-1.8.0-openjdk-demo-debug.x86_64         1:1.8.0.131-0.b11.el6_9     updates</p> <p>java-1.8.0-openjdk-devel.x86_64              1:1.8.0.131-0.b11.el6_9     updates</p> <p>java-1.8.0-openjdk-devel-debug.x86_64        1:1.8.0.131-0.b11.el6_9     updates</p> <p>java-1.8.0-openjdk-headless.x86_64           1:1.8.0.131-0.b11.el6_9     updates</p> <p>java-1.8.0-openjdk-headless-debug.x86_64     1:1.8.0.131-0.b11.el6_9     updates</p> <p>java-1.8.0-openjdk-javadoc.noarch            1:1.8.0.131-0.b11.el6_9     updates</p> <p>java-1.8.0-openjdk-javadoc-debug.noarch      1:1.8.0.131-0.b11.el6_9     updates</p> <p>java-1.8.0-openjdk-src.x86_64                1:1.8.0.131-0.b11.el6_9     updates</p> <p>java-1.8.0-openjdk-src-debug.x86_64          1:1.8.0.131-0.b11.el6_9     updates</p> <p>ldapjdk.x86_64                               4.18-8.el6                  base  </p> <p>ldapjdk-javadoc.x86_64                       4.18-8.el6                  base</p> <p> </p> <p><span style="font-family:宋体">如果没有看到上面的版本,安装</span>/<span style="font-family:宋体">更新</span>centos<span style="font-family:宋体">的扩展源</span></p> <pre> <code>#yum –y  install epel-release</code></pre> <h3>1.2<span style="font-family:宋体">安装</span>jdk1.8</h3> <p><span style="font-family:宋体">命令:</span></p> <pre> <code>[root@localhost ~]# yum install -y java-1.8.0-openjdk</code></pre> <p><img alt="可用jdk版本" class="img-thumbnail" src="/assist/images/blog/12c8939452534207b9857a8d40bb48c9.png" /></p> <h2>二、<span style="font-family:宋体">检查安装</span></h2> <p><span style="font-family:宋体">命令</span>:</p> <pre> <code>[root@localhost ~]# java –version openjdk version "1.8.0_131" OpenJDK Runtime Environment (build 1.8.0_131-b11) OpenJDK 64-Bit Server VM (build 25.131-b11, mixed mode)</code></pre> <p> </p> <p><em><span style="font-family:宋体">如上显示出</span>jdk</em><em><span style="font-family:宋体">版本标示已经成功安装</span></em></p>
  • java处理RSA非对称加解密

    java处理RSA非对称加解密 <pre> <code class="language-java">package org.xqlee.utils.security; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.security.InvalidKeyException; import java.security.Key; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import org.apache.commons.codec.binary.Base64; /** * * * <pre> * _________________________INFO_____________________________ * | Description : [RAS加密/解密工具类|其他说明,非对称加密速度非常慢,内容过大一般使用对称加密,然后对对称加密的密文进行非对称加密] * | Encoding : [UTF-8] * | Package : [org.xqlee.utils.security] * | Project : [utils] * | Author : [LXQ] * | CreateDate : [] * | Updater : [] * | UpdateDate : [] * | UpdateRemark: [] * | Company : [www.zhljc.com] * | Version : [v 1.0] * | Libs : [commons-codec-1.x.jar] * __________________________________________________________ * </pre> */ public class RSAUtil { /** 换行符 **/ private final static String lineSeparator = System.getProperty("line.separator", "\n"); /** 加解密算法键值-这里RSA **/ private final static String KEY_ALGORITHM = "RSA"; /** 获取公钥的KEY **/ public final static String PUBLIC_KEY = "RSAPublicKey"; /** 获取私钥的KEY **/ public final static String PRIVATE_KEY = "RSAPrivateKey"; /** * 生成RSA算法的密钥对 * * @return 密钥对,Map-> key=RSAPublicKey|KEY=RSAPrivateKey * @throws NoSuchAlgorithmException * 获取密钥对可能发生的异常 */ public static Map<String, Object> genKeyPair() throws NoSuchAlgorithmException { KeyPairGenerator kGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM); // init the keyPair KeyPair keyPair = kGenerator.generateKeyPair(); // get public key RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // get private key RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); Map<String, Object> keys = new HashMap<String, Object>(); keys.put(PUBLIC_KEY, publicKey); keys.put(PRIVATE_KEY, privateKey); return keys; } /** * 加密 * * @param key * 加密使用的[公钥/私钥] * @param input * 需要加密的明文 * @return 加密后的密文 * @throws Exception * 加密过程中可能发生的异常 */ public static byte[] encrypt(Key key, byte[] input) throws Exception { if (key != null) { // Cipher负责完成加密或解密工作,基于RSA Cipher cipher; try { cipher = Cipher.getInstance(KEY_ALGORITHM); // 根据公钥,对Cipher对象进行初始化 cipher.init(Cipher.ENCRYPT_MODE, key); byte[] resultBytes = cipher.doFinal(input); return resultBytes; } catch (NoSuchAlgorithmException e) { throw new Exception("无此解密算法:" + e.getMessage()); } catch (NoSuchPaddingException e) { throw new Exception("加密过程中发生异常:" + e.getMessage()); } catch (InvalidKeyException e) { throw new Exception("解密私钥非法,请检查:" + e.getMessage()); } catch (IllegalBlockSizeException e) { throw new Exception("密文长度非法:" + e.getMessage()); } catch (BadPaddingException e) { throw new Exception("密文数据已损坏:" + e.getMessage()); } } else { throw new Exception("解密私钥为空, 请设置"); } } /** * 解密 * * @param key * 对应解密的[公钥或私钥] * @param input * 需要解密的加密信息 * @return 解密后的明文信息 * @throws Exception * 解密过程中可能发生的异常 */ public static byte[] decrypt(Key key, byte[] input) throws Exception { if (key == null) { throw new Exception("解密私钥为空, 请设置"); } Cipher cipher = null; try { // Cipher负责完成加密或解密工作,基于RSA cipher = Cipher.getInstance(KEY_ALGORITHM); // 根据私钥,对Cipher对象进行初始化 cipher.init(Cipher.DECRYPT_MODE, key); byte[] output = cipher.doFinal(input); return output; } catch (NoSuchAlgorithmException e) { throw new Exception("无此解密算法:" + e.getMessage()); } catch (NoSuchPaddingException e) { throw new Exception("解密过程中发生异常:" + e.getMessage()); } catch (InvalidKeyException e) { throw new Exception("解密私钥非法,请检查:" + e.getMessage()); } catch (IllegalBlockSizeException e) { throw new Exception("密文长度非法:" + e.getMessage()); } catch (BadPaddingException e) { throw new Exception("密文数据已损坏:" + e.getMessage()); } } /** * 通过文件获取私钥对象 * * @param file * 私钥文件 * @return 私钥对象 * @throws Exception * 从文件私钥获取私钥Java对象过程中可能发生的异常 */ public static PrivateKey getPrivateKey(File file) throws Exception { String strPrivateKey = null; try { BufferedReader br = new BufferedReader(new FileReader(file)); String readLine = null; StringBuilder sb = new StringBuilder(); while ((readLine = br.readLine()) != null) { sb.append(readLine); sb.append(lineSeparator); } br.close(); // 字符 strPrivateKey = sb.toString().substring(0, sb.toString().length() - lineSeparator.length()); } catch (IOException e) { throw new Exception("私钥数据流读取错误:" + e.getMessage()); } try { byte[] buffer = Base64.decodeBase64(strPrivateKey.getBytes()); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); return keyFactory.generatePrivate(keySpec); } catch (NoSuchAlgorithmException e) { throw new Exception("=====无此算法====="); } catch (InvalidKeySpecException e) { throw new Exception("=====密钥非法====="); } catch (NullPointerException e) { throw new Exception("=====私钥数据为空====="); } } /** * 通过字符串获取私钥对象 * * @param strPrivateKey * 字符串的私钥 * @return 私钥对象 * @throws Exception * 从字符串私钥获取私钥Java对象过程中可能发生的异常 */ public static PrivateKey getPrivateKey(String strPrivateKey) throws Exception { try { byte[] buffer = Base64.decodeBase64(strPrivateKey.getBytes()); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); return keyFactory.generatePrivate(keySpec); } catch (NoSuchAlgorithmException e) { throw new Exception("=====无此算法====="); } catch (InvalidKeySpecException e) { throw new Exception("=====密钥非法====="); } catch (NullPointerException e) { throw new Exception("=====私钥数据为空====="); } } /** * 从公钥文件中加载获取公钥Java对象 * * @param file * 公钥文件 * @return Java公钥对象 * @throws Exception * 获取过程中可能发生的异常 */ public static PublicKey getPublicKey(File file) throws Exception { String strRSAPublicKey = null; try { BufferedReader br = new BufferedReader(new FileReader(file)); String readLine = null; StringBuilder sb = new StringBuilder(); while ((readLine = br.readLine()) != null) { sb.append(readLine); sb.append(lineSeparator); } br.close(); strRSAPublicKey = sb.toString().substring(0, sb.toString().length() - lineSeparator.length()); } catch (IOException e) { throw new Exception("公钥数据流读取错误"); } catch (NullPointerException e) { throw new Exception("公钥输入流为空"); } try { byte[] buffer = Base64.decodeBase64(strRSAPublicKey.getBytes()); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer); return keyFactory.generatePublic(keySpec); } catch (NoSuchAlgorithmException e) { throw new Exception("=====无此算法====="); } catch (InvalidKeySpecException e) { throw new Exception("=====公钥非法====="); } catch (NullPointerException e) { throw new Exception("=====公钥数据为空====="); } } /** * 从公钥字符串加载获取公钥Java对象 * * @param strPublicKey * 公钥字符串 * @return Java公钥对象 * @throws Exception * 获取过程中可能发生的异常 */ public static PublicKey getPublicKey(String strPublicKey) throws Exception { try { byte[] buffer = Base64.decodeBase64(strPublicKey.getBytes()); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer); return keyFactory.generatePublic(keySpec); } catch (NoSuchAlgorithmException e) { throw new Exception("=====无此算法====="); } catch (InvalidKeySpecException e) { throw new Exception("=====公钥非法====="); } catch (NullPointerException e) { throw new Exception("=====公钥数据为空====="); } } /** * 将Java对象的公钥或者私钥转换为字符串 * * @param key * 公钥/私钥 * @return 秘钥的字符串 */ public static String key2String(Key key) { byte[] keyBytes = key.getEncoded(); String result = new String(Base64.encodeBase64(keyBytes)); return result; } } </code></pre>  
  • Spring boot hessian 通讯加密验证

    Spring boot hessian 通讯加密,Spring boot hessian RPC框架通讯之间的加密验证。实现安全的RPC访问<h2>引言</h2>     前面写了一篇<a rel="" target="_blank"href="http://www.leftso.com/blog/294.html" rel="" target="_blank" title="spring boot RPC 框架 Hessian">Spring boot RPC 框架 Hessian</a>。讲解了spring boot整合hessian的基本使用。这里主要围绕上一篇讲解的内容进行扩展讲解,hessian通讯的验证/加密实现安全的RPC访问。 <h2>一.自定义一个HessianServiceExporter</h2>     从上一篇博客<a rel="" target="_blank"href="http://www.leftso.com/blog/294.html" rel="" target="_blank" title="spring boot RPC 框架 Hessian">Spring boot RPC 框架 Hessian</a>中我们可以发现,hessian的server端是通过HessianServiceExporter发布hessian接口服务的。<br />     <br /> 目前hessian的server端项目结构图:<br /> <img alt="项目结构图" class="img-thumbnail" src="/assist/images/blog/4d20852096264d59b39b1dada4f5ba62.png" /><br /> 与上一篇对比,项目结构中多了一个类HessianServerProxyExporter。这个类主要是继承了HessianServiceExporter类并重写了handleRequest方法: <pre> <code class="language-java">package net.xqlee.project; import java.io.IOException; import java.util.Base64; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.remoting.caucho.HessianServiceExporter; import org.springframework.util.StringUtils; import org.springframework.web.util.NestedServletException; /** * 自定义hessian服务发布,可用于自定义验证服务 * * @author xqlee * */ public class HessianServerProxyExporter extends HessianServiceExporter { private static final Logger log = LoggerFactory.getLogger(HessianServerProxyExporter.class); @Override public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String authorization = request.getHeader("authorization"); if (StringUtils.isEmpty(authorization)) { throw new NestedServletException("Auth Is Empty!"); } log.info(authorization); String[] authArr = authorization.trim().split(" "); String auth = authArr[1]; auth = new String(Base64.getDecoder().decode(auth)); String[] namePwdArr = auth.split(":"); String pwd = namePwdArr[1]; // 验证密码 if (!"123456".equals(pwd)) { throw new NestedServletException("Auth Fail!"); } super.handleRequest(request, response); } } </code></pre> 验证的核心代码就在重写的方法里面,这里只是简单的进行了密码的认证。<br /> <br /> 为了使验证生效,我们需要重写类DemoSpringbootRpcHessianApplication: <pre> <code class="language-java">package net.xqlee.project; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.remoting.caucho.HessianServiceExporter; import net.xqlee.project.service.HelloWorldService; @SpringBootApplication public class DemoSpringbootRpcHessianApplication { @Autowired private HelloWorldService helloWorldService; public static void main(String[] args) { SpringApplication.run(DemoSpringbootRpcHessianApplication.class, args); } // 发布服务 @Bean(name = "/HelloWorldService") public HessianServiceExporter accountService() { // HessianServiceExporter exporter = new HessianServiceExporter(); HessianServerProxyExporter exporter=new HessianServerProxyExporter(); exporter.setService(helloWorldService); exporter.setServiceInterface(HelloWorldService.class); return exporter; } } </code></pre> 可以看到只是进行了简单修改,使用我们自己定义的HessianServerProxyExporter 来发布hessian服务,而不是默认的HessianServiceExporter。 <h2>二.hessian客户端设置用户密码</h2> 客户端的项目结构图没变,如下:<br /> <img alt="项目结构图" class="img-thumbnail" src="/assist/images/blog/f10a8296447a4a95996ff163b14e22e9.png" /><br /> 客户端比之前只是在访问hessian接口的时候多设置了用户名和密码: <pre> <code class="language-java">package net.xqlee.project; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.remoting.caucho.HessianProxyFactoryBean; import net.xqlee.project.service.HelloWorldService; @SpringBootApplication public class DemoSpringbootRpcHessianClientApplication { public static void main(String[] args) { SpringApplication.run(DemoSpringbootRpcHessianClientApplication.class, args); } @Bean public HessianProxyFactoryBean helloClient() { HessianProxyFactoryBean factory = new HessianProxyFactoryBean(); factory.setServiceUrl("http://localhost:8083/HelloWorldService"); factory.setServiceInterface(HelloWorldService.class); factory.setPassword("123456"); factory.setUsername("download"); return factory; } } </code></pre> <span style="color:#ff0000"><span style="background-color:#ffff00">注意:HessianProxyFactoryBean中必须同时设置用户名和密码才能生效。</span></span><br /> <br /> 通过访问客户端的服务,通过断点到hessian的服务端HessianServerProxyExporter类,我们可以看到是如何传递用户名和密码参数的:<br /> <img alt="hessian传递认证信息" class="img-thumbnail" src="/assist/images/blog/3b8f60ff3153416fbe45c618a0e7f319.png" /><br /> 可以看到传递到服务端是通过HTTP协议的header传递的。并且传递的Basic认证头。这个头后面跟的字符串就是用户名:密码的Base64字符串,通过base64解密我们可以得到:<br /> <img alt="base64解密" class="img-thumbnail" src="/assist/images/blog/17312f236a3d454bac688634453d200e.png" /><br /> 用户名:密码已经显示出来。同样后面的判断也能实现我们的通讯验证。<br /> <br /> <br /> <strong>提示:<br /> 实际使用中,传递的密码或者用户请通过其他非对称加密方式加密后传输,服务端进行解密更为安全。</strong><br /> <br /> <br /> <br />  
  • eclipse如何关闭java代码中某些部分/片段代码不被格式化

    eclipse如何关闭java代码中某些部分/片段代码不被格式化,eclipse,代码部分不被格式化,How to turn off the Eclipse code formatter for certain sections of Java code?eclipse如何关闭java代码中某些部分/片段代码不被格式化,eclipse,代码部分不被格式化,<br /> How to turn off the Eclipse code formatter for certain sections of Java code?<br /> <br /> 1.设置eclipse开启Off/On tags<br /> <br /> 依次点击菜单<br /> preferences->Java->Code Style->Formatter<br /> 点击Edit<br /> <img alt="1" class="img-thumbnail" src="/assist/images/blog/d2fc6ee509064f309342ae36d146bb42.png" /><br /> <br /> 找到tag,点击enable Off/On tags<br /> <img alt="2" class="img-thumbnail" src="/assist/images/blog/44a828ea10834828a6587602e9e42c03.png" /><br /> <br /> <br /> 在不想被格式化的代码之间添加以下注释标签即可<br />   <pre> <code class="language-java">import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import org.springframework.util.Base64Utils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import com.alibaba.fastjson.JSONObject; import com.cqax.axschoolweb2.common.pojo.Result; /** * 验证码公用处理类 * * @author xq * */ @RestController public class ValidationCodeController { //@formatter:off /** * * @api {get} /apis/validation/getcode.json 获取验证码 * * @apiName GetValidateCode * * @apiGroup Validation * * @apiParam {String} [timeStamp] 时间戳 * * @apiSuccessExample {String} 返回值: * { "id": "1be34f4a324c4123b0325ecf0593d70e", "data": { "image": "iVBORwCCAAAAAAAAAAAAAAAAA==" }, "code": "00000", "dateTime": "2017-05-23 14:00:23", "msg": null } * */ //@formatter:on @GetMapping("/apis/validation/getcode.json") public Result getCode() { try { InputStream is = new FileInputStream(new File("e:/2.png")); ByteArrayOutputStream bao = new ByteArrayOutputStream(); byte[] cache = new byte[4096]; while (is.read(cache) != -1) { bao.write(cache); } String rs = Base64Utils.encodeToString(bao.toByteArray()); JSONObject obj = new JSONObject(); obj.put("image", rs); is.close(); return Result.success(obj); } catch (Exception e) { return Result.fail("eeeee", "错误,异常," + e.getMessage()); } } //@formatter:off /** * @api {get} /apis/validation/compare.json 对比验证码 * * @apiName CompareValidateCode * * @apiGroup Validation * * @apiParam {String} vcode 验证码 * * @apiSuccessExample {json} 返回值: * { "id":"f47611a1a7ee4d4c8c0420a4f7e4b228", "data":{ "result":true }, "code":"00000", "dateTime":"2017-05-23 14:41:36", "msg":null } */ //@formatter:on @GetMapping("/apis/validation/compare.json") public Result compare(String vcode) { JSONObject obj = new JSONObject(); obj.put("result", true);// 对比结果 return Result.success(obj); } public Result getPhoneCode(){ JSONObject obj=new JSONObject(); return null; } } </code></pre> <br />
  • AES 使用JavaScript加密然后用Java解密

    AES 使用JavaScript加密然后用Java解密,AES代表高级加密系统,它是一种对称加密算法。很多时候我们需要在客户端加密一些明文,例如密码,并将其发送到服务器,然后服务器将其解密以进一步处理.AES加密和解密更容易在Android客户端和Java服务器等相同的平台上实现,但有时在跨平台环境(如Javascript客户端和Java Server,如Spring mvc框架)中解密AES加密密码变得非常具有挑战性,因为如果任何系统默认值不匹配解密将失败。<h2>引言</h2> <blockquote> <p style="text-align:start"><span style="font-family:Tahoma,Arial,Verdana,sans-serif">AES代表高级加密系统,它是一种对称加密算法。很多时候我们需要在客户端加密一些明文,例如密码,并将其发送到服务器,然后服务器将其解密以进一步处理.AES加密和解密更容易在Android客户端和Java服务器等相同的平台上实现,但有时在跨平台环境(如Javascript客户端和Java Server,如Spring mvc框架)中解密AES加密密码变得非常具有挑战性,因为如果任何系统默认值不匹配解密将失败。</span></p> </blockquote> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">    在本文中,我们将使用spring mvc和angular js客户端创建一个应用程序。我们将有一个带有用户名和密码的表单输入的登录页面。在将密码发送到服务器之前,密码将使用CryptoJS在JavaScript中加密,并且相同的加密密码将在java中解密,并且会进行比较以匹配密码。我们将在javascript中生成salt和IV,然后生成从密码,salt和密钥大小中使用PBKDF2函数的密钥。之后,我们将使用密钥和IV对明文进行加密,并且这些密钥将在Java中进行解密。因此,基本上我们将开发一种可与Java进行可互操作的AES加密的机制,的JavaScript。</span></span></span></p> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">    在继续进行之前,让我们明确一点,该机制仅在数据的有线传输期间(最有可能)增加了一种额外的安全性,但并未提供充分的证明安全性。如果您不使用SSL,则攻击者可以执行中间人攻击并通过为用户提供不同的密钥来窃取数据。</span></span></span></p> <h2 style="text-align:start">项目结构</h2> 我们这里有个spring  boot和angular js webapp项目。项目结构如下:<img srcset="" width="" size="" class="img-thumbnail" alt="项目结构图" src="/assist/images/blog/e0c03ca22f804d51b2ab0dbc4e93828d.png" /> <h2 style="margin-left:0px; margin-right:0px; text-align:start">JavaScript中的Aes加密</h2> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">    对于JavaScript中的AES加密,我们已经导入了两个js文件 - <code>crypto.js</code>并且<code>pbkdf2.js</code>我们有<code>AesUtil.js</code>用于执行加密和解密的通用代码。这里this.keySize是4字节块的密钥大小。因此,要使用128位密钥,我们将位数除以32得到用于CryptoJS的密钥大小。</span></span></span></p> <strong>AesUtil.js:</strong> <pre> <code class="language-javascript">var AesUtil = function(keySize, iterationCount) { this.keySize = keySize / 32; this.iterationCount = iterationCount; }; AesUtil.prototype.generateKey = function(salt, passPhrase) { var key = CryptoJS.PBKDF2( passPhrase, CryptoJS.enc.Hex.parse(salt), { keySize: this.keySize, iterations: this.iterationCount }); return key; } AesUtil.prototype.encrypt = function(salt, iv, passPhrase, plainText) { var key = this.generateKey(salt, passPhrase); var encrypted = CryptoJS.AES.encrypt( plainText, key, { iv: CryptoJS.enc.Hex.parse(iv) }); return encrypted.ciphertext.toString(CryptoJS.enc.Base64); } AesUtil.prototype.decrypt = function(salt, iv, passPhrase, cipherText) { var key = this.generateKey(salt, passPhrase); var cipherParams = CryptoJS.lib.CipherParams.create({ ciphertext: CryptoJS.enc.Base64.parse(cipherText) }); var decrypted = CryptoJS.AES.decrypt( cipherParams, key, { iv: CryptoJS.enc.Hex.parse(iv) }); return decrypted.toString(CryptoJS.enc.Utf8); }</code></pre> <h2 style="margin-left:0px; margin-right:0px; text-align:start">密码加密在JavaScript中</h2> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">    该方法<code>logMeIn()</code>将在点击提交按钮后被调用。此方法将使用定义的通用代码<code>AesUtil.js</code>对密码进行加密并使POST请求验证密码。发送的密码将采用以下格式:<code>iv::salt::ciphertext</code>在服务器端,java将解密密码并在响应中发送解密密码显示在警告框中。</span></span></span><br />  </p> <pre> <code class="language-javascript">var app = angular.module('demoApp', []); app.controller('loginController', ['$scope', '$rootScope', '$http', function ($scope, $rootScope, $http) { $scope.logMeIn = function(){ if(!$scope.userName || !$scope.password){ $scope.showMessage("Missing required fields.", false); return; } var iv = CryptoJS.lib.WordArray.random(128/8).toString(CryptoJS.enc.Hex); var salt = CryptoJS.lib.WordArray.random(128/8).toString(CryptoJS.enc.Hex); var aesUtil = new AesUtil(128, 1000); var ciphertext = aesUtil.encrypt(salt, iv, $('#key').text(), $scope.password); var aesPassword = (iv + "::" + salt + "::" + ciphertext); var password = btoa(aesPassword); var data = { userName: $scope.userName, password: password } $http.post('/login',data).then(function (response){ if(response.status === 200){ alert("Password is " + response.data.password); }else { alert("Error occurred"); } }) }; }]);</code></pre> <h2 style="margin-left:0px; margin-right:0px; text-align:start">Java中的AES解密</h2> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">首先让我们实现将拦截登录请求的控制器类。在这里,我们对密钥进行了硬编码。此密钥将由服务器唯一地生成并发送给客户端以用于每个登录请求。客户端将使用相同的密钥,而加密和服务器将使用相同的密钥进行解密。确保密钥长度为16,因为我们使用的是128位加密。请记住我们从客户端发送的加密文本的格式<code>iv::salt::ciphertext</code>。文本以相同的格式解密。我们已经有IV,盐和密文。</span></span></span><br />  </p> <pre> <code class="language-java">import com.example.demo.model.Credentials; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Map; import java.util.UUID; @Controller public class WelcomeController { private static final Logger LOGGER = LoggerFactory.getLogger(WelcomeController.class); @RequestMapping(value={"/login"},method = RequestMethod.GET) public String loginPage(HttpServletRequest request){ LOGGER.info("Received request for login page with id - " + request.getSession().getId()); String randomKey = UUID.randomUUID().toString(); //String uniqueKey = randomKey.substring(randomKey.length()-17, randomKey.length() -1); String uniqueKey = "1234567891234567"; request.getSession().setAttribute("key", uniqueKey); return "index"; } @RequestMapping(value={"/login"},method = RequestMethod.POST) public @ResponseBody ResponseEntity login(@RequestBody Credentials credentials, HttpServletRequest request) { String decryptedPassword = new String(java.util.Base64.getDecoder().decode(credentials.getPassword())); AesUtil aesUtil = new AesUtil(128, 1000); Map map = new HashMap<>(); if (decryptedPassword != null && decryptedPassword.split("::").length == 3) { LOGGER.info("Password decrypted successfully for username - " + credentials.getUserName()); String password = aesUtil.decrypt(decryptedPassword.split("::")[1], decryptedPassword.split("::")[0], "1234567891234567", decryptedPassword.split("::")[2]); map.put("password", password); } return new ResponseEntity<>(map, HttpStatus.OK); } }</code></pre> 以下是用于AES加密和解密的java util类。您可以按照<a href="https://www.javacodegeeks.com/2018/03/aes-encryption-and-decryption-in-javacbc-mode.html" rel="external nofollow" style="padding:0px; margin:0px; outline:none; list-style:none; border:0px none; color:#326693; text-decoration:none; transition:all 0.2s ease-in-out; font-family:Tahoma, Arial, Verdana, sans-serif; font-size:15px; font-style:normal; font-variant-ligatures:normal; font-variant-caps:normal; font-weight:normal; letter-spacing:normal; orphans:2; text-align:start; text-transform:none; white-space:normal; widows:2; word-spacing:0px; -webkit-text-stroke-width:0px; background-color:#ffffff" target="_blank" >java中的AES加密和解密</a>获得关于以下实现的更多详细说明。 <pre> <code class="language-java">import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Hex; import javax.crypto.*; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; import java.io.UnsupportedEncodingException; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; public class AesUtil { private final int keySize; private final int iterationCount; private final Cipher cipher; public AesUtil(int keySize, int iterationCount) { this.keySize = keySize; this.iterationCount = iterationCount; try { cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { throw fail(e); } } public String decrypt(String salt, String iv, String passphrase, String ciphertext) { try { SecretKey key = generateKey(salt, passphrase); byte[] decrypted = doFinal(Cipher.DECRYPT_MODE, key, iv, base64(ciphertext)); return new String(decrypted, "UTF-8"); } catch (UnsupportedEncodingException e) { return null; }catch (Exception e){ return null; } } private byte[] doFinal(int encryptMode, SecretKey key, String iv, byte[] bytes) { try { cipher.init(encryptMode, key, new IvParameterSpec(hex(iv))); return cipher.doFinal(bytes); } catch (InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) { return null; } } private SecretKey generateKey(String salt, String passphrase) { try { SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); KeySpec spec = new PBEKeySpec(passphrase.toCharArray(), hex(salt), iterationCount, keySize); SecretKey key = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES"); return key; } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { return null; } } public static byte[] base64(String str) { return Base64.decodeBase64(str); } public static byte[] hex(String str) { try { return Hex.decodeHex(str.toCharArray()); } catch (DecoderException e) { throw new IllegalStateException(e); } } private IllegalStateException fail(Exception e) { return null; } }</code></pre> <h2 style="margin-left:0px; margin-right:0px; text-align:start">测试AES加密和解密</h2> <code>    DemoApplication.java</code>作为Java应用程序运行,然后打到http:// localhost:8080。一旦出现登录页面,您可以输入用户名和密码,然后单击提交按钮,您可以在警报中看到解密的密码。<br /> <br /> <br /> <strong><img srcset="" width="" size="" class="img-thumbnail" alt="测试结果" src="/assist/images/blog/ac54eebc032e4d06929bb72b807b1381.png" /></strong><br />   <h2 style="margin-left:0px; margin-right:0px; text-align:start">总结</h2> <p style="text-align:start"><span style="color:#333333"><span style="font-family:Tahoma,Arial,Verdana,sans-serif"><span style="background-color:#ffffff">在这篇文章中,我们讨论了使用Java和Javascript进行可互操作的AES加密。我们使用Crypto.js库在javascript中执行此加密。</span></span></span></p> <br /> <a href="http://www.leftso.com/resource/1005.html" target="_blank" ><strong>项目源码下载</strong></a><br /> <br />