first commit
This commit is contained in:
342
src/main/java/com/peanut/common/Interface/KdApiEOrder.java
Normal file
342
src/main/java/com/peanut/common/Interface/KdApiEOrder.java
Normal file
@@ -0,0 +1,342 @@
|
||||
package com.peanut.common.Interface;
|
||||
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.peanut.common.utils.HttpClientUtils;
|
||||
import com.peanut.common.utils.KdUtils;
|
||||
import com.peanut.modules.book.entity.FMSCommodity;
|
||||
import com.peanut.modules.book.entity.FMSOrderEntity;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @技术QQ群: 可登录官网https://www.kdniao.com/右侧查看技术群号
|
||||
* @see: https://kdniao.com/api-eorder
|
||||
* @copyright: 深圳市快金数据技术服务有限公司
|
||||
* ID和Key请到官网申请:https://kdniao.com/reg
|
||||
|
||||
|
||||
* 电子面单接口
|
||||
* 此接口用于向快递/快运公司下发订单并获取快递单号,返回电子面单html模板,通知快递员上门取件。该功能支持情况需查看技术文档。
|
||||
*正式地址:https://api.kdniao.com/api/EOrderService
|
||||
*
|
||||
*
|
||||
* 系统级参数
|
||||
* RequestData String R 请求内容为JSON格式 详情可参考接口技术文档:https://www.kdniao.com/documents
|
||||
* EBusinessID String R 用户ID
|
||||
* RequestType String R 请求接口指令
|
||||
* DataSign String R 数据内容签名,加密方法为:把(请求内容(未编码)+ApiKey)进行MD5加密--32位小写,然后Base64编码,最后进行URL(utf-8)编码
|
||||
* DataType String R DataType=2,请求、返回数据类型均为JSON格式
|
||||
|
||||
* 应用级参数
|
||||
* R-必填(Required),O-可选(Optional),C-报文中该参数在一定条件下可选(Conditional)
|
||||
* Callback String(50) O 用户自定义回传字段
|
||||
* CustomerName String(50) C 电子面单客户号,需要下载《快递鸟电子面单客户号参数对照表.xlsx》,参考对应字段传值 https://www.kdniao.com/documents
|
||||
* CustomerPwd String(50) C 同上
|
||||
* SendSite String(50) C 同上
|
||||
* SendStaff String(50) C 同上
|
||||
* MonthCode String(20) C 同上
|
||||
* CustomArea String(500) O 商家自定义区域,需查看技术文档说明
|
||||
* WareHouseID String(30) C 发货仓编码(ShipperCode为JD或JDKY时必填)
|
||||
* TransType Int(2) O 京东(ShipperCode为JD或JDKY)的产品类型,需查看技术文档说明
|
||||
* ShipperCode String(10) R 快递公司编码详细编码参考《快递鸟接口支持快递公司编码.xlsx》 https://www.kdniao.com/documents
|
||||
* LogisticCode String(30) O 快递单号(仅宅急送可用)
|
||||
* OrderCode String(30) R 订单编号(自定义,不可重复)
|
||||
* ThrOrderCode String(50) C 京东商城的订单号(ShipperCode为JD且ExpType为1时必填)
|
||||
* PayType Int(1) R 运费支付方式:1-现付,2-到付,3-月结
|
||||
* ExpType String(2) R 详细快递类型参考《快递公司快递业务类型.xlsx》 https://www.kdniao.com/documents
|
||||
* IsReturnSignBill Int(1) O 是否要求签回单 0-不要求,1-要求
|
||||
* Receiver.Company String(30) O 收件人公司
|
||||
* Receiver.Name String(30) R 收件人
|
||||
* Receiver.Tel String(20) R 电话(电话与手机,必填一个)
|
||||
* Receiver.Mobile String(20) R 手机(电话与手机,必填一个)
|
||||
* Receiver.PostCode String(10) C 收件地邮编(ShipperCode为EMS、YZPY、YZBK时必填)
|
||||
* Receiver.ProvinceName String(20) R 收件省(如广东省,不要缺少“省”;如是直辖市,请直接传北京、上海等;如是自治区,请直接传广西壮族自治区等)
|
||||
* Receiver.CityName String(20) R 收件市(如深圳市,不要缺少“市;如是市辖区,请直接传北京市、上海市等”)
|
||||
* Receiver.ExpAreaName String(20) R 收件区/县(如福田区,不要缺少“区”或“县”)
|
||||
* Receiver.Address String(100) R 收件人详细地址(不用传省市区)
|
||||
* Sender.Company String(30) O 发件人公司
|
||||
* Sender.Name String(30) R 发件人
|
||||
* Sender.Tel String(20) R 电话(电话与手机,必填一个)
|
||||
* Sender.Mobile String(20) R 手机(电话与手机,必填一个)
|
||||
* Sender.PostCode String(10) C 发件地邮编(ShipperCode为EMS、YZPY、YZBK时必填)
|
||||
* Sender.ProvinceName String(20) R 发件省(如广东省,不要缺少“省”;如是直辖市,请直接传北京、上海等;如是自治区,请直接传广西壮族自治区等)
|
||||
* Sender.CityName String(20) R 发件市(如深圳市,不要缺少“市;如是市辖区,请直接传北京市、上海市等”)
|
||||
* Sender.ExpAreaName String(20) R 发件区/县(如福田区,不要缺少“区”或“县”)
|
||||
* Sender.Address String(100) R 发件人详细地址(不用传省市区)
|
||||
* IsNotice Int(1) O 是否通知快递员上门揽件 0-通知,1-不通知,不填则默认为1
|
||||
* StartDate String(32) O 上门揽件时间段,格式:YYYY-MM-DD HH24:MM:SS
|
||||
* EndDate String(32) O 上门揽件时间段,格式:YYYY-MM-DD HH24:MM:SS
|
||||
* Weight Double(10,3) C 包裹总重量kg 1、当为快运的订单时必填;2、ShipperCode为JD时必填;
|
||||
* Quantity Int(2) R 包裹数(最多支持300件)一个包裹对应一个运单号,如果是大于1个包裹,返回则按照子母件的方式返回母运单号和子运单号
|
||||
* Volume Double(20,3) C 包裹总体积m3 1、当为快运的订单时必填;2、ShipperCode为JD时必填;
|
||||
* Remark String(60) O 备注
|
||||
* AddService.Name String(20) C 增值服务名称(数组形式,可以有多个增值服务)
|
||||
* AddService.Value String(30) C 增值服务值
|
||||
* AddService.CustomerID String(30) O 客户标识
|
||||
* Commodity.GoodsName String(100) R 商品名称(数组形式)
|
||||
* IsReturnPrintTemplate String(1) O 是否返回电子面单模板:0-不需要,1-需要
|
||||
* IsSendMessage Int(1) O 是否订阅短信:0-不需要,1-需要
|
||||
* IsSubscribe String(1) O 是否订阅轨迹推送 0-不订阅,1-订阅,不填默认为1
|
||||
* TemplateSize String(10) O 模板规格,需查看技术文档说明
|
||||
* PackingType Int(2) C 包装类型(快运字段),需查看技术文档说明
|
||||
* DeliveryMethod Int(1) C 送货方式/派送类型/配送方式(快运字段),需查看技术文档说明
|
||||
* CurrencyCode String(10) C 货物单价的币种:CNY: 人民币 HKD: 港币 NTD: 新台币 MOP: 澳门元 (ShipperCode为SF且收件地址为港澳台地区,必填)
|
||||
* Dutiable.DeclaredValue Number(15,3) C 申报价值:订单货物总声明价值,包含子母件,精确到小数点后3位 (ShipperCode为SF且收件地址为港澳台地区,必填)
|
||||
*/
|
||||
|
||||
public class KdApiEOrder {
|
||||
|
||||
//用户ID,快递鸟提供,注意保管,不要泄漏
|
||||
private static String EBusinessID="1788532";//即用户ID
|
||||
// private static String EBusinessID="test1788532";//即用户ID
|
||||
//API key,快递鸟提供,注意保管,不要泄漏
|
||||
private static String ApiKey="f4342e6c-5cfa-458f-997b-f973eb29eb1d";//即API key
|
||||
// private static String ApiKey="34f033ae-9c73-4b9a-899e-943a65fd86bf";//即API key
|
||||
|
||||
// 电子面单请求url
|
||||
private static String OnlineReqURL="https://api.kdniao.com/api/EOrderService";
|
||||
// private static String OnlineReqURL="http://sandboxapi.kdniao.com:8080/kdniaosandbox/gateway/exterfaceInvoke.json";
|
||||
|
||||
// 物流信息跟踪
|
||||
private String TrackReqURL="https://api.kdniao.com/api/dist";
|
||||
// private static String TrackReqURL="http://sandboxapi.kdniao.com:8080/kdniaosandbox/gateway/exterfaceInvoke.json";
|
||||
|
||||
// 即时查询物流信息
|
||||
private static String QueryReqURL="https://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx";
|
||||
// private static String QueryReqURL="http://sandboxapi.kdniao.com:8080/kdniaosandbox/gateway/exterfaceInvoke.json";
|
||||
|
||||
|
||||
// public static void main(String[] args) {
|
||||
// try {
|
||||
// KdApiEOrder api = new KdApiEOrder();
|
||||
// System.out.println(api.orderOnlineByJson());
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* 电子面单接口
|
||||
* 此接口用于向快递/快运公司下发订单并获取快递单号,返回电子面单html模板,通知快递员上门取件。
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static JSONArray orderOnlineByJson(List<FMSOrderEntity> fmsOrderList) throws Exception{
|
||||
String RequestData= "";
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
String cust = "";
|
||||
for(FMSOrderEntity fms : fmsOrderList){
|
||||
// 组装应用级参数
|
||||
RequestData= "{"+
|
||||
"'OrderCode': '" + fms.getOrderCode() + "',"+
|
||||
"'ShipperCode': '" + fms.getShipperCode() + "',";
|
||||
if("JD".equals(fms.getShipperCode())){
|
||||
cust = "'CustomerName': '010K1598220',"+
|
||||
"'CustomerPwd': '',";
|
||||
}
|
||||
if ("YD".equals(fms.getShipperCode())){
|
||||
// cust = "'CustomerName': '114198226272',"+
|
||||
// "'CustomerPwd': 'gcs5XavNGRVqbhUmHpnkDd7Fi3T9Ef',";
|
||||
cust = "'CustomerName': 'testyd',"+
|
||||
"'CustomerPwd': 'testydpwd',";
|
||||
}
|
||||
|
||||
cust += "'MonthCode': '',"+
|
||||
"'SendSite': '',"+
|
||||
"'PayType': 1,"+
|
||||
"'MonthCode': '',"+
|
||||
"'ExpType': 1,"+
|
||||
"'Cost': 1.0,"+
|
||||
"'OtherCost': 1.0,"+
|
||||
// "'TemplateSize':'130'"+
|
||||
"'Sender': {"+
|
||||
"'Company': '众妙之门',"+
|
||||
"'Name': 'Taylor',"+
|
||||
"'Mobile': '12345678901',"+
|
||||
"'ProvinceName': '天津',"+
|
||||
"'CityName': '天津市',"+
|
||||
"'ExpAreaName': '南开区',"+
|
||||
"'Address': '天津市南开区融创中心中南广场东区2号楼605'"+
|
||||
"},"+
|
||||
"'Receiver': {"+
|
||||
"'Company': '',"+
|
||||
"'Name': '" + fms.getReceiverName() + "',"+
|
||||
"'Mobile': '" + fms.getReceiverMobile() + "',"+
|
||||
"'ProvinceName': '" + fms.getReceiverProvinceName() + "',"+
|
||||
"'CityName': '" + fms.getReceiverCityName() + "',"+
|
||||
"'ExpAreaName': '" + fms.getReceiverExpAreaName() + "',"+
|
||||
"'Address': '" + fms.getReceiverAddress() + "'"+
|
||||
"},"+
|
||||
"'Commodity': [" ;
|
||||
String s = "";
|
||||
for(FMSCommodity fmsCommodity : fms.getCommodityList() ){
|
||||
s += "{'GoodsName': '"+fmsCommodity.getGoodsName()+ "'},";
|
||||
}
|
||||
s = s.substring(0,s.lastIndexOf(','));
|
||||
String a = s + "],"+
|
||||
"'AddService': [],"+
|
||||
"'IsReturnPrintTemplate':1,"+
|
||||
"'Remark': "+ fms.getRemark()+""+
|
||||
"}";
|
||||
|
||||
// 组装系统级参数
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.put("RequestData", KdUtils.urlEncoder(RequestData + cust + a, "UTF-8"));
|
||||
params.put("EBusinessID", EBusinessID);
|
||||
params.put("RequestType", "1007");
|
||||
String dataSign=KdUtils.encrypt(RequestData + cust + a, ApiKey, "UTF-8");
|
||||
System.out.println(RequestData + a);
|
||||
params.put("DataSign", KdUtils.urlEncoder(dataSign, "UTF-8"));
|
||||
params.put("DataType", "2");
|
||||
// 以form表单形式提交post请求,post请求体中包含了应用级参数和系统级参数
|
||||
String result= HttpClientUtils.kdSendPost(OnlineReqURL, params);
|
||||
jsonArray.add(result);
|
||||
}
|
||||
return jsonArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* 电子面单取消接口
|
||||
* 此接口用于取消“电子面单接口”下单成功的订单,回收快递单号。
|
||||
*
|
||||
* 应用级参数
|
||||
* R-必填(Required),O-可选(Optional),C-报文中该参数在一定条件下可选(Conditional)
|
||||
* ShipperCode String(10) R 快递公司编码
|
||||
* OrderCode String(30) R 订单编号
|
||||
* ExpNo String(30) R 快递单号
|
||||
* CustomerName String(50) R 电子面单客户号
|
||||
* CustomerPwd String(30) R 电子面单密码(顺丰不需要)
|
||||
*
|
||||
*/
|
||||
@RequestMapping("/cancel")
|
||||
public static String cancelOrderByJson(@RequestParam Map<String,Object> param) throws Exception{
|
||||
|
||||
// 组装应用级参数
|
||||
String RequestData= "{"+
|
||||
"'ShipperCode':" +param.get("ShipperCode")+","+
|
||||
"'OrderCode': "+param.get("orderSn")+","+
|
||||
"'ExpNo': '"+param.get("ExpNo")+"',"+
|
||||
"}";
|
||||
// 组装系统级参数
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
params.put("RequestData", KdUtils.urlEncoder(RequestData, "UTF-8"));
|
||||
params.put("EBusinessID", EBusinessID);
|
||||
params.put("RequestType", "1147");
|
||||
String dataSign=KdUtils.encrypt(RequestData, ApiKey, "UTF-8");
|
||||
params.put("DataSign", KdUtils.urlEncoder(dataSign, "UTF-8"));
|
||||
params.put("DataType", "2");
|
||||
// 以form表单形式提交post请求,post请求体中包含了应用级参数和系统级参数
|
||||
String result=HttpClientUtils.kdSendPost(OnlineReqURL, params);
|
||||
|
||||
// JSONObject json = JSONObject.parseObject(result);
|
||||
// if(json.get("Success").equals("true")){
|
||||
// // TODO 返回值为Success时 存入到系统中的 sys_interface_log 表
|
||||
//
|
||||
// }else{
|
||||
// // TODO 存入到系统中的 sys_interface_fail 表中
|
||||
// // TODO 存入interfaceType 值为 ‘2’ 用作以后人工干预重推 区分是什么接口
|
||||
//
|
||||
// }
|
||||
|
||||
//根据公司业务处理返回的信息......
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 即时查询接口(增值版)
|
||||
* 此接口用于向快递公司实时查询物流轨迹信息。
|
||||
*
|
||||
* 应用级参数
|
||||
* R-必填(Required),O-可选(Optional),C-报文中该参数在一定条件下可选(Conditional)
|
||||
* OrderCode String(30) O 订单编号
|
||||
* CustomerName String(50) C ShipperCode为SF时必填,对应寄件人/收件人手机号后四位;ShipperCode为其他快递时,可不填或保留字段,不可传值
|
||||
* ShipperCode String(10) R 快递公司编码 详细编码参考《快递鸟接口支持快递公司编码.xlsx》
|
||||
* LogisticCode String(30) R 快递单号
|
||||
*/
|
||||
@RequestMapping("/queryOrder")
|
||||
public static String queryOrderOnlineByJson(@RequestParam Map<String,Object> param) throws Exception{
|
||||
// 组装应用级参数
|
||||
String RequestData= "{"+
|
||||
"'ShipperCode': '"+ param.get("ShipperCode") +"',"+
|
||||
"'LogisticCode': '"+ param.get("LogisticCode") +"',"+
|
||||
"}";
|
||||
// 组装系统级参数
|
||||
Map<String,String> params = new HashMap<String,String>();
|
||||
params.put("RequestData", KdUtils.urlEncoder(RequestData, "UTF-8"));
|
||||
params.put("EBusinessID", EBusinessID);
|
||||
params.put("RequestType", "8001");//在途监控即时查询接口指令8001/地图版即时查询接口指令8003
|
||||
String dataSign=KdUtils.encrypt(RequestData, ApiKey, "UTF-8");
|
||||
params.put("DataSign", KdUtils.urlEncoder(dataSign, "UTF-8"));
|
||||
params.put("DataType", "2");
|
||||
// 以form表单形式提交post请求,post请求体中包含了应用级参数和系统级参数
|
||||
String result=HttpClientUtils.kdSendPost(QueryReqURL, params);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 物流跟踪接口(增值版)
|
||||
* 此接口用于向快递鸟订阅物流轨迹信息。
|
||||
*
|
||||
* 应用级参数
|
||||
* R-必填(Required),O-可选(Optional),C-报文中该参数在一定条件下可选(Conditional)
|
||||
* Callback String(50) O 用户自定义回传字段
|
||||
* ShipperCode String(10) R 快递公司编码 详细编码参考《快递鸟接口支持快递公司编码.xlsx》
|
||||
* LogisticCode String(30) R 快递单号
|
||||
* CustomerName String(50) C ShipperCode为SF时必填,对应寄件人/收件人手机号后四位;ShipperCode为其他快递时,可不填或保留字段,不可传值
|
||||
|
||||
*/
|
||||
@RequestMapping("/track")
|
||||
public String trackOrderByJson(@RequestParam Map<String,Object> param) throws Exception{
|
||||
// 组装应用级参数
|
||||
String RequestData= "{"+
|
||||
"'Callback':'OrderCode',"+
|
||||
"'ShipperCode':'" + param.get("ShipperCode") + "',"+
|
||||
"'LogisticCode':'" + param.get("LogisticCode") + "',"+
|
||||
"}";
|
||||
// 组装系统级参数
|
||||
Map<String,String> params = new HashMap<String,String>();
|
||||
params.put("RequestData", KdUtils.urlEncoder(RequestData, "UTF-8"));
|
||||
params.put("EBusinessID", EBusinessID);
|
||||
params.put("RequestType", "8008");//在途监控订阅接口指令8008/地图版订阅接口指令8005
|
||||
String dataSign=KdUtils.encrypt(RequestData, ApiKey, "UTF-8");
|
||||
params.put("DataSign", KdUtils.urlEncoder(dataSign, "UTF-8"));
|
||||
params.put("DataType", "2");
|
||||
// 以form表单形式提交post请求,post请求体中包含了应用级参数和系统级参数
|
||||
String result=HttpClientUtils.kdSendPost(TrackReqURL, params);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 此接口用于快递鸟推送物流轨迹信息。
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
// TODO 后续编写 获取信息存库 调用消息队列 异步推送给 一路健康 or 疯子读书
|
||||
@RequestMapping("/pushOrder")
|
||||
public String subscribeOrderByJSON() throws Exception{
|
||||
|
||||
// JSONObject json = JSONObject.parseObject(result);
|
||||
// if(json.get("Success").equals("true")){
|
||||
// // TODO 返回值为Success时 存入到系统中的 sys_interface_log 表
|
||||
//
|
||||
// }else{
|
||||
// // TODO 存入到系统中的 sys_interface_fail 表中
|
||||
// // TODO 存入interfaceType 值为 ‘5’ 用作以后人工干预重推 区分是什么接口
|
||||
//
|
||||
// }
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
28
src/main/java/com/peanut/common/annotation/SysLog.java
Normal file
28
src/main/java/com/peanut/common/annotation/SysLog.java
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 系统日志注解
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface SysLog {
|
||||
|
||||
String value() default "";
|
||||
}
|
||||
46
src/main/java/com/peanut/common/aspect/RedisAspect.java
Normal file
46
src/main/java/com/peanut/common/aspect/RedisAspect.java
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.aspect;
|
||||
|
||||
import com.peanut.common.exception.RRException;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Redis切面处理类
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Aspect
|
||||
@Configuration
|
||||
public class RedisAspect {
|
||||
private Logger logger = LoggerFactory.getLogger(getClass());
|
||||
//是否开启redis缓存 true开启 false关闭
|
||||
@Value("${spring.redis.open: false}")
|
||||
private boolean open;
|
||||
|
||||
@Around("execution(* com.peanut.common.utils.RedisUtils.*(..))")
|
||||
public Object around(ProceedingJoinPoint point) throws Throwable {
|
||||
Object result = null;
|
||||
if(open){
|
||||
try{
|
||||
result = point.proceed();
|
||||
}catch (Exception e){
|
||||
logger.error("redis error", e);
|
||||
throw new RRException("Redis服务异常");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
101
src/main/java/com/peanut/common/aspect/SysLogAspect.java
Normal file
101
src/main/java/com/peanut/common/aspect/SysLogAspect.java
Normal file
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.aspect;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.peanut.common.annotation.SysLog;
|
||||
import com.peanut.common.utils.HttpContextUtils;
|
||||
import com.peanut.common.utils.IPUtils;
|
||||
import com.peanut.modules.sys.entity.SysLogEntity;
|
||||
import com.peanut.modules.sys.entity.SysUserEntity;
|
||||
import com.peanut.modules.sys.service.SysLogService;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 系统日志,切面处理类
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
public class SysLogAspect {
|
||||
@Autowired
|
||||
private SysLogService sysLogService;
|
||||
|
||||
@Pointcut("@annotation(com.peanut.common.annotation.SysLog)")
|
||||
public void logPointCut() {
|
||||
|
||||
}
|
||||
|
||||
@Around("logPointCut()")
|
||||
public Object around(ProceedingJoinPoint point) throws Throwable {
|
||||
long beginTime = System.currentTimeMillis();
|
||||
//执行方法
|
||||
Object result = point.proceed();
|
||||
//执行时长(毫秒)
|
||||
long time = System.currentTimeMillis() - beginTime;
|
||||
|
||||
//保存日志
|
||||
saveSysLog(point, time);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void saveSysLog(ProceedingJoinPoint joinPoint, long time) {
|
||||
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||
Method method = signature.getMethod();
|
||||
|
||||
SysLogEntity sysLog = new SysLogEntity();
|
||||
SysLog syslog = method.getAnnotation(SysLog.class);
|
||||
if(syslog != null){
|
||||
//注解上的描述
|
||||
sysLog.setOperation(syslog.value());
|
||||
}
|
||||
|
||||
//请求的方法名
|
||||
String className = joinPoint.getTarget().getClass().getName();
|
||||
String methodName = signature.getName();
|
||||
sysLog.setMethod(className + "." + methodName + "()");
|
||||
|
||||
//请求的参数
|
||||
Object[] args = joinPoint.getArgs();
|
||||
try{
|
||||
String params = new Gson().toJson(args);
|
||||
sysLog.setParams(params);
|
||||
}catch (Exception e){
|
||||
|
||||
}
|
||||
|
||||
//获取request
|
||||
HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
|
||||
//设置IP地址
|
||||
sysLog.setIp(IPUtils.getIpAddr(request));
|
||||
|
||||
//用户名
|
||||
String username = ((SysUserEntity) SecurityUtils.getSubject().getPrincipal()).getUsername();
|
||||
sysLog.setUsername(username);
|
||||
|
||||
sysLog.setTime(time);
|
||||
sysLog.setCreateDate(new Date());
|
||||
//保存系统日志
|
||||
sysLogService.save(sysLog);
|
||||
}
|
||||
}
|
||||
61
src/main/java/com/peanut/common/exception/RRException.java
Normal file
61
src/main/java/com/peanut/common/exception/RRException.java
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.exception;
|
||||
|
||||
/**
|
||||
* 自定义异常
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class RRException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String msg;
|
||||
private int code = 500;
|
||||
|
||||
public RRException(String msg) {
|
||||
super(msg);
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public RRException(String msg, Throwable e) {
|
||||
super(msg, e);
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public RRException(String msg, int code) {
|
||||
super(msg);
|
||||
this.msg = msg;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public RRException(String msg, int code, Throwable e) {
|
||||
super(msg, e);
|
||||
this.msg = msg;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void setMsg(String msg) {
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.exception;
|
||||
|
||||
import com.peanut.common.utils.R;
|
||||
import org.apache.shiro.authz.AuthorizationException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.servlet.NoHandlerFoundException;
|
||||
|
||||
/**
|
||||
* 异常处理器
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@RestControllerAdvice
|
||||
public class RRExceptionHandler {
|
||||
private Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
/**
|
||||
* 处理自定义异常
|
||||
*/
|
||||
@ExceptionHandler(RRException.class)
|
||||
public R handleRRException(RRException e){
|
||||
R r = new R();
|
||||
r.put("code", e.getCode());
|
||||
r.put("msg", e.getMessage());
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@ExceptionHandler(NoHandlerFoundException.class)
|
||||
public R handlerNoFoundException(Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
return R.error(404, "路径不存在,请检查路径是否正确");
|
||||
}
|
||||
|
||||
@ExceptionHandler(DuplicateKeyException.class)
|
||||
public R handleDuplicateKeyException(DuplicateKeyException e){
|
||||
logger.error(e.getMessage(), e);
|
||||
return R.error("数据库中已存在该记录");
|
||||
}
|
||||
|
||||
@ExceptionHandler(AuthorizationException.class)
|
||||
public R handleAuthorizationException(AuthorizationException e){
|
||||
logger.error(e.getMessage(), e);
|
||||
return R.error("没有权限,请联系管理员授权");
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public R handleException(Exception e){
|
||||
logger.error(e.getMessage(), e);
|
||||
return R.error();
|
||||
}
|
||||
}
|
||||
71
src/main/java/com/peanut/common/utils/BaiduVoicesUtils.java
Normal file
71
src/main/java/com/peanut/common/utils/BaiduVoicesUtils.java
Normal file
@@ -0,0 +1,71 @@
|
||||
package com.peanut.common.utils;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.UUID;
|
||||
|
||||
public class BaiduVoicesUtils {
|
||||
|
||||
// 填写申请百度语音申请的appkey 申请地址:百度AI开放平台
|
||||
private final static String appKey = "aKDun6vXyqPLhWMdoIsv87Ez";
|
||||
// private final static String appKey = "eaPPX40oIazH8R4oWsD9U4IT";
|
||||
|
||||
// 填写申请百度语音申请的APP SECRET
|
||||
private final static String secretKey = "ew9dMb4yGmwF1g4qutxNvogzjd9eP5tb";
|
||||
// private final static String secretKey = "DTN0ioQywwM23IoT2ZzEBmvfBe63ATEY";
|
||||
|
||||
// text 的内容为"欢迎使用百度语音合成"的urlencode,utf-8 编码
|
||||
private final String text = "百度百科是百度公司推出的一部内容开放、自由的网络百科全书。";
|
||||
// 发音人选择, 0为普通女声,1为普通男生,3为情感合成-度逍遥,4为情感合成-度丫丫,默认为普通女声
|
||||
private final static int per = 3;
|
||||
// 语速,取值0-9,默认为5中语速
|
||||
private final static int spd = 5;
|
||||
// 音调,取值0-9,默认为5中语调
|
||||
private final static int pit = 5;
|
||||
// 音量,取值0-9,默认为5中音量
|
||||
private final static int vol = 5;
|
||||
// 调用地址
|
||||
public final static String url = "http://tsn.baidu.com/text2audio";
|
||||
// 用户唯一标识,用来区分用户,填写机器 MAC 地址或 IMEI 码,长度为60以内
|
||||
private static String cuid = "0322java";
|
||||
|
||||
public static String run(String content) throws Exception {
|
||||
TokenHolder holder = new TokenHolder(appKey, secretKey, TokenHolder.ASR_SCOPE);
|
||||
holder.resfresh();
|
||||
String token = holder.getToken();
|
||||
|
||||
// for (String a:list) {
|
||||
String url2 = url + "?tex=" + ConnUtil.urlEncode(content);
|
||||
url2 += "&per=" + per;
|
||||
url2 += "&spd=" + spd;
|
||||
url2 += "&pit=" + pit;
|
||||
url2 += "&vol=" + vol;
|
||||
url2 += "&cuid=" + cuid;
|
||||
url2 += "&tok=" + token;
|
||||
url2 += "&lan=zh&ctp=1";
|
||||
HttpURLConnection conn = (HttpURLConnection) new URL(url2).openConnection();
|
||||
conn.setConnectTimeout(5000);
|
||||
String contentType = conn.getContentType();
|
||||
if (contentType.contains("mp3")) {
|
||||
byte[] bytes = ConnUtil.getResponseBytes(conn);
|
||||
// 存在项目根目录下,去文件夹点击可以播放
|
||||
String substring = UUID.randomUUID().toString().substring(0, 6);
|
||||
File file = new File(substring+".mp3");
|
||||
FileOutputStream os = new FileOutputStream(file);
|
||||
os.write(bytes);
|
||||
os.close();
|
||||
System.out.println("mp3 file write to " + file.getAbsolutePath());
|
||||
return file.getAbsolutePath();
|
||||
} else {
|
||||
System.err.println("ERROR: content-type= " + contentType);
|
||||
String res = ConnUtil.getResponseString(conn);
|
||||
System.err.println(res);
|
||||
return res;
|
||||
}
|
||||
// }
|
||||
|
||||
}
|
||||
}
|
||||
21
src/main/java/com/peanut/common/utils/ConfigConstant.java
Normal file
21
src/main/java/com/peanut/common/utils/ConfigConstant.java
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.utils;
|
||||
|
||||
/**
|
||||
* 系统参数相关Key
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class ConfigConstant {
|
||||
/**
|
||||
* 云存储配置KEY
|
||||
*/
|
||||
public final static String CLOUD_STORAGE_CONFIG_KEY = "CLOUD_STORAGE_CONFIG_KEY";
|
||||
}
|
||||
92
src/main/java/com/peanut/common/utils/ConnUtil.java
Normal file
92
src/main/java/com/peanut/common/utils/ConnUtil.java
Normal file
@@ -0,0 +1,92 @@
|
||||
package com.peanut.common.utils;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URLEncoder;
|
||||
|
||||
|
||||
public class ConnUtil {
|
||||
/**
|
||||
* UrlEncode, UTF-8 编码
|
||||
*
|
||||
* @param str
|
||||
* 原始字符串
|
||||
* @return
|
||||
*/
|
||||
public static String urlEncode(String str) {
|
||||
String result = null;
|
||||
try {
|
||||
result = URLEncoder.encode(str, "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从HttpURLConnection 获取返回的字符串
|
||||
*
|
||||
* @param conn
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws DemoException
|
||||
*/
|
||||
public static String getResponseString(HttpURLConnection conn) throws IOException, DemoException {
|
||||
return new String(getResponseBytes(conn));
|
||||
}
|
||||
|
||||
/**
|
||||
* 从HttpURLConnection 获取返回的bytes 注意 HttpURLConnection自身问题,
|
||||
* 400类错误,会直接抛出异常。不能获取conn.getInputStream();
|
||||
*
|
||||
* @param conn
|
||||
* @return
|
||||
* @throws IOException
|
||||
* http请求错误
|
||||
* @throws DemoException
|
||||
* http 的状态码不是 200
|
||||
*/
|
||||
public static byte[] getResponseBytes(HttpURLConnection conn) throws IOException, DemoException {
|
||||
int responseCode = conn.getResponseCode();
|
||||
if (responseCode != 200) {
|
||||
System.err.println("http 请求返回的状态码错误,期望200, 当前是 " + responseCode);
|
||||
if (responseCode == 401) {
|
||||
System.err.println("可能是appkey appSecret 填错");
|
||||
}
|
||||
throw new DemoException("http response code is" + responseCode);
|
||||
}
|
||||
|
||||
InputStream inputStream = conn.getInputStream();
|
||||
byte[] result = getInputStreamContent(inputStream);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将InputStream内的内容全部读取,作为bytes返回
|
||||
*
|
||||
* @param is
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @see InputStream.read()
|
||||
*/
|
||||
public static byte[] getInputStreamContent(InputStream is) throws IOException {
|
||||
byte[] b = new byte[1024];
|
||||
// 定义一个输出流存储接收到的数据
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
// 开始接收数据
|
||||
int len = 0;
|
||||
while (true) {
|
||||
len = is.read(b);
|
||||
if (len == -1) {
|
||||
// 数据读完
|
||||
break;
|
||||
}
|
||||
byteArrayOutputStream.write(b, 0, len);
|
||||
}
|
||||
return byteArrayOutputStream.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
152
src/main/java/com/peanut/common/utils/Constant.java
Normal file
152
src/main/java/com/peanut/common/utils/Constant.java
Normal file
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
* <p>
|
||||
* https://www.renren.io
|
||||
* <p>
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.utils;
|
||||
|
||||
import com.peanut.common.validator.group.AliyunGroup;
|
||||
import com.peanut.common.validator.group.QcloudGroup;
|
||||
import com.peanut.common.validator.group.QiniuGroup;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* 常量
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class Constant {
|
||||
/**
|
||||
* 超级管理员ID
|
||||
*/
|
||||
public static final int SUPER_ADMIN = 1;
|
||||
/**
|
||||
* 当前页码
|
||||
*/
|
||||
public static final String PAGE = "page";
|
||||
/**
|
||||
* 每页显示记录数
|
||||
*/
|
||||
public static final String LIMIT = "limit";
|
||||
/**
|
||||
* 排序字段
|
||||
*/
|
||||
public static final String ORDER_FIELD = "sidx";
|
||||
/**
|
||||
* 排序方式
|
||||
*/
|
||||
public static final String ORDER = "order";
|
||||
/**
|
||||
* 升序
|
||||
*/
|
||||
public static final String ASC = "asc";
|
||||
|
||||
/**
|
||||
* 菜单类型
|
||||
*
|
||||
* @author chenshun
|
||||
* @email sunlightcs@gmail.com
|
||||
* @date 2016年11月15日 下午1:24:29
|
||||
*/
|
||||
public enum MenuType {
|
||||
/**
|
||||
* 目录
|
||||
*/
|
||||
CATALOG(0),
|
||||
/**
|
||||
* 菜单
|
||||
*/
|
||||
MENU(1),
|
||||
/**
|
||||
* 按钮
|
||||
*/
|
||||
BUTTON(2);
|
||||
|
||||
private int value;
|
||||
|
||||
MenuType(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 定时任务状态
|
||||
*
|
||||
* @author chenshun
|
||||
* @email sunlightcs@gmail.com
|
||||
* @date 2016年12月3日 上午12:07:22
|
||||
*/
|
||||
public enum ScheduleStatus {
|
||||
/**
|
||||
* 正常
|
||||
*/
|
||||
NORMAL(0),
|
||||
/**
|
||||
* 暂停
|
||||
*/
|
||||
PAUSE(1);
|
||||
|
||||
private int value;
|
||||
|
||||
ScheduleStatus(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 云服务商
|
||||
*/
|
||||
public enum CloudService {
|
||||
/**
|
||||
* 七牛云
|
||||
*/
|
||||
QINIU(1, QiniuGroup.class),
|
||||
/**
|
||||
* 阿里云
|
||||
*/
|
||||
ALIYUN(2, AliyunGroup.class),
|
||||
/**
|
||||
* 腾讯云
|
||||
*/
|
||||
QCLOUD(3, QcloudGroup.class);
|
||||
|
||||
private int value;
|
||||
|
||||
private Class<?> validatorGroupClass;
|
||||
|
||||
CloudService(int value, Class<?> validatorGroupClass) {
|
||||
this.value = value;
|
||||
this.validatorGroupClass = validatorGroupClass;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public Class<?> getValidatorGroupClass() {
|
||||
return this.validatorGroupClass;
|
||||
}
|
||||
|
||||
public static CloudService getByValue(Integer value) {
|
||||
Optional<CloudService> first = Stream.of(CloudService.values()).filter(cs -> value.equals(cs.value)).findFirst();
|
||||
if (!first.isPresent()) {
|
||||
throw new IllegalArgumentException("非法的枚举值:" + value);
|
||||
}
|
||||
return first.get();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.peanut.common.utils;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@PropertySource("classpath:application.properties") //变量名需要与配置文件相匹配
|
||||
public class ConstantPropertiesUtil implements InitializingBean {
|
||||
|
||||
@Value("${wx.open.app_id}")
|
||||
private String appId;
|
||||
|
||||
@Value("${wx.open.app_secret}")
|
||||
private String appSecret;
|
||||
|
||||
@Value("${wx.open.redirect_url}")
|
||||
private String redirectUrl;
|
||||
|
||||
public static String WX_OPEN_APP_ID;
|
||||
public static String WX_OPEN_APP_SECRET;
|
||||
public static String WX_OPEN_REDIRECT_URL;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
WX_OPEN_APP_ID = appId;
|
||||
WX_OPEN_APP_SECRET = appSecret;
|
||||
WX_OPEN_REDIRECT_URL = redirectUrl;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.peanut.common.utils;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
//当项目已启动,spring接口,spring加载之后,执行接口一个方法
|
||||
@Component
|
||||
public class ConstantPropertiesUtils implements InitializingBean {
|
||||
|
||||
//读取配置文件内容
|
||||
@Value("${aliyun.oss.file.endpoint}")
|
||||
private String endpoint;
|
||||
|
||||
@Value("${aliyun.oss.file.keyid}")
|
||||
private String keyId;
|
||||
|
||||
@Value("${aliyun.oss.file.keysecret}")
|
||||
private String keySecret;
|
||||
|
||||
@Value("${aliyun.oss.file.bucketname}")
|
||||
private String bucketName;
|
||||
|
||||
//定义公开静态常量
|
||||
public static String END_POIND;
|
||||
public static String ACCESS_KEY_ID;
|
||||
public static String ACCESS_KEY_SECRET;
|
||||
public static String BUCKET_NAME;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
END_POIND = endpoint;
|
||||
ACCESS_KEY_ID = keyId;
|
||||
ACCESS_KEY_SECRET = keySecret;
|
||||
BUCKET_NAME = bucketName;
|
||||
}
|
||||
}
|
||||
27
src/main/java/com/peanut/common/utils/CopyUtils.java
Normal file
27
src/main/java/com/peanut/common/utils/CopyUtils.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package com.peanut.common.utils;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.BeanWrapperImpl;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class CopyUtils {
|
||||
public static String[] getNullPropertyNames (Object source) {
|
||||
final BeanWrapper src = new BeanWrapperImpl(source);
|
||||
java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();
|
||||
|
||||
Set<String> emptyNames = new HashSet<String>();
|
||||
for(java.beans.PropertyDescriptor pd : pds) {
|
||||
Object srcValue = src.getPropertyValue(pd.getName());
|
||||
if (srcValue == null) emptyNames.add(pd.getName());
|
||||
}
|
||||
String[] result = new String[emptyNames.size()];
|
||||
return emptyNames.toArray(result);
|
||||
}
|
||||
|
||||
public static void copyProperties(Object src, Object target) {
|
||||
BeanUtils.copyProperties(src, target, getNullPropertyNames(src));
|
||||
}
|
||||
}
|
||||
37
src/main/java/com/peanut/common/utils/DateUtil.java
Normal file
37
src/main/java/com/peanut/common/utils/DateUtil.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package com.peanut.common.utils;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
public class DateUtil {
|
||||
/**
|
||||
* 判断当前时间是否在[startTime, endTime]区间,注意时间格式要一致
|
||||
*
|
||||
* @param nowTime 当前时间
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @return
|
||||
* @author jqlin
|
||||
*/
|
||||
public static boolean isEffectiveDate(Date nowTime, Date startTime, Date endTime) {
|
||||
if (nowTime.getTime() == startTime.getTime()
|
||||
|| nowTime.getTime() == endTime.getTime()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Calendar date = Calendar.getInstance();
|
||||
date.setTime(nowTime);
|
||||
|
||||
Calendar begin = Calendar.getInstance();
|
||||
begin.setTime(startTime);
|
||||
|
||||
Calendar end = Calendar.getInstance();
|
||||
end.setTime(endTime);
|
||||
|
||||
if (date.after(begin) && date.before(end)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
166
src/main/java/com/peanut/common/utils/DateUtils.java
Normal file
166
src/main/java/com/peanut/common/utils/DateUtils.java
Normal file
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.utils;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 日期处理
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class DateUtils {
|
||||
/** 时间格式(yyyy-MM-dd) */
|
||||
public final static String DATE_PATTERN = "yyyy-MM-dd";
|
||||
/** 时间格式(yyyy-MM-dd HH:mm:ss) */
|
||||
public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
|
||||
|
||||
/**
|
||||
* 日期格式化 日期格式为:yyyy-MM-dd
|
||||
* @param date 日期
|
||||
* @return 返回yyyy-MM-dd格式日期
|
||||
*/
|
||||
public static String format(Date date) {
|
||||
return format(date, DATE_PATTERN);
|
||||
}
|
||||
|
||||
/**
|
||||
* 日期格式化 日期格式为:yyyy-MM-dd
|
||||
* @param date 日期
|
||||
* @param pattern 格式,如:DateUtils.DATE_TIME_PATTERN
|
||||
* @return 返回yyyy-MM-dd格式日期
|
||||
*/
|
||||
public static String format(Date date, String pattern) {
|
||||
if(date != null){
|
||||
SimpleDateFormat df = new SimpleDateFormat(pattern);
|
||||
return df.format(date);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串转换成日期
|
||||
* @param strDate 日期字符串
|
||||
* @param pattern 日期的格式,如:DateUtils.DATE_TIME_PATTERN
|
||||
*/
|
||||
public static Date stringToDate(String strDate, String pattern) {
|
||||
if (StringUtils.isBlank(strDate)){
|
||||
return null;
|
||||
}
|
||||
|
||||
DateTimeFormatter fmt = DateTimeFormat.forPattern(pattern);
|
||||
return fmt.parseLocalDateTime(strDate).toDate();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据周数,获取开始日期、结束日期
|
||||
* @param week 周期 0本周,-1上周,-2上上周,1下周,2下下周
|
||||
* @return 返回date[0]开始日期、date[1]结束日期
|
||||
*/
|
||||
public static Date[] getWeekStartAndEnd(int week) {
|
||||
DateTime dateTime = new DateTime();
|
||||
LocalDate date = new LocalDate(dateTime.plusWeeks(week));
|
||||
|
||||
date = date.dayOfWeek().withMinimumValue();
|
||||
Date beginDate = date.toDate();
|
||||
Date endDate = date.plusDays(6).toDate();
|
||||
return new Date[]{beginDate, endDate};
|
||||
}
|
||||
|
||||
/**
|
||||
* 对日期的【秒】进行加/减
|
||||
*
|
||||
* @param date 日期
|
||||
* @param seconds 秒数,负数为减
|
||||
* @return 加/减几秒后的日期
|
||||
*/
|
||||
public static Date addDateSeconds(Date date, int seconds) {
|
||||
DateTime dateTime = new DateTime(date);
|
||||
return dateTime.plusSeconds(seconds).toDate();
|
||||
}
|
||||
|
||||
/**
|
||||
* 对日期的【分钟】进行加/减
|
||||
*
|
||||
* @param date 日期
|
||||
* @param minutes 分钟数,负数为减
|
||||
* @return 加/减几分钟后的日期
|
||||
*/
|
||||
public static Date addDateMinutes(Date date, int minutes) {
|
||||
DateTime dateTime = new DateTime(date);
|
||||
return dateTime.plusMinutes(minutes).toDate();
|
||||
}
|
||||
|
||||
/**
|
||||
* 对日期的【小时】进行加/减
|
||||
*
|
||||
* @param date 日期
|
||||
* @param hours 小时数,负数为减
|
||||
* @return 加/减几小时后的日期
|
||||
*/
|
||||
public static Date addDateHours(Date date, int hours) {
|
||||
DateTime dateTime = new DateTime(date);
|
||||
return dateTime.plusHours(hours).toDate();
|
||||
}
|
||||
|
||||
/**
|
||||
* 对日期的【天】进行加/减
|
||||
*
|
||||
* @param date 日期
|
||||
* @param days 天数,负数为减
|
||||
* @return 加/减几天后的日期
|
||||
*/
|
||||
public static Date addDateDays(Date date, int days) {
|
||||
DateTime dateTime = new DateTime(date);
|
||||
return dateTime.plusDays(days).toDate();
|
||||
}
|
||||
|
||||
/**
|
||||
* 对日期的【周】进行加/减
|
||||
*
|
||||
* @param date 日期
|
||||
* @param weeks 周数,负数为减
|
||||
* @return 加/减几周后的日期
|
||||
*/
|
||||
public static Date addDateWeeks(Date date, int weeks) {
|
||||
DateTime dateTime = new DateTime(date);
|
||||
return dateTime.plusWeeks(weeks).toDate();
|
||||
}
|
||||
|
||||
/**
|
||||
* 对日期的【月】进行加/减
|
||||
*
|
||||
* @param date 日期
|
||||
* @param months 月数,负数为减
|
||||
* @return 加/减几月后的日期
|
||||
*/
|
||||
public static Date addDateMonths(Date date, int months) {
|
||||
DateTime dateTime = new DateTime(date);
|
||||
return dateTime.plusMonths(months).toDate();
|
||||
}
|
||||
|
||||
/**
|
||||
* 对日期的【年】进行加/减
|
||||
*
|
||||
* @param date 日期
|
||||
* @param years 年数,负数为减
|
||||
* @return 加/减几年后的日期
|
||||
*/
|
||||
public static Date addDateYears(Date date, int years) {
|
||||
DateTime dateTime = new DateTime(date);
|
||||
return dateTime.plusYears(years).toDate();
|
||||
}
|
||||
}
|
||||
8
src/main/java/com/peanut/common/utils/DemoException.java
Normal file
8
src/main/java/com/peanut/common/utils/DemoException.java
Normal file
@@ -0,0 +1,8 @@
|
||||
package com.peanut.common.utils;
|
||||
|
||||
|
||||
public class DemoException extends Exception {
|
||||
public DemoException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
71
src/main/java/com/peanut/common/utils/FileDownloadUtil.java
Normal file
71
src/main/java/com/peanut/common/utils/FileDownloadUtil.java
Normal file
@@ -0,0 +1,71 @@
|
||||
package com.peanut.common.utils;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
public class FileDownloadUtil {
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @description: 从服务器获得一个输入流
|
||||
*/
|
||||
public static InputStream getInputStream(String urlPath) {
|
||||
InputStream inputStream = null;
|
||||
HttpURLConnection httpURLConnection = null;
|
||||
try {
|
||||
URL url = new URL(urlPath);
|
||||
httpURLConnection = (HttpURLConnection) url.openConnection();
|
||||
// 设置网络连接超时时间
|
||||
httpURLConnection.setConnectTimeout(3000);
|
||||
// 设置应用程序要从网络连接读取数据
|
||||
httpURLConnection.setDoInput(true);
|
||||
httpURLConnection.setRequestMethod("GET");
|
||||
int responseCode = httpURLConnection.getResponseCode();
|
||||
System.out.println("responseCode is:" + responseCode);
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
// 从服务器返回一个输入流
|
||||
inputStream = httpURLConnection.getInputStream();
|
||||
} else {
|
||||
inputStream = httpURLConnection.getErrorStream();
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resp
|
||||
* @param inputStream
|
||||
* @description: 将输入流输出到页面
|
||||
*/
|
||||
public static void writeFile(HttpServletResponse resp, InputStream inputStream) {
|
||||
OutputStream out = null;
|
||||
try {
|
||||
out = resp.getOutputStream();
|
||||
int len = 0;
|
||||
byte[] b = new byte[1024];
|
||||
while ((len = inputStream.read(b)) != -1) {
|
||||
out.write(b, 0, len);
|
||||
}
|
||||
out.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
if (out != null) {
|
||||
out.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
449
src/main/java/com/peanut/common/utils/HttpClientUtils.java
Normal file
449
src/main/java/com/peanut/common/utils/HttpClientUtils.java
Normal file
@@ -0,0 +1,449 @@
|
||||
package com.peanut.common.utils;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.http.Consts;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.config.RequestConfig.Builder;
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.conn.ConnectTimeoutException;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.conn.ssl.SSLContextBuilder;
|
||||
import org.apache.http.conn.ssl.TrustStrategy;
|
||||
import org.apache.http.conn.ssl.X509HostnameVerifier;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
public class HttpClientUtils {
|
||||
|
||||
public static final int connTimeout=10000;
|
||||
public static final int readTimeout=10000;
|
||||
public static final String charset="UTF-8";
|
||||
private static HttpClient client = null;
|
||||
private static final Logger log = LoggerFactory.getLogger(HttpClientUtils.class);
|
||||
|
||||
static {
|
||||
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
|
||||
cm.setMaxTotal(128);
|
||||
cm.setDefaultMaxPerRoute(128);
|
||||
client = HttpClients.custom().setConnectionManager(cm).build();
|
||||
}
|
||||
|
||||
public static String postParameters(String url, String parameterStr) throws ConnectTimeoutException, SocketTimeoutException, Exception{
|
||||
return post(url,parameterStr,"application/x-www-form-urlencoded",charset,connTimeout,readTimeout);
|
||||
}
|
||||
|
||||
public static String postParameters(String url, String parameterStr,String charset, Integer connTimeout, Integer readTimeout) throws ConnectTimeoutException, SocketTimeoutException, Exception{
|
||||
return post(url,parameterStr,"application/x-www-form-urlencoded",charset,connTimeout,readTimeout);
|
||||
}
|
||||
|
||||
public static String postParameters(String url, Map<String, Object> params) throws ConnectTimeoutException,
|
||||
SocketTimeoutException, Exception {
|
||||
return postForm(url, params, null, connTimeout, readTimeout);
|
||||
}
|
||||
|
||||
public static String postParameters(String url, Map<String, Object> params, Integer connTimeout,Integer readTimeout) throws ConnectTimeoutException,
|
||||
SocketTimeoutException, Exception {
|
||||
return postForm(url, params, null, connTimeout, readTimeout);
|
||||
}
|
||||
|
||||
public static String get(String url) throws Exception {
|
||||
return get(url, charset, null, null);
|
||||
}
|
||||
|
||||
public static String get(String url, String charset) throws Exception {
|
||||
return get(url, charset, connTimeout, readTimeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送一个 Post 请求, 使用指定的字符集编码.
|
||||
*
|
||||
* @param url
|
||||
* @param body RequestBody
|
||||
* @param mimeType 例如 application/xml "application/x-www-form-urlencoded" a=1&b=2&c=3
|
||||
* @param charset 编码
|
||||
* @param connTimeout 建立链接超时时间,毫秒.
|
||||
* @param readTimeout 响应超时时间,毫秒.
|
||||
* @return ResponseBody, 使用指定的字符集编码.
|
||||
* @throws ConnectTimeoutException 建立链接超时异常
|
||||
* @throws SocketTimeoutException 响应超时
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String post(String url, String body, String mimeType,String charset, Integer connTimeout, Integer readTimeout)
|
||||
throws ConnectTimeoutException, SocketTimeoutException, Exception {
|
||||
HttpClient client = null;
|
||||
HttpPost post = new HttpPost(url);
|
||||
String result = "";
|
||||
try {
|
||||
if (StringUtils.isNotBlank(body)) {
|
||||
HttpEntity entity = new StringEntity(body, ContentType.create(mimeType, charset));
|
||||
post.setEntity(entity);
|
||||
}
|
||||
// 设置参数
|
||||
Builder customReqConf = RequestConfig.custom();
|
||||
if (connTimeout != null) {
|
||||
customReqConf.setConnectTimeout(connTimeout);
|
||||
}
|
||||
if (readTimeout != null) {
|
||||
customReqConf.setSocketTimeout(readTimeout);
|
||||
}
|
||||
post.setConfig(customReqConf.build());
|
||||
|
||||
HttpResponse res;
|
||||
if (url.startsWith("https")) {
|
||||
// 执行 Https 请求.
|
||||
client = createSSLInsecureClient();
|
||||
res = client.execute(post);
|
||||
} else {
|
||||
// 执行 Http 请求.
|
||||
client = HttpClientUtils.client;
|
||||
res = client.execute(post);
|
||||
}
|
||||
result = IOUtils.toString(res.getEntity().getContent(), charset);
|
||||
} finally {
|
||||
post.releaseConnection();
|
||||
if (url.startsWith("https") && client != null&& client instanceof CloseableHttpClient) {
|
||||
((CloseableHttpClient) client).close();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 提交form表单
|
||||
*
|
||||
* @param url
|
||||
* @param params
|
||||
* @param connTimeout
|
||||
* @param readTimeout
|
||||
* @return
|
||||
* @throws ConnectTimeoutException
|
||||
* @throws SocketTimeoutException
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String postForm(String url, Map<String, Object> params, Map<String, String> headers, Integer connTimeout,Integer readTimeout) throws ConnectTimeoutException,
|
||||
SocketTimeoutException, Exception {
|
||||
|
||||
HttpClient client = null;
|
||||
HttpPost post = new HttpPost(url);
|
||||
try {
|
||||
if (params != null && !params.isEmpty()) {
|
||||
List<NameValuePair> formParams = new ArrayList<NameValuePair>();
|
||||
Set<Entry<String, Object>> entrySet = params.entrySet();
|
||||
for (Entry<String, Object> entry : entrySet) {
|
||||
formParams.add(new BasicNameValuePair(entry.getKey(), entry.toString()));
|
||||
}
|
||||
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formParams, Consts.UTF_8);
|
||||
post.setEntity(entity);
|
||||
}
|
||||
|
||||
if (headers != null && !headers.isEmpty()) {
|
||||
for (Entry<String, String> entry : headers.entrySet()) {
|
||||
post.addHeader(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
// 设置参数
|
||||
Builder customReqConf = RequestConfig.custom();
|
||||
if (connTimeout != null) {
|
||||
customReqConf.setConnectTimeout(connTimeout);
|
||||
}
|
||||
if (readTimeout != null) {
|
||||
customReqConf.setSocketTimeout(readTimeout);
|
||||
}
|
||||
post.setConfig(customReqConf.build());
|
||||
HttpResponse res = null;
|
||||
if (url.startsWith("https")) {
|
||||
// 执行 Https 请求.
|
||||
client = createSSLInsecureClient();
|
||||
res = client.execute(post);
|
||||
} else {
|
||||
// 执行 Http 请求.
|
||||
client = HttpClientUtils.client;
|
||||
res = client.execute(post);
|
||||
}
|
||||
return IOUtils.toString(res.getEntity().getContent(), "UTF-8");
|
||||
} finally {
|
||||
post.releaseConnection();
|
||||
if (url.startsWith("https") && client != null
|
||||
&& client instanceof CloseableHttpClient) {
|
||||
((CloseableHttpClient) client).close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送一个 GET 请求
|
||||
*/
|
||||
public static String get(String url, String charset, Integer connTimeout,Integer readTimeout)
|
||||
throws ConnectTimeoutException,SocketTimeoutException, Exception {
|
||||
|
||||
HttpClient client = null;
|
||||
HttpGet get = new HttpGet(url);
|
||||
String result = "";
|
||||
try {
|
||||
// 设置参数
|
||||
Builder customReqConf = RequestConfig.custom();
|
||||
if (connTimeout != null) {
|
||||
customReqConf.setConnectTimeout(connTimeout);
|
||||
}
|
||||
if (readTimeout != null) {
|
||||
customReqConf.setSocketTimeout(readTimeout);
|
||||
}
|
||||
get.setConfig(customReqConf.build());
|
||||
|
||||
HttpResponse res = null;
|
||||
|
||||
if (url.startsWith("https")) {
|
||||
// 执行 Https 请求.
|
||||
client = createSSLInsecureClient();
|
||||
res = client.execute(get);
|
||||
} else {
|
||||
// 执行 Http 请求.
|
||||
client = HttpClientUtils.client;
|
||||
res = client.execute(get);
|
||||
}
|
||||
|
||||
result = IOUtils.toString(res.getEntity().getContent(), charset);
|
||||
} finally {
|
||||
get.releaseConnection();
|
||||
if (url.startsWith("https") && client != null && client instanceof CloseableHttpClient) {
|
||||
((CloseableHttpClient) client).close();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 response 里获取 charset
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private static String getCharsetFromResponse(HttpResponse ressponse) {
|
||||
// Content-Type:text/html; charset=GBK
|
||||
if (ressponse.getEntity() != null && ressponse.getEntity().getContentType() != null && ressponse.getEntity().getContentType().getValue() != null) {
|
||||
String contentType = ressponse.getEntity().getContentType().getValue();
|
||||
if (contentType.contains("charset=")) {
|
||||
return contentType.substring(contentType.indexOf("charset=") + 8);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 SSL连接
|
||||
* @return
|
||||
* @throws GeneralSecurityException
|
||||
*/
|
||||
private static CloseableHttpClient createSSLInsecureClient() throws GeneralSecurityException {
|
||||
try {
|
||||
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
|
||||
public boolean isTrusted(X509Certificate[] chain,String authType) throws CertificateException {
|
||||
return true;
|
||||
}
|
||||
}).build();
|
||||
|
||||
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new X509HostnameVerifier() {
|
||||
|
||||
@Override
|
||||
public boolean verify(String arg0, SSLSession arg1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void verify(String host, SSLSocket ssl)
|
||||
throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void verify(String host, X509Certificate cert)
|
||||
throws SSLException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void verify(String host, String[] cns,
|
||||
String[] subjectAlts) throws SSLException {
|
||||
}
|
||||
});
|
||||
return HttpClients.custom().setSSLSocketFactory(sslsf).build();
|
||||
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 向指定 URL 发送POST方法的请求
|
||||
*
|
||||
* @param url 发送请求的 URL
|
||||
* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
|
||||
* @return 所代表远程资源的响应结果
|
||||
*/
|
||||
public static String sendPost(String url, String param)
|
||||
{
|
||||
PrintWriter out = null;
|
||||
BufferedReader in = null;
|
||||
StringBuilder result = new StringBuilder();
|
||||
try
|
||||
{
|
||||
log.info("sendPost - {}", url);
|
||||
URL realUrl = new URL(url);
|
||||
URLConnection conn = realUrl.openConnection();
|
||||
conn.setRequestProperty("accept", "*/*");
|
||||
conn.setRequestProperty("connection", "Keep-Alive");
|
||||
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
|
||||
conn.setRequestProperty("Accept-Charset", "utf-8");
|
||||
conn.setRequestProperty("contentType", "utf-8");
|
||||
conn.setDoOutput(true);
|
||||
conn.setDoInput(true);
|
||||
out = new PrintWriter(conn.getOutputStream());
|
||||
out.print(param);
|
||||
out.flush();
|
||||
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
|
||||
String line;
|
||||
while ((line = in.readLine()) != null)
|
||||
{
|
||||
result.append(line);
|
||||
}
|
||||
log.info("recv - {}", result);
|
||||
}
|
||||
catch (ConnectException e)
|
||||
{
|
||||
log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
|
||||
}
|
||||
catch (SocketTimeoutException e)
|
||||
{
|
||||
log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
if (out != null)
|
||||
{
|
||||
out.close();
|
||||
}
|
||||
if (in != null)
|
||||
{
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 快递鸟向指定 URL 发送POST方法的请求
|
||||
* url 发送请求的 URL
|
||||
* params 请求的参数集合
|
||||
* @return 远程资源的响应结果
|
||||
*/
|
||||
public static String kdSendPost(String url, Map<String, String> params) {
|
||||
OutputStreamWriter out = null;
|
||||
BufferedReader in = null;
|
||||
StringBuilder result = new StringBuilder();
|
||||
try {
|
||||
URL realUrl = new URL(url);
|
||||
HttpURLConnection conn =(HttpURLConnection) realUrl.openConnection();
|
||||
// 发送POST请求必须设置如下两行
|
||||
conn.setDoOutput(true);
|
||||
conn.setDoInput(true);
|
||||
// POST方法
|
||||
conn.setRequestMethod("POST");
|
||||
// 设置通用的请求属性
|
||||
conn.setRequestProperty("accept", "*/*");
|
||||
conn.setRequestProperty("connection", "Keep-Alive");
|
||||
conn.setRequestProperty("user-agent",
|
||||
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
|
||||
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
conn.connect();
|
||||
// 获取URLConnection对象对应的输出流
|
||||
out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
|
||||
// 发送请求参数
|
||||
if (params != null) {
|
||||
StringBuilder param = new StringBuilder();
|
||||
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||
if(param.length()>0){
|
||||
param.append("&");
|
||||
}
|
||||
param.append(entry.getKey());
|
||||
param.append("=");
|
||||
param.append(entry.getValue());
|
||||
log.info(entry.getKey()+":"+entry.getValue());
|
||||
}
|
||||
log.info("param:"+param.toString());
|
||||
out.write(param.toString());
|
||||
}
|
||||
// flush输出流的缓冲
|
||||
out.flush();
|
||||
// 定义BufferedReader输入流来读取URL的响应
|
||||
in = new BufferedReader(
|
||||
new InputStreamReader(conn.getInputStream(), "UTF-8"));
|
||||
String line;
|
||||
while ((line = in.readLine()) != null) {
|
||||
result.append(line);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//使用finally块来关闭输出流、输入流
|
||||
finally{
|
||||
try{
|
||||
if(out!=null){
|
||||
out.close();
|
||||
}
|
||||
if(in!=null){
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
catch(IOException ex){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
32
src/main/java/com/peanut/common/utils/HttpContextUtils.java
Normal file
32
src/main/java/com/peanut/common/utils/HttpContextUtils.java
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.utils;
|
||||
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
public class HttpContextUtils {
|
||||
|
||||
public static HttpServletRequest getHttpServletRequest() {
|
||||
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||
}
|
||||
|
||||
public static String getDomain(){
|
||||
HttpServletRequest request = getHttpServletRequest();
|
||||
StringBuffer url = request.getRequestURL();
|
||||
return url.delete(url.length() - request.getRequestURI().length(), url.length()).toString();
|
||||
}
|
||||
|
||||
public static String getOrigin(){
|
||||
HttpServletRequest request = getHttpServletRequest();
|
||||
return request.getHeader("Origin");
|
||||
}
|
||||
}
|
||||
64
src/main/java/com/peanut/common/utils/IPUtils.java
Normal file
64
src/main/java/com/peanut/common/utils/IPUtils.java
Normal file
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.utils;
|
||||
|
||||
import com.alibaba.druid.util.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* IP地址
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class IPUtils {
|
||||
private static Logger logger = LoggerFactory.getLogger(IPUtils.class);
|
||||
|
||||
/**
|
||||
* 获取IP地址
|
||||
*
|
||||
* 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址
|
||||
* 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址
|
||||
*/
|
||||
public static String getIpAddr(HttpServletRequest request) {
|
||||
String ip = null;
|
||||
try {
|
||||
ip = request.getHeader("x-forwarded-for");
|
||||
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("Proxy-Client-IP");
|
||||
}
|
||||
if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("WL-Proxy-Client-IP");
|
||||
}
|
||||
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("HTTP_CLIENT_IP");
|
||||
}
|
||||
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
|
||||
}
|
||||
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
|
||||
ip = request.getRemoteAddr();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("IPUtils ERROR ", e);
|
||||
}
|
||||
|
||||
// //使用代理,则获取第一个IP地址
|
||||
// if(StringUtils.isEmpty(ip) && ip.length() > 15) {
|
||||
// if(ip.indexOf(",") > 0) {
|
||||
// ip = ip.substring(0, ip.indexOf(","));
|
||||
// }
|
||||
// }
|
||||
|
||||
return ip;
|
||||
}
|
||||
|
||||
}
|
||||
67
src/main/java/com/peanut/common/utils/KdUtils.java
Normal file
67
src/main/java/com/peanut/common/utils/KdUtils.java
Normal file
@@ -0,0 +1,67 @@
|
||||
package com.peanut.common.utils;
|
||||
|
||||
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.security.MessageDigest;
|
||||
|
||||
public class KdUtils {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* MD5加密
|
||||
* str 内容
|
||||
* charset 编码方式
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String MD5(String str, String charset) throws Exception {
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
md.update(str.getBytes(charset));
|
||||
byte[] result = md.digest();
|
||||
StringBuffer sb = new StringBuffer(32);
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
int val = result[i] & 0xff;
|
||||
if (val <= 0xf) {
|
||||
sb.append("0");
|
||||
}
|
||||
sb.append(Integer.toHexString(val));
|
||||
}
|
||||
return sb.toString().toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* base64编码
|
||||
* str 内容
|
||||
* charset 编码方式
|
||||
* @throws UnsupportedEncodingException
|
||||
*/
|
||||
public static String base64(String str, String charset) throws UnsupportedEncodingException{
|
||||
String encoded = Base64.encode(str.getBytes(charset));
|
||||
return encoded;
|
||||
}
|
||||
|
||||
public static String urlEncoder(String str, String charset) throws UnsupportedEncodingException{
|
||||
String result = URLEncoder.encode(str, charset);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 电商Sign签名生成
|
||||
* content 内容
|
||||
* keyValue ApiKey
|
||||
* charset 编码方式
|
||||
* @throws UnsupportedEncodingException ,Exception
|
||||
* @return DataSign签名
|
||||
*/
|
||||
public static String encrypt (String content, String keyValue, String charset) throws UnsupportedEncodingException, Exception
|
||||
{
|
||||
if (keyValue != null)
|
||||
{
|
||||
return base64(MD5(content + keyValue, charset), charset);
|
||||
}
|
||||
return base64(MD5(content, charset), charset);
|
||||
}
|
||||
|
||||
}
|
||||
45
src/main/java/com/peanut/common/utils/MD5Util.java
Normal file
45
src/main/java/com/peanut/common/utils/MD5Util.java
Normal file
@@ -0,0 +1,45 @@
|
||||
package com.peanut.common.utils;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
public class MD5Util {
|
||||
|
||||
private static MessageDigest mdigest = null;
|
||||
private static char digits[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
|
||||
private static MessageDigest getMdInst(){
|
||||
if(null == mdigest){
|
||||
try{
|
||||
mdigest = MessageDigest.getInstance("MD5");
|
||||
}catch(NoSuchAlgorithmException e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return mdigest;
|
||||
}
|
||||
|
||||
public static String encode(String s){
|
||||
if(null == s){
|
||||
return "";
|
||||
}
|
||||
|
||||
try{
|
||||
byte[] bytes = s.getBytes();
|
||||
getMdInst().update(bytes);
|
||||
byte[] md = getMdInst().digest();
|
||||
int j = md.length;
|
||||
char str[] = new char[j * 2];
|
||||
int k = 0;
|
||||
for(int i = 0; i < j; i++) {
|
||||
byte byte0 = md[i];
|
||||
str[k++] = digits[byte0 >>> 4 & 0xf];
|
||||
str[k++] = digits[byte0 & 0xf];
|
||||
}
|
||||
return new String(str);
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
255
src/main/java/com/peanut/common/utils/MD5Utils.java
Normal file
255
src/main/java/com/peanut/common/utils/MD5Utils.java
Normal file
@@ -0,0 +1,255 @@
|
||||
package com.peanut.common.utils;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Random;
|
||||
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
|
||||
/**
|
||||
* @author hh@163.com:
|
||||
* @version 创建时间:2018-3-20 下午2:40:13
|
||||
* @introduction
|
||||
*/
|
||||
public class MD5Utils {
|
||||
|
||||
/**
|
||||
* 普通MD5加密 01
|
||||
* <p>
|
||||
*
|
||||
* @Title : getStrMD5
|
||||
* </p>
|
||||
* <p>
|
||||
* @Description : TODO
|
||||
* </p>
|
||||
* <p>
|
||||
* @Author : HuaZai
|
||||
* </p>
|
||||
* <p>
|
||||
* @Date : 2017年12月26日 下午2:49:44
|
||||
* </p>
|
||||
*/
|
||||
public static String getStrMD5(String inStr) {
|
||||
// 获取MD5实例
|
||||
MessageDigest md5 = null;
|
||||
try {
|
||||
md5 = MessageDigest.getInstance("MD5");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
System.out.println(e.toString());
|
||||
return "";
|
||||
}
|
||||
|
||||
// 将加密字符串转换为字符数组
|
||||
char[] charArray = inStr.toCharArray();
|
||||
byte[] byteArray = new byte[charArray.length];
|
||||
|
||||
// 开始加密
|
||||
for (int i = 0; i < charArray.length; i++)
|
||||
byteArray[i] = (byte) charArray[i];
|
||||
byte[] digest = md5.digest(byteArray);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < digest.length; i++) {
|
||||
int var = digest[i] & 0xff;
|
||||
if (var < 16)
|
||||
sb.append("0");
|
||||
sb.append(Integer.toHexString(var));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 普通MD5加密 02
|
||||
* <p>
|
||||
*
|
||||
* @Title : getStrrMD5
|
||||
* </p>
|
||||
* <p>
|
||||
* @Description : TODO
|
||||
* </p>
|
||||
* <p>
|
||||
* @Author : HuaZai
|
||||
* </p>
|
||||
* <p>
|
||||
* @Date : 2017年12月27日 上午11:18:39
|
||||
* </p>
|
||||
*/
|
||||
public static String getStrrMD5(String password) {
|
||||
|
||||
char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
|
||||
try {
|
||||
byte strTemp[] = password.getBytes("UTF-8");
|
||||
MessageDigest mdTemp = MessageDigest.getInstance("MD5");
|
||||
mdTemp.update(strTemp);
|
||||
byte md[] = mdTemp.digest();
|
||||
int j = md.length;
|
||||
char str[] = new char[j * 2];
|
||||
int k = 0;
|
||||
for (int i = 0; i < j; i++) {
|
||||
byte byte0 = md[i];
|
||||
str[k++] = hexDigits[byte0 >>> 4 & 15];
|
||||
str[k++] = hexDigits[byte0 & 15];
|
||||
}
|
||||
|
||||
return new String(str);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* MD5双重解密
|
||||
* <p>
|
||||
*
|
||||
* @Title : getconvertMD5
|
||||
* </p>
|
||||
* <p>
|
||||
* @Description : TODO
|
||||
* </p>
|
||||
* <p>
|
||||
* @Author : HuaZai
|
||||
* </p>
|
||||
* <p>
|
||||
* @Date : 2017年12月26日 下午3:34:17
|
||||
* </p>
|
||||
*/
|
||||
public static String getconvertMD5(String inStr) {
|
||||
char[] charArray = inStr.toCharArray();
|
||||
for (int i = 0; i < charArray.length; i++) {
|
||||
charArray[i] = (char) (charArray[i] ^ 't');
|
||||
}
|
||||
String str = String.valueOf(charArray);
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用Apache的Hex类实现Hex(16进制字符串和)和字节数组的互转
|
||||
* <p>
|
||||
*
|
||||
* @Title : md5Hex
|
||||
* </p>
|
||||
* <p>
|
||||
* @Description : TODO
|
||||
* </p>
|
||||
* <p>
|
||||
* @Author : HuaZai
|
||||
* </p>
|
||||
* <p>
|
||||
* @Date : 2017年12月27日 上午11:28:25
|
||||
* </p>
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private static String md5Hex(String str) {
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
byte[] digest = md.digest(str.getBytes());
|
||||
return new String(new Hex().encode(digest));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.out.println(e.toString());
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加盐MD5加密
|
||||
* <p>
|
||||
*
|
||||
* @Title : getSaltMD5
|
||||
* </p>
|
||||
* <p>
|
||||
* @Description : TODO
|
||||
* </p>
|
||||
* <p>
|
||||
* @Author : HuaZai
|
||||
* </p>
|
||||
* <p>
|
||||
* @Date : 2017年12月27日 上午11:21:00
|
||||
* </p>
|
||||
*/
|
||||
public static String getSaltMD5(String password) {
|
||||
// 生成一个16位的随机数
|
||||
Random random = new Random();
|
||||
StringBuilder sBuilder = new StringBuilder(16);
|
||||
sBuilder.append(random.nextInt(99999999)).append(random.nextInt(99999999));
|
||||
int len = sBuilder.length();
|
||||
if (len < 16) {
|
||||
for (int i = 0; i < 16 - len; i++) {
|
||||
sBuilder.append("0");
|
||||
}
|
||||
}
|
||||
// 生成最终的加密盐
|
||||
String Salt = sBuilder.toString();
|
||||
password = md5Hex(password + Salt);
|
||||
char[] cs = new char[48];
|
||||
for (int i = 0; i < 48; i += 3) {
|
||||
cs[i] = password.charAt(i / 3 * 2);
|
||||
char c = Salt.charAt(i / 3);
|
||||
cs[i + 1] = c;
|
||||
cs[i + 2] = password.charAt(i / 3 * 2 + 1);
|
||||
}
|
||||
return String.valueOf(cs);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证加盐后是否和原文一致
|
||||
* <p>
|
||||
*
|
||||
* @Title : verifyMD5
|
||||
* </p>
|
||||
* <p>
|
||||
* @Description : TODO
|
||||
* </p>
|
||||
* <p>
|
||||
* @Author : HuaZai
|
||||
* </p>
|
||||
* <p>
|
||||
* @Date : 2017年12月27日 下午2:22:22
|
||||
* </p>
|
||||
*/
|
||||
public static boolean getSaltverifyMD5(String password, String md5str) {
|
||||
char[] cs1 = new char[32];
|
||||
char[] cs2 = new char[16];
|
||||
for (int i = 0; i < 48; i += 3) {
|
||||
cs1[i / 3 * 2] = md5str.charAt(i);
|
||||
cs1[i / 3 * 2 + 1] = md5str.charAt(i + 2);
|
||||
cs2[i / 3] = md5str.charAt(i + 1);
|
||||
}
|
||||
String Salt = new String(cs2);
|
||||
return md5Hex(password + Salt).equals(String.valueOf(cs1));
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
MD5Utils md = new MD5Utils();
|
||||
String strMD5 = new String("12345");
|
||||
|
||||
System.out.println("原始:" + strMD5);
|
||||
System.out.println("东东的:" + md.getStrrMD5(strMD5));
|
||||
System.out.println("MD5后:" + md.getStrMD5(strMD5));
|
||||
System.out.println("加密的:" + md.getconvertMD5(strMD5));
|
||||
System.out.println("解密的:" + md.getconvertMD5(md.getconvertMD5(strMD5)));
|
||||
|
||||
System.out.println("\t\t=======================================");
|
||||
// 原文
|
||||
String plaintext = "huazai";
|
||||
// plaintext = "123456";
|
||||
System.out.println("原始:" + plaintext);
|
||||
System.out.println("普通MD5后:" + MD5Utils.getStrMD5(plaintext));
|
||||
|
||||
// 获取加盐后的MD5值
|
||||
String ciphertext = MD5Utils.getSaltMD5(plaintext);
|
||||
System.out.println("加盐后MD5:" + ciphertext);
|
||||
System.out.println("是否是同一字符串:" + MD5Utils.getSaltverifyMD5(plaintext, ciphertext));
|
||||
/**
|
||||
* 其中某次DingSai字符串的MD5值
|
||||
*/
|
||||
String[] tempSalt = { "810e1ee9ee5e28188658f431451a29c2d81048de6a108e8a",
|
||||
"66db82d9da2e35c95416471a147d12e46925d38e1185c043",
|
||||
"61a718e4c15d914504a41d95230087a51816632183732b5a" };
|
||||
|
||||
for (String temp : tempSalt) {
|
||||
System.out.println("是否是同一字符串:" + MD5Utils.getSaltverifyMD5(plaintext, temp));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
26
src/main/java/com/peanut/common/utils/MapUtils.java
Normal file
26
src/main/java/com/peanut/common/utils/MapUtils.java
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.utils;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
|
||||
/**
|
||||
* Map工具类
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class MapUtils extends HashMap<String, Object> {
|
||||
|
||||
@Override
|
||||
public MapUtils put(String key, Object value) {
|
||||
super.put(key, value);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.peanut.common.utils;
|
||||
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import org.apache.ibatis.reflection.MetaObject;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Component
|
||||
public class MyMetaObjectHandler implements MetaObjectHandler {
|
||||
@Override
|
||||
public void insertFill(MetaObject metaObject) {
|
||||
this.setFieldValByName("createTime", new Date(), metaObject);
|
||||
this.setFieldValByName("updateTime", new Date(), metaObject);
|
||||
this.setFieldValByName("successTime", new Date(), metaObject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFill(MetaObject metaObject) {
|
||||
this.setFieldValByName("updateTime", new Date(), metaObject);
|
||||
this.setFieldValByName("successTime", new Date(), metaObject);
|
||||
this.setFieldValByName("payTime", new Date(), metaObject);
|
||||
}
|
||||
}
|
||||
115
src/main/java/com/peanut/common/utils/OrderUtils.java
Normal file
115
src/main/java/com/peanut/common/utils/OrderUtils.java
Normal file
@@ -0,0 +1,115 @@
|
||||
package com.peanut.common.utils;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* * 订单编码生成器,生成32位数字编码,
|
||||
* * @生成规则 1位单号类型+17位时间戳+14位(用户id加密&随机数)
|
||||
*/
|
||||
public class OrderUtils {
|
||||
/**
|
||||
* 订单类别头
|
||||
*/
|
||||
|
||||
private static final String ORDER_CODE = "";
|
||||
/**
|
||||
* 退货类别头
|
||||
*/
|
||||
|
||||
private static final String RETURN_ORDER = "";
|
||||
/**
|
||||
* 退款类别头
|
||||
*/
|
||||
|
||||
private static final String REFUND_ORDER = "";
|
||||
|
||||
|
||||
/**
|
||||
* 随即编码
|
||||
*/
|
||||
|
||||
private static final int[] r = new int[]{7, 9, 6, 2, 8, 1, 3, 0, 5, 4};
|
||||
/**
|
||||
* 用户id和随机数总长度
|
||||
*/
|
||||
|
||||
private static final int maxLength = 14;
|
||||
|
||||
/**
|
||||
* 根据id进行加密+加随机数组成固定长度编码
|
||||
*/
|
||||
private static String toCode(Integer userId) {
|
||||
String idStr = userId.toString();
|
||||
StringBuilder idsbs = new StringBuilder();
|
||||
for (int i = idStr.length() - 1; i >= 0; i--) {
|
||||
idsbs.append(r[idStr.charAt(i) - '0']);
|
||||
}
|
||||
return idsbs.append(getRandom(maxLength - idStr.length())).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成时间戳
|
||||
*/
|
||||
private static String getDateTime() {
|
||||
DateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
|
||||
return sdf.format(new Date());
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成固定长度随机码
|
||||
*
|
||||
* @param n 长度
|
||||
*/
|
||||
|
||||
private static long getRandom(long n) {
|
||||
long min = 1, max = 9;
|
||||
for (int i = 1; i < n; i++) {
|
||||
min *= 10;
|
||||
max *= 10;
|
||||
}
|
||||
long rangeLong = (((long) (new Random().nextDouble() * (max - min)))) + min;
|
||||
return rangeLong;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成不带类别标头的编码
|
||||
*
|
||||
* @param userId
|
||||
*/
|
||||
private static synchronized String getCode(Integer userId) {
|
||||
userId = userId == null ? 10000 : userId;
|
||||
return getDateTime() + toCode(userId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成订单单号编码(调用方法)
|
||||
* @param userId 网站中该用户唯一ID 防止重复
|
||||
*/
|
||||
|
||||
public static String getOrderCode(Integer userId) {
|
||||
return ORDER_CODE + getCode(userId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成退货单号编码(调用方法)
|
||||
* @param userId 网站中该用户唯一ID 防止重复
|
||||
*/
|
||||
public static String getReturnCode(Integer userId) {
|
||||
return RETURN_ORDER + getCode(userId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成退款单号编码(调用方法)
|
||||
* @param userId 网站中该用户唯一ID 防止重复
|
||||
*/
|
||||
public static String getRefundCode(Integer userId) {
|
||||
return REFUND_ORDER + getCode(userId);
|
||||
}
|
||||
}
|
||||
110
src/main/java/com/peanut/common/utils/PageUtils.java
Normal file
110
src/main/java/com/peanut/common/utils/PageUtils.java
Normal file
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.utils;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分页工具类
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class PageUtils implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
* 总记录数
|
||||
*/
|
||||
private int totalCount;
|
||||
/**
|
||||
* 每页记录数
|
||||
*/
|
||||
private int pageSize;
|
||||
/**
|
||||
* 总页数
|
||||
*/
|
||||
private int totalPage;
|
||||
/**
|
||||
* 当前页数
|
||||
*/
|
||||
private int currPage;
|
||||
/**
|
||||
* 列表数据
|
||||
*/
|
||||
private List<?> list;
|
||||
|
||||
/**
|
||||
* 分页
|
||||
* @param list 列表数据
|
||||
* @param totalCount 总记录数
|
||||
* @param pageSize 每页记录数
|
||||
* @param currPage 当前页数
|
||||
*/
|
||||
public PageUtils(List<?> list, int totalCount, int pageSize, int currPage) {
|
||||
this.list = list;
|
||||
this.totalCount = totalCount;
|
||||
this.pageSize = pageSize;
|
||||
this.currPage = currPage;
|
||||
this.totalPage = (int)Math.ceil((double)totalCount/pageSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页
|
||||
*/
|
||||
public PageUtils(IPage<?> page) {
|
||||
this.list = page.getRecords();
|
||||
this.totalCount = (int)page.getTotal();
|
||||
this.pageSize = (int)page.getSize();
|
||||
this.currPage = (int)page.getCurrent();
|
||||
this.totalPage = (int)page.getPages();
|
||||
}
|
||||
|
||||
public int getTotalCount() {
|
||||
return totalCount;
|
||||
}
|
||||
|
||||
public void setTotalCount(int totalCount) {
|
||||
this.totalCount = totalCount;
|
||||
}
|
||||
|
||||
public int getPageSize() {
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
public void setPageSize(int pageSize) {
|
||||
this.pageSize = pageSize;
|
||||
}
|
||||
|
||||
public int getTotalPage() {
|
||||
return totalPage;
|
||||
}
|
||||
|
||||
public void setTotalPage(int totalPage) {
|
||||
this.totalPage = totalPage;
|
||||
}
|
||||
|
||||
public int getCurrPage() {
|
||||
return currPage;
|
||||
}
|
||||
|
||||
public void setCurrPage(int currPage) {
|
||||
this.currPage = currPage;
|
||||
}
|
||||
|
||||
public List<?> getList() {
|
||||
return list;
|
||||
}
|
||||
|
||||
public void setList(List<?> list) {
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
}
|
||||
77
src/main/java/com/peanut/common/utils/Query.java
Normal file
77
src/main/java/com/peanut/common/utils/Query.java
Normal file
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.utils;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.metadata.OrderItem;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.peanut.common.xss.SQLFilter;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 查询参数
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class Query<T> {
|
||||
|
||||
public IPage<T> getPage(Map<String, Object> params) {
|
||||
return this.getPage(params, null, false);
|
||||
}
|
||||
|
||||
public IPage<T> getPage(Map<String, Object> params, String defaultOrderField, boolean isAsc) {
|
||||
//分页参数
|
||||
long curPage = 1;
|
||||
long limit = 10;
|
||||
|
||||
if(params.get(Constant.PAGE) != null){
|
||||
curPage = Long.parseLong((String)params.get(Constant.PAGE));
|
||||
}
|
||||
if(params.get(Constant.LIMIT) != null){
|
||||
limit = Long.parseLong((String)params.get(Constant.LIMIT));
|
||||
}
|
||||
|
||||
//分页对象
|
||||
Page<T> page = new Page<>(curPage, limit);
|
||||
|
||||
//分页参数
|
||||
params.put(Constant.PAGE, page);
|
||||
|
||||
//排序字段
|
||||
//防止SQL注入(因为sidx、order是通过拼接SQL实现排序的,会有SQL注入风险)
|
||||
String orderField = SQLFilter.sqlInject((String)params.get(Constant.ORDER_FIELD));
|
||||
String order = (String)params.get(Constant.ORDER);
|
||||
|
||||
|
||||
//前端字段排序
|
||||
if(StringUtils.isNotEmpty(orderField) && StringUtils.isNotEmpty(order)){
|
||||
if(Constant.ASC.equalsIgnoreCase(order)) {
|
||||
return page.addOrder(OrderItem.asc(orderField));
|
||||
}else {
|
||||
return page.addOrder(OrderItem.desc(orderField));
|
||||
}
|
||||
}
|
||||
|
||||
//没有排序字段,则不排序
|
||||
if(StringUtils.isBlank(defaultOrderField)){
|
||||
return page;
|
||||
}
|
||||
|
||||
//默认排序
|
||||
if(isAsc) {
|
||||
page.addOrder(OrderItem.asc(defaultOrderField));
|
||||
}else {
|
||||
page.addOrder(OrderItem.desc(defaultOrderField));
|
||||
}
|
||||
|
||||
return page;
|
||||
}
|
||||
}
|
||||
64
src/main/java/com/peanut/common/utils/R.java
Normal file
64
src/main/java/com/peanut/common/utils/R.java
Normal file
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.utils;
|
||||
|
||||
import org.apache.http.HttpStatus;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 返回数据
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class R extends HashMap<String, Object> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public R() {
|
||||
put("code", 0);
|
||||
put("msg", "success");
|
||||
}
|
||||
|
||||
public static R error() {
|
||||
return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知异常,请联系管理员");
|
||||
}
|
||||
|
||||
public static R error(String msg) {
|
||||
return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg);
|
||||
}
|
||||
|
||||
public static R error(int code, String msg) {
|
||||
R r = new R();
|
||||
r.put("code", code);
|
||||
r.put("msg", msg);
|
||||
return r;
|
||||
}
|
||||
|
||||
public static R ok(String msg) {
|
||||
R r = new R();
|
||||
r.put("msg", msg);
|
||||
return r;
|
||||
}
|
||||
|
||||
public static R ok(Map<String, Object> map) {
|
||||
R r = new R();
|
||||
r.putAll(map);
|
||||
return r;
|
||||
}
|
||||
|
||||
public static R ok() {
|
||||
return new R();
|
||||
}
|
||||
|
||||
public R put(String key, Object value) {
|
||||
super.put(key, value);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
86
src/main/java/com/peanut/common/utils/ReadProvinceUtil.java
Normal file
86
src/main/java/com/peanut/common/utils/ReadProvinceUtil.java
Normal file
@@ -0,0 +1,86 @@
|
||||
package com.peanut.common.utils;
|
||||
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.peanut.modules.book.entity.CityEntity;
|
||||
import com.peanut.modules.book.entity.CountyEntity;
|
||||
import com.peanut.modules.book.entity.ProvinceEntity;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class ReadProvinceUtil {
|
||||
public static List<ProvinceEntity> getFile(String filePath) {
|
||||
JSONArray proJsonArray = null;
|
||||
JSONArray cityJsonArray = null;
|
||||
JSONArray countyJsonArray = null;
|
||||
|
||||
JSONObject cityJson = null;
|
||||
JSONObject countyJson = null;
|
||||
Date date = new Date();
|
||||
|
||||
List<ProvinceEntity> provinceList = null;
|
||||
List<CityEntity> cityList = null;
|
||||
List<CountyEntity> countyList = null;
|
||||
|
||||
// String path = request.getSession().getServletContext().getRealPath("/");
|
||||
// path = path + filePath;
|
||||
File file = new File(filePath);
|
||||
try {
|
||||
String input = FileUtils.readFileToString(file, "UTF-8");// 读取文件
|
||||
System.out.println(input);
|
||||
//文件转换jsonObject格式
|
||||
String s = input.replaceAll("\n", "");
|
||||
JSONObject proJson = JSONObject.parseObject(s);
|
||||
if (proJson != null) {
|
||||
// 取出数据
|
||||
proJsonArray = proJson.getJSONArray("china");
|
||||
provinceList = new ArrayList<ProvinceEntity>();
|
||||
if (proJsonArray != null) {
|
||||
for (int i = 0; i < proJsonArray.size(); i++) {
|
||||
ProvinceEntity province = new ProvinceEntity();
|
||||
JSONObject temp = proJsonArray.getJSONObject(i);
|
||||
province.setProvName(temp.getString("name"));
|
||||
province.setCreateDate(date);
|
||||
province.setRegionCode(temp.getString("code"));
|
||||
|
||||
cityJsonArray = JSONArray.parseArray(temp.getString("cityList"));
|
||||
cityList = new ArrayList<CityEntity>();
|
||||
if (cityJsonArray != null) {
|
||||
for (int j = 0; j < cityJsonArray.size(); j++) {
|
||||
CityEntity city = new CityEntity();
|
||||
cityJson = cityJsonArray.getJSONObject(j);
|
||||
city.setCityName(cityJson.getString("name"));
|
||||
city.setRegionCode(cityJson.getString("code"));
|
||||
city.setCreateDate(date);
|
||||
countyJsonArray = JSONArray.parseArray(cityJson.getString("areaList"));
|
||||
countyList = new ArrayList<CountyEntity>();
|
||||
if (countyJsonArray != null) {
|
||||
for (int k = 0; k < countyJsonArray.size(); k++) {
|
||||
CountyEntity county = new CountyEntity();
|
||||
countyJson = countyJsonArray.getJSONObject(k);
|
||||
county.setCountyName(countyJson.getString("name"));
|
||||
county.setRegionCode(countyJson.getString("code"));
|
||||
county.setCreateDate(date);
|
||||
countyList.add(county);
|
||||
}
|
||||
city.setCountyList(countyList);
|
||||
cityList.add(city);
|
||||
}
|
||||
}
|
||||
province.setCityList(cityList);
|
||||
provinceList.add(province);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.getStackTrace();
|
||||
}
|
||||
return provinceList;
|
||||
}
|
||||
}
|
||||
21
src/main/java/com/peanut/common/utils/RedisKeys.java
Normal file
21
src/main/java/com/peanut/common/utils/RedisKeys.java
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.utils;
|
||||
|
||||
/**
|
||||
* Redis所有Keys
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class RedisKeys {
|
||||
|
||||
public static String getSysConfigKey(String key){
|
||||
return "sys:config:" + key;
|
||||
}
|
||||
}
|
||||
99
src/main/java/com/peanut/common/utils/RedisUtils.java
Normal file
99
src/main/java/com/peanut/common/utils/RedisUtils.java
Normal file
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.utils;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.*;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Redis工具类
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Component
|
||||
public class RedisUtils {
|
||||
@Autowired
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
@Autowired
|
||||
private ValueOperations<String, String> valueOperations;
|
||||
@Autowired
|
||||
private HashOperations<String, String, Object> hashOperations;
|
||||
@Autowired
|
||||
private ListOperations<String, Object> listOperations;
|
||||
@Autowired
|
||||
private SetOperations<String, Object> setOperations;
|
||||
@Autowired
|
||||
private ZSetOperations<String, Object> zSetOperations;
|
||||
/** 默认过期时长,单位:秒 */
|
||||
public final static long DEFAULT_EXPIRE = 60 * 60 * 24;
|
||||
/** 不设置过期时长 */
|
||||
public final static long NOT_EXPIRE = -1;
|
||||
private final static Gson gson = new Gson();
|
||||
|
||||
public void set(String key, Object value, long expire){
|
||||
valueOperations.set(key, toJson(value));
|
||||
if(expire != NOT_EXPIRE){
|
||||
redisTemplate.expire(key, expire, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
public void set(String key, Object value){
|
||||
set(key, value, DEFAULT_EXPIRE);
|
||||
}
|
||||
|
||||
public <T> T get(String key, Class<T> clazz, long expire) {
|
||||
String value = valueOperations.get(key);
|
||||
if(expire != NOT_EXPIRE){
|
||||
redisTemplate.expire(key, expire, TimeUnit.SECONDS);
|
||||
}
|
||||
return value == null ? null : fromJson(value, clazz);
|
||||
}
|
||||
|
||||
public <T> T get(String key, Class<T> clazz) {
|
||||
return get(key, clazz, NOT_EXPIRE);
|
||||
}
|
||||
|
||||
public String get(String key, long expire) {
|
||||
String value = valueOperations.get(key);
|
||||
if(expire != NOT_EXPIRE){
|
||||
redisTemplate.expire(key, expire, TimeUnit.SECONDS);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public String get(String key) {
|
||||
return get(key, NOT_EXPIRE);
|
||||
}
|
||||
|
||||
public void delete(String key) {
|
||||
redisTemplate.delete(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Object转成JSON数据
|
||||
*/
|
||||
private String toJson(Object object){
|
||||
if(object instanceof Integer || object instanceof Long || object instanceof Float ||
|
||||
object instanceof Double || object instanceof Boolean || object instanceof String){
|
||||
return String.valueOf(object);
|
||||
}
|
||||
return gson.toJson(object);
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON数据,转成Object
|
||||
*/
|
||||
private <T> T fromJson(String json, Class<T> clazz){
|
||||
return gson.fromJson(json, clazz);
|
||||
}
|
||||
}
|
||||
61
src/main/java/com/peanut/common/utils/ShiroUtils.java
Normal file
61
src/main/java/com/peanut/common/utils/ShiroUtils.java
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.utils;
|
||||
|
||||
import com.peanut.common.exception.RRException;
|
||||
import com.peanut.modules.sys.entity.SysUserEntity;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.session.Session;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
|
||||
/**
|
||||
* Shiro工具类
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class ShiroUtils {
|
||||
|
||||
public static Session getSession() {
|
||||
return SecurityUtils.getSubject().getSession();
|
||||
}
|
||||
|
||||
public static Subject getSubject() {
|
||||
return SecurityUtils.getSubject();
|
||||
}
|
||||
|
||||
public static SysUserEntity getUserEntity() {
|
||||
return (SysUserEntity)SecurityUtils.getSubject().getPrincipal();
|
||||
}
|
||||
|
||||
public static Long getUserId() {
|
||||
return getUserEntity().getUserId();
|
||||
}
|
||||
|
||||
public static void setSessionAttribute(Object key, Object value) {
|
||||
getSession().setAttribute(key, value);
|
||||
}
|
||||
|
||||
public static Object getSessionAttribute(Object key) {
|
||||
return getSession().getAttribute(key);
|
||||
}
|
||||
|
||||
public static boolean isLogin() {
|
||||
return SecurityUtils.getSubject().getPrincipal() != null;
|
||||
}
|
||||
|
||||
public static String getKaptcha(String key) {
|
||||
Object kaptcha = getSessionAttribute(key);
|
||||
if(kaptcha == null){
|
||||
throw new RRException("验证码已失效");
|
||||
}
|
||||
getSession().removeAttribute(key);
|
||||
return kaptcha.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.utils;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Spring Context 工具类
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Component
|
||||
public class SpringContextUtils implements ApplicationContextAware {
|
||||
public static ApplicationContext applicationContext;
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
SpringContextUtils.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
public static Object getBean(String name) {
|
||||
return applicationContext.getBean(name);
|
||||
}
|
||||
|
||||
public static <T> T getBean(String name, Class<T> requiredType) {
|
||||
return applicationContext.getBean(name, requiredType);
|
||||
}
|
||||
|
||||
public static boolean containsBean(String name) {
|
||||
return applicationContext.containsBean(name);
|
||||
}
|
||||
|
||||
public static boolean isSingleton(String name) {
|
||||
return applicationContext.isSingleton(name);
|
||||
}
|
||||
|
||||
public static Class<? extends Object> getType(String name) {
|
||||
return applicationContext.getType(name);
|
||||
}
|
||||
|
||||
}
|
||||
122
src/main/java/com/peanut/common/utils/TokenHolder.java
Normal file
122
src/main/java/com/peanut/common/utils/TokenHolder.java
Normal file
@@ -0,0 +1,122 @@
|
||||
package com.peanut.common.utils;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
public class TokenHolder {
|
||||
public static final String ASR_SCOPE = "audio_voice_assistant_get";
|
||||
|
||||
public static final String TTS_SCOPE = "audio_tts_post";
|
||||
|
||||
/**
|
||||
* url , Token的url,http可以改为https
|
||||
*/
|
||||
private static final String url = "http://openapi.baidu.com/oauth/2.0/token";
|
||||
|
||||
/**
|
||||
* asr的权限 scope 是 "audio_voice_assistant_get" tts 的权限 scope 是
|
||||
* "audio_tts_post"
|
||||
*/
|
||||
private String scope;
|
||||
|
||||
/**
|
||||
* 网页上申请语音识别应用获取的apiKey
|
||||
*/
|
||||
private String apiKey;
|
||||
|
||||
/**
|
||||
* 网页上申请语音识别应用获取的secretKey
|
||||
*/
|
||||
private String secretKey;
|
||||
|
||||
/**
|
||||
* 保存访问接口获取的token
|
||||
*/
|
||||
private String token;
|
||||
|
||||
/**
|
||||
* 当前的时间戳,毫秒
|
||||
*/
|
||||
private long expiresAt;
|
||||
|
||||
/**
|
||||
* @param apiKey
|
||||
* 网页上申请语音识别应用获取的apiKey
|
||||
* @param secretKey
|
||||
* 网页上申请语音识别应用获取的secretKey
|
||||
*/
|
||||
public TokenHolder(String apiKey, String secretKey, String scope) {
|
||||
this.apiKey = apiKey;
|
||||
this.secretKey = secretKey;
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取token,refresh 方法后调用有效
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取过期时间,refresh 方法后调用有效
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public long getExpiresAt() {
|
||||
return expiresAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取token
|
||||
*
|
||||
* @return
|
||||
* @throws IOException
|
||||
* http请求错误
|
||||
* @throws DemoException
|
||||
* http接口返回不是 200, access_token未获取
|
||||
*/
|
||||
public void resfresh() throws Exception {
|
||||
String getTokenURL = url + "?grant_type=client_credentials" + "&client_id=" + ConnUtil.urlEncode(apiKey)
|
||||
+ "&client_secret=" + ConnUtil.urlEncode(secretKey);
|
||||
|
||||
// 打印的url出来放到浏览器内可以复现
|
||||
System.out.println("token url:" + getTokenURL);
|
||||
|
||||
URL url = new URL(getTokenURL);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setConnectTimeout(5000);
|
||||
String result = ConnUtil.getResponseString(conn);
|
||||
System.out.println("Token result json:" + result);
|
||||
parseJson(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param result
|
||||
* token接口获得的result
|
||||
* @throws DemoException
|
||||
*/
|
||||
private void parseJson(String result) throws Exception {
|
||||
JSONObject json = new JSONObject(result);
|
||||
if (!json.has("access_token")) {
|
||||
// 返回没有access_token字段
|
||||
throw new DemoException("access_token not obtained, " + result);
|
||||
}
|
||||
if (!json.has("scope")) {
|
||||
// 返回没有scope字段
|
||||
throw new DemoException("scopenot obtained, " + result);
|
||||
}
|
||||
if (!json.getString("scope").contains(scope)) {
|
||||
throw new DemoException("scope not exist, " + scope + "," + result);
|
||||
}
|
||||
token = json.getString("access_token");
|
||||
expiresAt = System.currentTimeMillis() + json.getLong("expires_in") * 1000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
38
src/main/java/com/peanut/common/utils/UEditorUpload.java
Normal file
38
src/main/java/com/peanut/common/utils/UEditorUpload.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package com.peanut.common.utils;
|
||||
|
||||
import com.peanut.modules.app.entity.UEditorFile;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
@Component
|
||||
public class UEditorUpload {
|
||||
private Logger log = LoggerFactory.getLogger(UEditorUpload.class);
|
||||
private String path = ClassUtils.getDefaultClassLoader().getResource("").getPath();
|
||||
|
||||
public UEditorFile uploadImage(MultipartFile file) throws IOException {
|
||||
log.info("UEditor开始上传文件");
|
||||
String fileName = file.getOriginalFilename(); //获取文件名
|
||||
//Ueditor的config.json规定的返回路径格式
|
||||
String returnPath = "/image/upload/ueditor/"+new Date().getTime()+"/"+fileName;
|
||||
File saveFile = new File(path+"static"+returnPath);
|
||||
if (!saveFile.exists()){
|
||||
saveFile.mkdirs();
|
||||
}
|
||||
file.transferTo(saveFile); //将临时文件移动到保存路径
|
||||
log.info("UEditor上传文件成功,保存路径:"+saveFile.getAbsolutePath());
|
||||
UEditorFile uEditorFile = new UEditorFile();
|
||||
uEditorFile.setState("SUCCESS");
|
||||
uEditorFile.setUrl(returnPath); //访问URL
|
||||
uEditorFile.setTitle(fileName);
|
||||
uEditorFile.setOriginal(fileName);
|
||||
return uEditorFile;
|
||||
}
|
||||
|
||||
}
|
||||
32
src/main/java/com/peanut/common/validator/Assert.java
Normal file
32
src/main/java/com/peanut/common/validator/Assert.java
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.validator;
|
||||
|
||||
import com.peanut.common.exception.RRException;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
/**
|
||||
* 数据校验
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public abstract class Assert {
|
||||
|
||||
public static void isBlank(String str, String message) {
|
||||
if (StringUtils.isBlank(str)) {
|
||||
throw new RRException(message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void isNull(Object object, String message) {
|
||||
if (object == null) {
|
||||
throw new RRException(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
* <p>
|
||||
* https://www.renren.io
|
||||
* <p>
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.validator;
|
||||
|
||||
import com.peanut.common.exception.RRException;
|
||||
import com.peanut.common.utils.Constant;
|
||||
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.Validation;
|
||||
import javax.validation.Validator;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* hibernate-validator校验工具类
|
||||
*
|
||||
* 参考文档:http://docs.jboss.org/hibernate/validator/5.4/reference/en-US/html_single/
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class ValidatorUtils {
|
||||
private static Validator validator;
|
||||
|
||||
static {
|
||||
validator = Validation.buildDefaultValidatorFactory().getValidator();
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验对象
|
||||
* @param object 待校验对象
|
||||
* @param groups 待校验的组
|
||||
* @throws RRException 校验不通过,则报RRException异常
|
||||
*/
|
||||
public static void validateEntity(Object object, Class<?>... groups)
|
||||
throws RRException {
|
||||
Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
|
||||
if (!constraintViolations.isEmpty()) {
|
||||
StringBuilder msg = new StringBuilder();
|
||||
for (ConstraintViolation<Object> constraint : constraintViolations) {
|
||||
msg.append(constraint.getMessage()).append("<br>");
|
||||
}
|
||||
throw new RRException(msg.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static void validateEntity(Object object, Constant.CloudService type) {
|
||||
validateEntity(object, type.getValidatorGroupClass());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.validator.group;
|
||||
|
||||
/**
|
||||
* 新增数据 Group
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public interface AddGroup {
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.validator.group;
|
||||
|
||||
/**
|
||||
* 阿里云
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public interface AliyunGroup {
|
||||
}
|
||||
21
src/main/java/com/peanut/common/validator/group/Group.java
Normal file
21
src/main/java/com/peanut/common/validator/group/Group.java
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.validator.group;
|
||||
|
||||
import javax.validation.GroupSequence;
|
||||
|
||||
/**
|
||||
* 定义校验顺序,如果AddGroup组失败,则UpdateGroup组不会再校验
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@GroupSequence({AddGroup.class, UpdateGroup.class})
|
||||
public interface Group {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.validator.group;
|
||||
|
||||
/**
|
||||
* 腾讯云
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public interface QcloudGroup {
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.validator.group;
|
||||
|
||||
/**
|
||||
* 七牛
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public interface QiniuGroup {
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.validator.group;
|
||||
|
||||
/**
|
||||
* 更新数据 Group
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
|
||||
public interface UpdateGroup {
|
||||
|
||||
}
|
||||
530
src/main/java/com/peanut/common/xss/HTMLFilter.java
Normal file
530
src/main/java/com/peanut/common/xss/HTMLFilter.java
Normal file
@@ -0,0 +1,530 @@
|
||||
package com.peanut.common.xss;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
*
|
||||
* HTML filtering utility for protecting against XSS (Cross Site Scripting).
|
||||
*
|
||||
* This code is licensed LGPLv3
|
||||
*
|
||||
* This code is a Java port of the original work in PHP by Cal Hendersen.
|
||||
* http://code.iamcal.com/php/lib_filter/
|
||||
*
|
||||
* The trickiest part of the translation was handling the differences in regex handling
|
||||
* between PHP and Java. These resources were helpful in the process:
|
||||
*
|
||||
* http://java.sun.com/j2se/1.4.2/docs/api/java/util/regex/Pattern.html
|
||||
* http://us2.php.net/manual/en/reference.pcre.pattern.modifiers.php
|
||||
* http://www.regular-expressions.info/modifiers.html
|
||||
*
|
||||
* A note on naming conventions: instance variables are prefixed with a "v"; global
|
||||
* constants are in all caps.
|
||||
*
|
||||
* Sample use:
|
||||
* String input = ...
|
||||
* String clean = new HTMLFilter().filter( input );
|
||||
*
|
||||
* The class is not thread safe. Create a new instance if in doubt.
|
||||
*
|
||||
* If you find bugs or have suggestions on improvement (especially regarding
|
||||
* performance), please contact us. The latest version of this
|
||||
* source, and our contact details, can be found at http://xss-html-filter.sf.net
|
||||
*
|
||||
* @author Joseph O'Connell
|
||||
* @author Cal Hendersen
|
||||
* @author Michael Semb Wever
|
||||
*/
|
||||
public final class HTMLFilter {
|
||||
|
||||
/** regex flag union representing /si modifiers in php **/
|
||||
private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL;
|
||||
private static final Pattern P_COMMENTS = Pattern.compile("<!--(.*?)-->", Pattern.DOTALL);
|
||||
private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI);
|
||||
private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL);
|
||||
private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI);
|
||||
private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI);
|
||||
private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI);
|
||||
private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI);
|
||||
private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI);
|
||||
private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?");
|
||||
private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?");
|
||||
private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?");
|
||||
private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))");
|
||||
private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL);
|
||||
private static final Pattern P_END_ARROW = Pattern.compile("^>");
|
||||
private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)");
|
||||
private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)");
|
||||
private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)");
|
||||
private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)");
|
||||
private static final Pattern P_AMP = Pattern.compile("&");
|
||||
private static final Pattern P_QUOTE = Pattern.compile("<");
|
||||
private static final Pattern P_LEFT_ARROW = Pattern.compile("<");
|
||||
private static final Pattern P_RIGHT_ARROW = Pattern.compile(">");
|
||||
private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>");
|
||||
|
||||
// @xxx could grow large... maybe use sesat's ReferenceMap
|
||||
private static final ConcurrentMap<String,Pattern> P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<String, Pattern>();
|
||||
private static final ConcurrentMap<String,Pattern> P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<String, Pattern>();
|
||||
|
||||
/** set of allowed html elements, along with allowed attributes for each element **/
|
||||
private final Map<String, List<String>> vAllowed;
|
||||
/** counts of open tags for each (allowable) html element **/
|
||||
private final Map<String, Integer> vTagCounts = new HashMap<String, Integer>();
|
||||
|
||||
/** html elements which must always be self-closing (e.g. "<img />") **/
|
||||
private final String[] vSelfClosingTags;
|
||||
/** html elements which must always have separate opening and closing tags (e.g. "<b></b>") **/
|
||||
private final String[] vNeedClosingTags;
|
||||
/** set of disallowed html elements **/
|
||||
private final String[] vDisallowed;
|
||||
/** attributes which should be checked for valid protocols **/
|
||||
private final String[] vProtocolAtts;
|
||||
/** allowed protocols **/
|
||||
private final String[] vAllowedProtocols;
|
||||
/** tags which should be removed if they contain no content (e.g. "<b></b>" or "<b />") **/
|
||||
private final String[] vRemoveBlanks;
|
||||
/** entities allowed within html markup **/
|
||||
private final String[] vAllowedEntities;
|
||||
/** flag determining whether comments are allowed in input String. */
|
||||
private final boolean stripComment;
|
||||
private final boolean encodeQuotes;
|
||||
private boolean vDebug = false;
|
||||
/**
|
||||
* flag determining whether to try to make tags when presented with "unbalanced"
|
||||
* angle brackets (e.g. "<b text </b>" becomes "<b> text </b>"). If set to false,
|
||||
* unbalanced angle brackets will be html escaped.
|
||||
*/
|
||||
private final boolean alwaysMakeTags;
|
||||
|
||||
/** Default constructor.
|
||||
*
|
||||
*/
|
||||
public HTMLFilter() {
|
||||
vAllowed = new HashMap<>();
|
||||
|
||||
final ArrayList<String> a_atts = new ArrayList<String>();
|
||||
a_atts.add("href");
|
||||
a_atts.add("target");
|
||||
vAllowed.put("a", a_atts);
|
||||
|
||||
final ArrayList<String> img_atts = new ArrayList<String>();
|
||||
img_atts.add("src");
|
||||
img_atts.add("width");
|
||||
img_atts.add("height");
|
||||
img_atts.add("alt");
|
||||
vAllowed.put("img", img_atts);
|
||||
|
||||
final ArrayList<String> no_atts = new ArrayList<String>();
|
||||
vAllowed.put("b", no_atts);
|
||||
vAllowed.put("strong", no_atts);
|
||||
vAllowed.put("i", no_atts);
|
||||
vAllowed.put("em", no_atts);
|
||||
|
||||
vSelfClosingTags = new String[]{"img"};
|
||||
vNeedClosingTags = new String[]{"a", "b", "strong", "i", "em"};
|
||||
vDisallowed = new String[]{};
|
||||
vAllowedProtocols = new String[]{"http", "mailto", "https"}; // no ftp.
|
||||
vProtocolAtts = new String[]{"src", "href"};
|
||||
vRemoveBlanks = new String[]{"a", "b", "strong", "i", "em"};
|
||||
vAllowedEntities = new String[]{"amp", "gt", "lt", "quot"};
|
||||
stripComment = true;
|
||||
encodeQuotes = true;
|
||||
alwaysMakeTags = true;
|
||||
}
|
||||
|
||||
/** Set debug flag to true. Otherwise use default settings. See the default constructor.
|
||||
*
|
||||
* @param debug turn debug on with a true argument
|
||||
*/
|
||||
public HTMLFilter(final boolean debug) {
|
||||
this();
|
||||
vDebug = debug;
|
||||
|
||||
}
|
||||
|
||||
/** Map-parameter configurable constructor.
|
||||
*
|
||||
* @param conf map containing configuration. keys match field names.
|
||||
*/
|
||||
public HTMLFilter(final Map<String,Object> conf) {
|
||||
|
||||
assert conf.containsKey("vAllowed") : "configuration requires vAllowed";
|
||||
assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags";
|
||||
assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags";
|
||||
assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed";
|
||||
assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols";
|
||||
assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts";
|
||||
assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks";
|
||||
assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities";
|
||||
|
||||
vAllowed = Collections.unmodifiableMap((HashMap<String, List<String>>) conf.get("vAllowed"));
|
||||
vSelfClosingTags = (String[]) conf.get("vSelfClosingTags");
|
||||
vNeedClosingTags = (String[]) conf.get("vNeedClosingTags");
|
||||
vDisallowed = (String[]) conf.get("vDisallowed");
|
||||
vAllowedProtocols = (String[]) conf.get("vAllowedProtocols");
|
||||
vProtocolAtts = (String[]) conf.get("vProtocolAtts");
|
||||
vRemoveBlanks = (String[]) conf.get("vRemoveBlanks");
|
||||
vAllowedEntities = (String[]) conf.get("vAllowedEntities");
|
||||
stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true;
|
||||
encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true;
|
||||
alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true;
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
vTagCounts.clear();
|
||||
}
|
||||
|
||||
private void debug(final String msg) {
|
||||
if (vDebug) {
|
||||
Logger.getAnonymousLogger().info(msg);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// my versions of some PHP library functions
|
||||
public static String chr(final int decimal) {
|
||||
return String.valueOf((char) decimal);
|
||||
}
|
||||
|
||||
public static String htmlSpecialChars(final String s) {
|
||||
String result = s;
|
||||
result = regexReplace(P_AMP, "&", result);
|
||||
result = regexReplace(P_QUOTE, """, result);
|
||||
result = regexReplace(P_LEFT_ARROW, "<", result);
|
||||
result = regexReplace(P_RIGHT_ARROW, ">", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
/**
|
||||
* given a user submitted input String, filter out any invalid or restricted
|
||||
* html.
|
||||
*
|
||||
* @param input text (i.e. submitted by a user) than may contain html
|
||||
* @return "clean" version of input, with only valid, whitelisted html elements allowed
|
||||
*/
|
||||
public String filter(final String input) {
|
||||
reset();
|
||||
String s = input;
|
||||
|
||||
debug("************************************************");
|
||||
debug(" INPUT: " + input);
|
||||
|
||||
s = escapeComments(s);
|
||||
debug(" escapeComments: " + s);
|
||||
|
||||
s = balanceHTML(s);
|
||||
debug(" balanceHTML: " + s);
|
||||
|
||||
s = checkTags(s);
|
||||
debug(" checkTags: " + s);
|
||||
|
||||
s = processRemoveBlanks(s);
|
||||
debug("processRemoveBlanks: " + s);
|
||||
|
||||
s = validateEntities(s);
|
||||
debug(" validateEntites: " + s);
|
||||
|
||||
debug("************************************************\n\n");
|
||||
return s;
|
||||
}
|
||||
|
||||
public boolean isAlwaysMakeTags(){
|
||||
return alwaysMakeTags;
|
||||
}
|
||||
|
||||
public boolean isStripComments(){
|
||||
return stripComment;
|
||||
}
|
||||
|
||||
private String escapeComments(final String s) {
|
||||
final Matcher m = P_COMMENTS.matcher(s);
|
||||
final StringBuffer buf = new StringBuffer();
|
||||
if (m.find()) {
|
||||
final String match = m.group(1); //(.*?)
|
||||
m.appendReplacement(buf, Matcher.quoteReplacement("<!--" + htmlSpecialChars(match) + "-->"));
|
||||
}
|
||||
m.appendTail(buf);
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private String balanceHTML(String s) {
|
||||
if (alwaysMakeTags) {
|
||||
//
|
||||
// try and form html
|
||||
//
|
||||
s = regexReplace(P_END_ARROW, "", s);
|
||||
s = regexReplace(P_BODY_TO_END, "<$1>", s);
|
||||
s = regexReplace(P_XML_CONTENT, "$1<$2", s);
|
||||
|
||||
} else {
|
||||
//
|
||||
// escape stray brackets
|
||||
//
|
||||
s = regexReplace(P_STRAY_LEFT_ARROW, "<$1", s);
|
||||
s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2><", s);
|
||||
|
||||
//
|
||||
// the last regexp causes '<>' entities to appear
|
||||
// (we need to do a lookahead assertion so that the last bracket can
|
||||
// be used in the next pass of the regexp)
|
||||
//
|
||||
s = regexReplace(P_BOTH_ARROWS, "", s);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private String checkTags(String s) {
|
||||
Matcher m = P_TAGS.matcher(s);
|
||||
|
||||
final StringBuffer buf = new StringBuffer();
|
||||
while (m.find()) {
|
||||
String replaceStr = m.group(1);
|
||||
replaceStr = processTag(replaceStr);
|
||||
m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr));
|
||||
}
|
||||
m.appendTail(buf);
|
||||
|
||||
s = buf.toString();
|
||||
|
||||
// these get tallied in processTag
|
||||
// (remember to reset before subsequent calls to filter method)
|
||||
for (String key : vTagCounts.keySet()) {
|
||||
for (int ii = 0; ii < vTagCounts.get(key); ii++) {
|
||||
s += "</" + key + ">";
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private String processRemoveBlanks(final String s) {
|
||||
String result = s;
|
||||
for (String tag : vRemoveBlanks) {
|
||||
if(!P_REMOVE_PAIR_BLANKS.containsKey(tag)){
|
||||
P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?></" + tag + ">"));
|
||||
}
|
||||
result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result);
|
||||
if(!P_REMOVE_SELF_BLANKS.containsKey(tag)){
|
||||
P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>"));
|
||||
}
|
||||
result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) {
|
||||
Matcher m = regex_pattern.matcher(s);
|
||||
return m.replaceAll(replacement);
|
||||
}
|
||||
|
||||
private String processTag(final String s) {
|
||||
// ending tags
|
||||
Matcher m = P_END_TAG.matcher(s);
|
||||
if (m.find()) {
|
||||
final String name = m.group(1).toLowerCase();
|
||||
if (allowed(name)) {
|
||||
if (!inArray(name, vSelfClosingTags)) {
|
||||
if (vTagCounts.containsKey(name)) {
|
||||
vTagCounts.put(name, vTagCounts.get(name) - 1);
|
||||
return "</" + name + ">";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// starting tags
|
||||
m = P_START_TAG.matcher(s);
|
||||
if (m.find()) {
|
||||
final String name = m.group(1).toLowerCase();
|
||||
final String body = m.group(2);
|
||||
String ending = m.group(3);
|
||||
|
||||
//debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" );
|
||||
if (allowed(name)) {
|
||||
String params = "";
|
||||
|
||||
final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body);
|
||||
final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body);
|
||||
final List<String> paramNames = new ArrayList<String>();
|
||||
final List<String> paramValues = new ArrayList<String>();
|
||||
while (m2.find()) {
|
||||
paramNames.add(m2.group(1)); //([a-z0-9]+)
|
||||
paramValues.add(m2.group(3)); //(.*?)
|
||||
}
|
||||
while (m3.find()) {
|
||||
paramNames.add(m3.group(1)); //([a-z0-9]+)
|
||||
paramValues.add(m3.group(3)); //([^\"\\s']+)
|
||||
}
|
||||
|
||||
String paramName, paramValue;
|
||||
for (int ii = 0; ii < paramNames.size(); ii++) {
|
||||
paramName = paramNames.get(ii).toLowerCase();
|
||||
paramValue = paramValues.get(ii);
|
||||
|
||||
// debug( "paramName='" + paramName + "'" );
|
||||
// debug( "paramValue='" + paramValue + "'" );
|
||||
// debug( "allowed? " + vAllowed.get( name ).contains( paramName ) );
|
||||
|
||||
if (allowedAttribute(name, paramName)) {
|
||||
if (inArray(paramName, vProtocolAtts)) {
|
||||
paramValue = processParamProtocol(paramValue);
|
||||
}
|
||||
params += " " + paramName + "=\"" + paramValue + "\"";
|
||||
}
|
||||
}
|
||||
|
||||
if (inArray(name, vSelfClosingTags)) {
|
||||
ending = " /";
|
||||
}
|
||||
|
||||
if (inArray(name, vNeedClosingTags)) {
|
||||
ending = "";
|
||||
}
|
||||
|
||||
if (ending == null || ending.length() < 1) {
|
||||
if (vTagCounts.containsKey(name)) {
|
||||
vTagCounts.put(name, vTagCounts.get(name) + 1);
|
||||
} else {
|
||||
vTagCounts.put(name, 1);
|
||||
}
|
||||
} else {
|
||||
ending = " /";
|
||||
}
|
||||
return "<" + name + params + ending + ">";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// comments
|
||||
m = P_COMMENT.matcher(s);
|
||||
if (!stripComment && m.find()) {
|
||||
return "<" + m.group() + ">";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
private String processParamProtocol(String s) {
|
||||
s = decodeEntities(s);
|
||||
final Matcher m = P_PROTOCOL.matcher(s);
|
||||
if (m.find()) {
|
||||
final String protocol = m.group(1);
|
||||
if (!inArray(protocol, vAllowedProtocols)) {
|
||||
// bad protocol, turn into local anchor link instead
|
||||
s = "#" + s.substring(protocol.length() + 1, s.length());
|
||||
if (s.startsWith("#//")) {
|
||||
s = "#" + s.substring(3, s.length());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private String decodeEntities(String s) {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
|
||||
Matcher m = P_ENTITY.matcher(s);
|
||||
while (m.find()) {
|
||||
final String match = m.group(1);
|
||||
final int decimal = Integer.decode(match).intValue();
|
||||
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
|
||||
}
|
||||
m.appendTail(buf);
|
||||
s = buf.toString();
|
||||
|
||||
buf = new StringBuffer();
|
||||
m = P_ENTITY_UNICODE.matcher(s);
|
||||
while (m.find()) {
|
||||
final String match = m.group(1);
|
||||
final int decimal = Integer.valueOf(match, 16).intValue();
|
||||
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
|
||||
}
|
||||
m.appendTail(buf);
|
||||
s = buf.toString();
|
||||
|
||||
buf = new StringBuffer();
|
||||
m = P_ENCODE.matcher(s);
|
||||
while (m.find()) {
|
||||
final String match = m.group(1);
|
||||
final int decimal = Integer.valueOf(match, 16).intValue();
|
||||
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
|
||||
}
|
||||
m.appendTail(buf);
|
||||
s = buf.toString();
|
||||
|
||||
s = validateEntities(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
private String validateEntities(final String s) {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
|
||||
// validate entities throughout the string
|
||||
Matcher m = P_VALID_ENTITIES.matcher(s);
|
||||
while (m.find()) {
|
||||
final String one = m.group(1); //([^&;]*)
|
||||
final String two = m.group(2); //(?=(;|&|$))
|
||||
m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two)));
|
||||
}
|
||||
m.appendTail(buf);
|
||||
|
||||
return encodeQuotes(buf.toString());
|
||||
}
|
||||
|
||||
private String encodeQuotes(final String s){
|
||||
if(encodeQuotes){
|
||||
StringBuffer buf = new StringBuffer();
|
||||
Matcher m = P_VALID_QUOTES.matcher(s);
|
||||
while (m.find()) {
|
||||
final String one = m.group(1); //(>|^)
|
||||
final String two = m.group(2); //([^<]+?)
|
||||
final String three = m.group(3); //(<|$)
|
||||
m.appendReplacement(buf, Matcher.quoteReplacement(one + regexReplace(P_QUOTE, """, two) + three));
|
||||
}
|
||||
m.appendTail(buf);
|
||||
return buf.toString();
|
||||
}else{
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
private String checkEntity(final String preamble, final String term) {
|
||||
|
||||
return ";".equals(term) && isValidEntity(preamble)
|
||||
? '&' + preamble
|
||||
: "&" + preamble;
|
||||
}
|
||||
|
||||
private boolean isValidEntity(final String entity) {
|
||||
return inArray(entity, vAllowedEntities);
|
||||
}
|
||||
|
||||
private static boolean inArray(final String s, final String[] array) {
|
||||
for (String item : array) {
|
||||
if (item != null && item.equals(s)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean allowed(final String name) {
|
||||
return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed);
|
||||
}
|
||||
|
||||
private boolean allowedAttribute(final String name, final String paramName) {
|
||||
return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName));
|
||||
}
|
||||
}
|
||||
50
src/main/java/com/peanut/common/xss/SQLFilter.java
Normal file
50
src/main/java/com/peanut/common/xss/SQLFilter.java
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.xss;
|
||||
|
||||
import com.peanut.common.exception.RRException;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
/**
|
||||
* SQL过滤
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class SQLFilter {
|
||||
|
||||
/**
|
||||
* SQL注入过滤
|
||||
* @param str 待验证的字符串
|
||||
*/
|
||||
public static String sqlInject(String str){
|
||||
if(StringUtils.isBlank(str)){
|
||||
return null;
|
||||
}
|
||||
//去掉'|"|;|\字符
|
||||
str = StringUtils.replace(str, "'", "");
|
||||
str = StringUtils.replace(str, "\"", "");
|
||||
str = StringUtils.replace(str, ";", "");
|
||||
str = StringUtils.replace(str, "\\", "");
|
||||
|
||||
//转换成小写
|
||||
str = str.toLowerCase();
|
||||
|
||||
//非法字符
|
||||
String[] keywords = {"master", "truncate", "insert", "select", "delete", "update", "declare", "alter", "drop"};
|
||||
|
||||
//判断是否包含非法字符
|
||||
for(String keyword : keywords){
|
||||
if(str.indexOf(keyword) != -1){
|
||||
throw new RRException("包含非法字符");
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
}
|
||||
37
src/main/java/com/peanut/common/xss/XssFilter.java
Normal file
37
src/main/java/com/peanut/common/xss/XssFilter.java
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.xss;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* XSS过滤
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class XssFilter implements Filter {
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig config) throws ServletException {
|
||||
}
|
||||
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper(
|
||||
(HttpServletRequest) request);
|
||||
chain.doFilter(xssRequest, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.peanut.common.xss;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import javax.servlet.ReadListener;
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* XSS过滤处理
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
|
||||
//没被包装过的HttpServletRequest(特殊场景,需要自己过滤)
|
||||
HttpServletRequest orgRequest;
|
||||
//html过滤
|
||||
private final static HTMLFilter htmlFilter = new HTMLFilter();
|
||||
|
||||
public XssHttpServletRequestWrapper(HttpServletRequest request) {
|
||||
super(request);
|
||||
orgRequest = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletInputStream getInputStream() throws IOException {
|
||||
//非json类型,直接返回
|
||||
if(!MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(super.getHeader(HttpHeaders.CONTENT_TYPE))){
|
||||
return super.getInputStream();
|
||||
}
|
||||
|
||||
//为空,直接返回
|
||||
String json = IOUtils.toString(super.getInputStream(), "utf-8");
|
||||
if (StringUtils.isBlank(json)) {
|
||||
return super.getInputStream();
|
||||
}
|
||||
|
||||
//xss过滤
|
||||
json = xssEncode(json);
|
||||
final ByteArrayInputStream bis = new ByteArrayInputStream(json.getBytes("utf-8"));
|
||||
return new ServletInputStream() {
|
||||
@Override
|
||||
public boolean isFinished() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadListener(ReadListener readListener) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return bis.read();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParameter(String name) {
|
||||
String value = super.getParameter(xssEncode(name));
|
||||
if (StringUtils.isNotBlank(value)) {
|
||||
value = xssEncode(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getParameterValues(String name) {
|
||||
String[] parameters = super.getParameterValues(name);
|
||||
if (parameters == null || parameters.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
parameters[i] = xssEncode(parameters[i]);
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String,String[]> getParameterMap() {
|
||||
Map<String,String[]> map = new LinkedHashMap<>();
|
||||
Map<String,String[]> parameters = super.getParameterMap();
|
||||
for (String key : parameters.keySet()) {
|
||||
String[] values = parameters.get(key);
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
values[i] = xssEncode(values[i]);
|
||||
}
|
||||
map.put(key, values);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHeader(String name) {
|
||||
String value = super.getHeader(xssEncode(name));
|
||||
if (StringUtils.isNotBlank(value)) {
|
||||
value = xssEncode(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private String xssEncode(String input) {
|
||||
return htmlFilter.filter(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最原始的request
|
||||
*/
|
||||
public HttpServletRequest getOrgRequest() {
|
||||
return orgRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最原始的request
|
||||
*/
|
||||
public static HttpServletRequest getOrgRequest(HttpServletRequest request) {
|
||||
if (request instanceof XssHttpServletRequestWrapper) {
|
||||
return ((XssHttpServletRequestWrapper) request).getOrgRequest();
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user