Table of Contents
概述
开发中某些数据的传输需要对数据进行加密后再进行传输,所有的数据都是用非对称加密算法可能导致性能降低,在很多场合下我们可以直接使用对称加密算法结合混淆字符串,再加以不同的迭代加密次数以达到所需的加密效果,增大恶意人员破解成本。
Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。
我们可以使用Base64算法对字符串信息进行加密,再传输到对应的服务器进行信息处理。在Web系统中,前后端分离的开发模式使用广泛,而在前后端分离的模式下,信息加密传输显得尤为重要!
这里小编为大家讲解如何使用Base64算法在前后端分离的模式下进行数据传输加解密。
以下例子使用:前端架构使用Vue 2.x,后端使用Spring boot 1.5.1,前后端分离,接口为RESUTFUL风格,根据业务再次进行封装为JSON格式进行数据传输。
特别注意:下述例子js中的Base64为一个自封装的Base64.js,Java中的Base64Util为自封装的一个Base64Util.java,具体代码见文末。
一、js加密,java解密
1、js加密
1、中文字符串加密
let str = Base64.encode('今天是个好日子');
console.log(str);
// 输出结果:5LuK5aSp5piv5Liq5aW95pel5a2Q
2、英文等字符串加密
let str = Base64.encode('Today is a good day. I have 100 yuan');
console.log(str);
// 输出结果:VG9kYXkgaXMgYSBnb29kIGRheS4gSSBoYXZlIDEwMCB5dWFu
3、中文字符串混淆、迭代加密
let str2 = Base64.encoder('今天是个好日子', '3b5E', 3);
console.log(str2);
// 输出结果:M2I1RU0ySTFSVTB5U1RGU1pWTTNhWFZYYTNGbFlWbHlLMU0wY1hWWGJIWmxZVmh3WlZkMGEwUk9hVTVWVlQwellqVkYzYjVF
4、英文等字符串混淆、迭代加密
let str = Base64.encoder('Today is a good day. I have 100 yuan', 'tom', 2);
console.log(str);
// 输出结果:dG9tZEc5dFZHOWtZWGtnYVhNZ1lTQm5iMjlrSUdSaGVTNGdTU0JvWVhabElERXdNQ0I1ZFdGdWRHOXR0b20=
5、JSON数据混淆、迭代加密
let str3 = Base64.encodeJson({a: 1, b: '今天是个好日子',c: [1,'2',true],d: {e: 'have', f: [true, false]}}, 'ars3a', 2);
console.log(str3);
// 输出结果:YXJzM2FZWEp6TTJGN0ltRWlPakVzSW1JaU9pTGt1NHJscEtubW1LL2t1S3JscGIzbWw2WGxyWkFpTENKaklqcGJNU3dpTWlJc2RISjFaVjBzSW1RaU9uc2laU0k2SW1oaGRtVWlMQ0ptSWpwYmRISjFaU3htWVd4elpWMTlmV0Z5Y3pOaGFyczNh
2、Java解密
public static void main(String[] args) {
String str = Base64Util.decode("5LuK5aSp5piv5Liq5aW95pel5a2Q");
System.out.println(str);
String str1 = Base64Util.decode("VG9kYXkgaXMgYSBnb29kIGRheS4gSSBoYXZlIDEwMCB5dWFu");
System.out.println(str1);
String str2 = Base64Util.decode("M2I1RU0ySTFSVTB5U1RGU1pWTTNhWFZYYTNGbFlWbHlLMU0wY1hWWGJIWmxZVmh3WlZkMGEwUk9hVTVWVlQwellqVkYzYjVF","3b5E", 3);
System.out.println(str2);
String str3 = Base64Util.decode("dG9tZEc5dFZHOWtZWGtnYVhNZ1lTQm5iMjlrSUdSaGVTNGdTU0JvWVhabElERXdNQ0I1ZFdGdWRHOXR0b20=","tom", 2);
System.out.println(str3);
Map<String, Object> json = Base64Util.decodeJson("YXJzM1lYSnpNM3NpWVNJNk1Td2lZaUk2SXVTN2l1V2txZWFZcitTNHF1V2x2ZWFYcGVXdGtDSXNJbU1pT2xzeExDSXlJaXgwY25WbFhTd2laQ0k2ZXlKbElqb2lhR0YyWlNJc0ltWWlPbHQwY25WbExHWmhiSE5sWFgxOVlYSnpNdz09YXJzMw==", "ars3", 2);
System.out.println(json);
}
结果如下:
二、java加密,js解密
1、Java加密
1、中文字符串加密
String str = Base64Util.encode("今天是个好日子");
System.out.println(str);
// 加密结果:5LuK5aSp5piv5Liq5aW95pel5a2Q
2、英文等字符串加密
String str1 = Base64Util.encode("Today is a good day. I have 100 yuan");
System.out.println(str1);
// 加密结果:VG9kYXkgaXMgYSBnb29kIGRheS4gSSBoYXZlIDEwMCB5dWFu
3、中文字符串混淆、迭代加密
String str2 = Base64Util.encode("今天是个好日子","4d==", 2);
System.out.println(str2);
// 加密结果:NGQ9PU5HUTlQZVM3aXVXa3FlYVlyK1M0cXVXbHZlYVhwZVd0a0RSa1BUMD00ZD09
4、英文等字符串混淆、迭代加密
String str3 = Base64Util.encode("Today is a good day. I have 100 yuan","gfd5", 3);
System.out.println(str3);
// 加密结果:Z2ZkNVoyWmtOVm95V210T1ZsSjJXa2RHTlVsSGJIcEpSMFZuV2pJNWRscERRbXRaV0d0MVNVVnJaMkZIUmpKYVUwRjRUVVJCWjJWWVZtaGliV1J0V2tSVlBXZG1aRFU9Z2ZkNQ==
5、Map<k,v>数据混淆、迭代加密
ArrayList<Object> list1 = Lists.newArrayList();
list1.add(true);
list1.add(false);
HashMap<String, Object> item = Maps.newHashMap();
item.put("e","have");
item.put("f",list1);
ArrayList<Object> list = Lists.newArrayList();
list.add(1);
list.add("2");
list.add(true);
HashMap<String, Object> map = new HashMap<>(3);
map.put("a",1);
map.put("b","今天是个好日子");
map.put("c",list);
map.put("d",item);
String json = Base64Util.encodeJson(map, "f23o", 3);
System.out.println(json);
// 加密结果:ZjIzb1pqSXpiMXBxU1hwaU0zTnBXVk5KTmsxVGQybFphVWsyU1hWVE4ybDFWMnR4WldGWmNpdFROSEYxVjJ4MlpXRlljR1ZYZEd0RFNYTkpiVTFwVDJ4emVFeERTWGxKYVhnd1kyNVdiRmhUZDJsYVEwazJaWGxLYkVscWIybGhSMFl5V2xOSmMwbHRXV2xQYkhRd1kyNVdiRXhIV21oaVNFNXNXRmd4T1ZwcVNYcGlkejA5WmpJemJ3PT1mMjNv
2、js解密
let str = Base64.decode('5LuK5aSp5piv5Liq5aW95pel5a2Q');
console.log(str);
// 输出结果:见下图
let str1 = Base64.decode('VG9kYXkgaXMgYSBnb29kIGRheS4gSSBoYXZlIDEwMCB5dWFu');
console.log(str1);
// 输出结果:见下图
let str2 = Base64.decoder('NGQ9PU5HUTlQZVM3aXVXa3FlYVlyK1M0cXVXbHZlYVhwZVd0a0RSa1BUMD00ZD09', '4d==', 2);
console.log(str2);
// 输出结果:见下图
let str3 = Base64.decoder('Z2ZkNVoyWmtOVm95V210T1ZsSjJXa2RHTlVsSGJIcEpSMFZuV2pJNWRscERRbXRaV0d0MVNVVnJaMkZIUmpKYVUwRjRUVVJCWjJWWVZtaGliV1J0V2tSVlBXZG1aRFU9Z2ZkNQ==', 'gfd5', 3);
console.log(str3);
// 输出结果:见下图
let str4 = Base64.decodeJson('ZjIzb1pqSXpiMXBxU1hwaU0zTnBXVk5KTmsxVGQybFphVWsyU1hWVE4ybDFWMnR4WldGWmNpdFROSEYxVjJ4MlpXRlljR1ZYZEd0RFNYTkpiVTFwVDJ4emVFeERTWGxKYVhnd1kyNVdiRmhUZDJsYVEwazJaWGxLYkVscWIybGhSMFl5V2xOSmMwbHRXV2xQYkhRd1kyNVdiRXhIV21oaVNFNXNXRmd4T1ZwcVNYcGlkejA5WmpJemJ3PT1mMjNv', 'f23o', 3);
console.log(str4);
// 输出结果:见下图
结果如下:
三、源代码
1、前端js代码:Base64.js
/*
Base64工具类
功能:对字符串进行加解密,可携带混淆字符串、迭代次数
注:
Base64字符串特点:
字符串只可能包含A-Z,a-z,0-9,+,/,=字符
字符串长度是4的倍数
=只会出现在字符串最后,可能没有或者一个等号或者两个等号
@author He Changjie(何昌杰)
@version V 1.0.0
@date 2019-12-25 16:34:00
*/
;(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined'
? module.exports = factory(global)
: typeof define === 'function' && define.amd
? define(factory) : factory(global)
}((
typeof self !== 'undefined' ? self
: typeof window !== 'undefined' ? window
: typeof global !== 'undefined' ? global
: this
), function(global) {
'use strict';
// existing version for noConflict()
global = global || {};
var _Base64 = global.Base64;
var version = "2.5.1";
// if node.js and NOT React Native, we use Buffer
var buffer;
if (typeof module !== 'undefined' && module.exports) {
try {
buffer = eval("require('buffer').Buffer");
} catch (err) {
buffer = undefined;
}
}
// constants
var b64chars
= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
var b64tab = function(bin) {
var t = {};
for (var i = 0, l = bin.length; i < l; i++) t[bin.charAt(i)] = i;
return t;
}(b64chars);
var fromCharCode = String.fromCharCode;
// encoder stuff
var cb_utob = function(c) {
if (c.length < 2) {
var cc = c.charCodeAt(0);
return cc < 0x80 ? c
: cc < 0x800 ? (fromCharCode(0xc0 | (cc >>> 6))
+ fromCharCode(0x80 | (cc & 0x3f)))
: (fromCharCode(0xe0 | ((cc >>> 12) & 0x0f))
+ fromCharCode(0x80 | ((cc >>> 6) & 0x3f))
+ fromCharCode(0x80 | ( cc & 0x3f)));
} else {
var cc = 0x10000
+ (c.charCodeAt(0) - 0xD800) * 0x400
+ (c.charCodeAt(1) - 0xDC00);
return (fromCharCode(0xf0 | ((cc >>> 18) & 0x07))
+ fromCharCode(0x80 | ((cc >>> 12) & 0x3f))
+ fromCharCode(0x80 | ((cc >>> 6) & 0x3f))
+ fromCharCode(0x80 | ( cc & 0x3f)));
}
};
var re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g;
var utob = function(u) {
return u.replace(re_utob, cb_utob);
};
var cb_encode = function(ccc) {
var padlen = [0, 2, 1][ccc.length % 3],
ord = ccc.charCodeAt(0) << 16
| ((ccc.length > 1 ? ccc.charCodeAt(1) : 0) << 8)
| ((ccc.length > 2 ? ccc.charCodeAt(2) : 0)),
chars = [
b64chars.charAt( ord >>> 18),
b64chars.charAt((ord >>> 12) & 63),
padlen >= 2 ? '=' : b64chars.charAt((ord >>> 6) & 63),
padlen >= 1 ? '=' : b64chars.charAt(ord & 63)
];
return chars.join('');
};
var btoa = global.btoa ? function(b) {
return global.btoa(b);
} : function(b) {
return b.replace(/[\s\S]{1,3}/g, cb_encode);
};
var _encode = function(u) {
const isUint8Array = Object.prototype.toString.call(u) === '[object Uint8Array]';
return isUint8Array ? u.toString('base64')
: btoa(utob(String(u)));
}
var encode = function(u, urisafe) {
return !urisafe
? _encode(u)
: _encode(String(u)).replace(/[+\/]/g, function(m0) {
return m0 == '+' ? '-' : '_';
}).replace(/=/g, '');
};
/**
* 对字符串进行Base64加密
* @param str 字符串
* @param confound 混淆字符串(应与Base64特点一致,长度为4个倍数,以加强混淆程度)
* @param iterate 迭代次数
* @return string 加密后的字符串
*/
var encoder = function (str, confound, iterate = 2){
let result = str;
if(str && iterate > 0) {
while (iterate-- > 0) {
result = encode(confound + result + confound);
}
}
return result;
};
/**
* 对JSON格式的数据进行BASE加密
* @param str 字符串
* @param confound 混淆字符串(应与Base64特点一致,长度为4个倍数,以加强混淆程度)
* @param iterate 迭代次数
* @return string JSON加密后的字符串
*/
var encodeJson = function (str, confound, iterate = 2) {
return encoder(JSON.stringify(str), confound, iterate);
};
var encodeURI = function(u) { return encode(u, true) };
// decoder stuff
var re_btou = new RegExp([
'[\xC0-\xDF][\x80-\xBF]',
'[\xE0-\xEF][\x80-\xBF]{2}',
'[\xF0-\xF7][\x80-\xBF]{3}'
].join('|'), 'g');
var cb_btou = function(cccc) {
switch(cccc.length) {
case 4:
var cp = ((0x07 & cccc.charCodeAt(0)) << 18)
| ((0x3f & cccc.charCodeAt(1)) << 12)
| ((0x3f & cccc.charCodeAt(2)) << 6)
| (0x3f & cccc.charCodeAt(3)),
offset = cp - 0x10000;
return (fromCharCode((offset >>> 10) + 0xD800)
+ fromCharCode((offset & 0x3FF) + 0xDC00));
case 3:
return fromCharCode(
((0x0f & cccc.charCodeAt(0)) << 12)
| ((0x3f & cccc.charCodeAt(1)) << 6)
| (0x3f & cccc.charCodeAt(2))
);
default:
return fromCharCode(
((0x1f & cccc.charCodeAt(0)) << 6)
| (0x3f & cccc.charCodeAt(1))
);
}
};
var btou = function(b) {
return b.replace(re_btou, cb_btou);
};
var cb_decode = function(cccc) {
var len = cccc.length,
padlen = len % 4,
n = (len > 0 ? b64tab[cccc.charAt(0)] << 18 : 0)
| (len > 1 ? b64tab[cccc.charAt(1)] << 12 : 0)
| (len > 2 ? b64tab[cccc.charAt(2)] << 6 : 0)
| (len > 3 ? b64tab[cccc.charAt(3)] : 0),
chars = [
fromCharCode( n >>> 16),
fromCharCode((n >>> 8) & 0xff),
fromCharCode( n & 0xff)
];
chars.length -= [0, 0, 2, 1][padlen];
return chars.join('');
};
var _atob = global.atob ? function(a) {
return global.atob(a);
} : function(a){
return a.replace(/\S{1,4}/g, cb_decode);
};
var atob = function(a) {
return _atob(String(a).replace(/[^A-Za-z0-9\+\/]/g, ''));
};
/**
* 私有函数
* 判断字符串是否经过为Base64加密
* @param str 字符串
* @return boolean 是否经过为Base64加密
*/
var isBase64 = function(str){
return /^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$/.test(str);
};
var _decode = buffer ?
buffer.from && Uint8Array && buffer.from !== Uint8Array.from
? function(a) {
return (a.constructor === buffer.constructor
? a : buffer.from(a, 'base64')).toString();
}
: function(a) {
return (a.constructor === buffer.constructor
? a : new buffer(a, 'base64')).toString();
}
: function(a) { return btou(_atob(a)) };
var decode = function(a){
return _decode(
String(a).replace(/[-_]/g, function(m0) { return m0 == '-' ? '+' : '/' })
.replace(/[^A-Za-z0-9\+\/]/g, '')
);
};
/**
* 对字符串进行Base64解密
* 当解密异常时返回原字符串
* @param str 字符串
* @param confound 混淆字符串
* @param iterate 迭代次数
* @return string 解密后的字符串
*/
var decoder = function (str, confound, iterate = 2){
let result = str;
if(str && iterate > 0){
if(isBase64(str)){
let pos;
while (iterate-- > 0){
if(confound.length > 0){
result = decode(result);
if(result.length > confound.length){
result = result.substring(confound.length);
}
pos = result.lastIndexOf(confound);
result = pos === -1 ? result : result.substring(0, pos);
} else {
result = decode(result);
}
}
}
}
return result;
}
/**
* 对JSON格式的数据进行BASE解密
* 当解密异常时返回原字符串
* @param str 字符串
* @param confound 混淆字符串(应与Base64特点一致,长度为4个倍数,以加强混淆程度)
* @param iterate 迭代次数
* @return json 解密后的JSON对象
*/
var decodeJson = function (str, confound, iterate = 2) {
try{
let s2 = decoder(str, confound, iterate);
return JSON.parse(s2);
}catch(err){}
return str;
};
var noConflict = function() {
var Base64 = global.Base64;
global.Base64 = _Base64;
return Base64;
};
// export Base64
global.Base64 = {
VERSION: version,
atob: atob,
btoa: btoa,
fromBase64: decode,
toBase64: encode,
utob: utob,
encode: encode,
encoder: encoder,
encodeJson: encodeJson,
encodeURI: encodeURI,
btou: btou,
decode: decode,
decoder: decoder,
decodeJson: decodeJson,
noConflict: noConflict,
__buffer__: buffer
};
// if ES5 is available, make Base64.extendString() available
if (typeof Object.defineProperty === 'function') {
var noEnum = function(v){
return {value:v,enumerable:false,writable:true,configurable:true};
};
global.Base64.extendString = function () {
Object.defineProperty(
String.prototype, 'fromBase64', noEnum(function () {
return decode(this)
}));
Object.defineProperty(
String.prototype, 'toBase64', noEnum(function (urisafe) {
return encode(this, urisafe)
}));
Object.defineProperty(
String.prototype, 'toBase64URI', noEnum(function () {
return encode(this, true)
}));
};
}
//
// export Base64 to the namespace
//
if (global['Meteor']) { // Meteor.js
Base64 = global.Base64;
}
// module.exports and AMD are mutually exclusive.
// module.exports has precedence.
if (typeof module !== 'undefined' && module.exports) {
module.exports.Base64 = global.Base64;
}
else if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define([], function(){ return global.Base64 });
}
// that's it!
return {Base64: global.Base64}
}));
2、后端Java代码:Base64Util.java
package ***;
import org.springframework.util.Assert;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Map;
import java.util.regex.Pattern;
/**
* Base64工具类
* 功能:对字符串进行加解密,可携带混淆字符串、迭代次数
*
* 注:
* Base64字符串特点:
* 字符串只可能包含A-Z,a-z,0-9,+,/,=字符
* 字符串长度是4的倍数
* =只会出现在字符串最后,可能没有或者一个等号或者两个等号
* @author He Changjie(何昌杰)
* @version V 1.0.0
* @date 2019-12-25 16:34:00
*
*/
public class Base64Util {
/**
* JSON格式化类
*/
private final static JsonMapper JSON_MAPPER = JsonMapper.INSTANCE;
/**
* BASE64编码器
*/
private final static Base64.Encoder ENCODER = Base64.getEncoder();
/**
* BASE64解码器
*/
private final static Base64.Decoder DECODER = Base64.getDecoder();
/**
* 对JSON格式的Map数据进行Base 64加密
* @param map Map数据
* @param confound 混淆字符串(应与Base64特点一致,长度为4个倍数,以加强混淆程度)
* @param iterate 迭代次数
* @return string JSON加密后的字符串
*/
public static String encodeJson(Map<String, Object> map, String confound, int iterate){
String json = JSON_MAPPER.toJson(map);
return encode(json, confound, iterate);
}
/**
* 对JSON格式的数据进行Base 64加密
* @param obj 源数据
* @param confound 混淆字符串(应与Base64特点一致,长度为4个倍数,以加强混淆程度)
* @return string JSON加密后的字符串
*/
public static String encodeJson(Object obj, String confound){
int iterate = 2;
String json = JSON_MAPPER.toJson(obj);
return encode(json, confound, iterate);
}
/**
* 对JSON格式的Map数据进行Base 64解密
* @param str Map数据的JSON字符串
* @param confound 混淆字符串(应与Base64特点一致,长度为4个倍数,以加强混淆程度)
* @param iterate 迭代次数
* @return string JSON加密后的字符串
*/
public static Map<String, Object> decodeJson(String str, String confound, int iterate){
String decoder = decode(str, confound, iterate);
return JSON_MAPPER.fromJson(decoder, Map.class);
}
/**
* 对JSON格式的Map数据进行Base 64解密
* @param str Map数据的JSON字符串
* @param confound 混淆字符串(应与Base64特点一致,长度为4个倍数,以加强混淆程度)
* @return string JSON加密后的字符串
*/
public static Map<String, Object> decodeJson(String str, String confound){
int iterate = 2;
String decoder = decode(str, confound, iterate);
return JSON_MAPPER.fromJson(decoder, Map.class);
}
/**
* 进行Base64加密
* @param str 源字符串
* @param confound 混淆字符串(应与Base64特点一致,长度为4个倍数,以加强混淆程度)
* @param iterate 迭代次数
* @return 加密后字符串
*/
public static String encode(String str, String confound, int iterate){
Assert.isTrue(iterate > 0, "迭代次数错误");
Assert.notNull(str, "源字符串缺失");
String result = str;
while (iterate-- > 0){
result = Base64Util.encode(confound + result + confound).replaceAll("\r\n","");
}
return result;
}
/**
* 进行Base64加密
* @param str 源字符串
* @param confound 混淆字符串(应与Base64特点一致,长度为4个倍数,以加强混淆程度)
* @return 加密后字符串
*/
public static String encode(String str, String confound){
Assert.notNull(str, "源字符串缺失");
int iterate = 2;
String result = str;
while (iterate-- > 0){
result = Base64Util.encode(confound + result + confound).replaceAll("\r\n","");
}
return result;
}
/**
* 进行Base64解密
* @param str 源字符串
* @param confound 混淆字符串
* @param iterate 迭代次数
* @return 解密后字符串
*/
public static String decode(String str, String confound, int iterate){
Assert.isTrue(iterate > 0, "迭代次数错误");
Assert.notNull(str, "源字符串缺失");
String result = str;
if(Base64Util.isBase64(str)){
int pos;
while (iterate-- > 0){
if(confound.length() > 0){
result = Base64Util.decode(result);
if(result.length() > confound.length()){
result = result.substring(confound.length());
}
pos = result.lastIndexOf(confound);
result = pos == -1 ? result : result.substring(0, pos);
} else {
result = Base64Util.decode(result);
}
}
}
return result;
}
/**
* 进行Base64解密
* @param str 源字符串
* @param confound 混淆字符串
* @return 解密后字符串
*/
public static String decode(String str, String confound){
Assert.notNull(str, "源字符串缺失");
String result = str;
int iterate = 2;
if(Base64Util.isBase64(str)){
int pos;
while (iterate-- > 0){
if(confound.length() > 0){
result = Base64Util.decode(result);
if(result.length() > confound.length()){
result = result.substring(confound.length());
}
pos = result.lastIndexOf(confound);
result = pos == -1 ? result : result.substring(0, pos);
} else {
result = Base64Util.decode(result);
}
}
}
return result;
}
/**
* 进行一次Base64加密
* @param str 源字符串
* @return 加密后字符串
*/
public static String encode(String str){
Assert.notNull(str, "源字符串缺失");
return ENCODER.encodeToString(str.getBytes(StandardCharsets.UTF_8));
}
/**
* 进行一次Base64解密
* @param str 源字符串
* @return 解密后字符串
*/
public static String decode(String str){
Assert.notNull(str, "源字符串缺失");
try {
str = new String(DECODER.decode(str), StandardCharsets.UTF_8);
} catch (Exception ignored) {}
return str;
}
/**
* 私有函数
* 判断源字符串是否经过为Base64加密
* @param str 源字符串
* @return 是否经过为Base64加密
*/
private static boolean isBase64(String str){
String base64Pattern = "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$";
return Pattern.matches(base64Pattern, str);
}
}
如有疑问欢迎评论留言!
手编不易,转载请注明地址:https://blog.csdn.net/qq_32352777/article/details/103968443
谢谢大家!