Kaynağa Gözat

Merge branch 'dev' of http://192.168.1.220:10080/Amoy2/wlyy2.0 into dev

# Conflicts:
#	svr/svr-internet-hospital/src/main/java/com/yihu/jw/hospital/endpoint/wechat/WechatMenuController.java
wangzhinan 4 yıl önce
ebeveyn
işleme
6f2055b30d

+ 18 - 0
business/base-service/src/main/java/com/yihu/jw/hospital/prescription/service/PrescriptionService.java

@ -76,6 +76,7 @@ import com.yihu.jw.util.common.IdCardUtil;
import com.yihu.jw.util.common.LatitudeUtils;
import com.yihu.jw.util.date.DateUtil;
import com.yihu.jw.util.wechat.WeixinMessagePushUtils;
import com.yihu.jw.utils.GenerateUserSig;
import com.yihu.jw.utils.Pkis.PKIService_PortType;
import com.yihu.jw.utils.Pkis.PKIService_ServiceLocator;
import com.yihu.jw.utils.StringUtil;
@ -260,6 +261,8 @@ public class PrescriptionService extends BaseJpaService<WlyyPrescriptionDO, Pres
    private PrescriptionDiagnosisDao  prescriptionDiagnosisDao;
    @Autowired
    private XzyyPrescriptionService xzyyPrescriptionService;
    @Autowired
    private GenerateUserSig generateUserSig;
@ -9025,4 +9028,19 @@ public class PrescriptionService extends BaseJpaService<WlyyPrescriptionDO, Pres
            return "删除失败";
        }
    }
    /**
     * 小程序生成签名
     * @param userId
     * @return
     */
    public String appletSign(String userId){
        WlyyHospitalSysDictDO sysDictDO = hospitalSysDictDao.findById("SDKAPPID");
        WlyyHospitalSysDictDO hospitalSysDictDO =  hospitalSysDictDao.findById("SECRETKEY");
        if (sysDictDO!=null&&hospitalSysDictDO!=null){
            return GenerateUserSig.GenTLSSignature(Long.parseLong(sysDictDO.getDictValue()),userId,604800,null,hospitalSysDictDO.getDictValue());
        }
        return null;
    }
}

+ 128 - 0
business/base-service/src/main/java/com/yihu/jw/utils/GenerateUserSig.java

@ -0,0 +1,128 @@
package com.yihu.jw.utils;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.util.Base64Utils;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.zip.Deflater;
/*
 * Module:   GenerateUserSig
 *
 * Function: 用于生成测试用的 UserSig,UserSig 是腾讯云为其云服务设计的一种安全保护签名。
 *           其计算方法是对 SDKAppID、UserID 和 EXPIRETIME 进行加密,加密算法为 HMAC-SHA256。
 *
 * Attention: 请不要将如下代码发布到您的线上正式版本的 App 中,原因如下:
 *
 *            本文件中的代码虽然能够正确计算出 UserSig,但仅适合快速调通 SDK 的基本功能,不适合线上产品,
 *            这是因为客户端代码中的 SECRETKEY 很容易被反编译逆向破解,尤其是 Web 端的代码被破解的难度几乎为零。
 *            一旦您的密钥泄露,攻击者就可以计算出正确的 UserSig 来盗用您的腾讯云流量。
 *
 *            正确的做法是将 UserSig 的计算代码和加密密钥放在您的业务服务器上,然后由 App 按需向您的服务器获取实时算出的 UserSig。
 *            由于破解服务器的成本要高于破解客户端 App,所以服务器计算的方案能够更好地保护您的加密密钥。
 *
 * Reference:https://cloud.tencent.com/document/product/269/32688#Server
 */
public class GenerateUserSig {
    /**
     * 生成 tls 票据
     *
     * @param sdkappid      应用的 appid
     * @param userId        用户 id
     * @param expire        有效期,单位是秒
     * @param userbuf       默认填写null
     * @param priKeyContent 生成 tls 票据使用的私钥内容
     * @return 如果出错,会返回为空,或者有异常打印,成功返回有效的票据
     */
    public static String GenTLSSignature(long sdkappid, String userId, long expire, byte[] userbuf, String priKeyContent) {
        if (StringUtil.isEmpty(priKeyContent)) {
            return "";
        }
        long       currTime = System.currentTimeMillis() / 1000;
        JSONObject sigDoc   = new JSONObject();
        try {
            sigDoc.put("TLS.ver", "2.0");
            sigDoc.put("TLS.identifier", userId);
            sigDoc.put("TLS.sdkappid", sdkappid);
            sigDoc.put("TLS.expire", expire);
            sigDoc.put("TLS.time", currTime);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        String base64UserBuf = null;
        if (null != userbuf) {
            base64UserBuf = Base64Utils.encodeToString(userbuf);
            try {
                sigDoc.put("TLS.userbuf", base64UserBuf);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        String sig = hmacsha256(sdkappid, userId, currTime, expire, priKeyContent, base64UserBuf);
        if (sig.length() == 0) {
            return "";
        }
        try {
            sigDoc.put("TLS.sig", sig);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        Deflater compressor = new Deflater();
        compressor.setInput(sigDoc.toString().getBytes(Charset.forName("UTF-8")));
        compressor.finish();
        byte[] compressedBytes = new byte[2048];
        int compressedBytesLength = compressor.deflate(compressedBytes);
        compressor.end();
        return new String(base64EncodeUrl(Arrays.copyOfRange(compressedBytes, 0, compressedBytesLength)));
    }
    private static String hmacsha256(long sdkappid, String userId, long currTime, long expire, String priKeyContent, String base64Userbuf) {
        String contentToBeSigned = "TLS.identifier:" + userId + "\n"
                + "TLS.sdkappid:" + sdkappid + "\n"
                + "TLS.time:" + currTime + "\n"
                + "TLS.expire:" + expire + "\n";
        if (null != base64Userbuf) {
            contentToBeSigned += "TLS.userbuf:" + base64Userbuf + "\n";
        }
        try {
            byte[]        byteKey = priKeyContent.getBytes("UTF-8");
            Mac           hmac    = Mac.getInstance("HmacSHA256");
            SecretKeySpec keySpec = new SecretKeySpec(byteKey, "HmacSHA256");
            hmac.init(keySpec);
            byte[] byteSig = hmac.doFinal(contentToBeSigned.getBytes("UTF-8"));
            return new String(Base64Utils.encodeToString(byteSig));
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }
    private static byte[] base64EncodeUrl(byte[] input) {
        byte[] base64 = new String(Base64Utils.encodeToString(input)).getBytes();
        for (int i = 0; i < base64.length; ++i)
            switch (base64[i]) {
                case '+':
                    base64[i] = '*';
                    break;
                case '/':
                    base64[i] = '-';
                    break;
                case '=':
                    base64[i] = '_';
                    break;
                default:
                    break;
            }
        return base64;
    }
}

+ 2 - 0
common/common-request-mapping/src/main/java/com/yihu/jw/rm/hospital/BaseHospitalRequestMapping.java

@ -514,6 +514,8 @@ public class BaseHospitalRequestMapping {
        public static final String updatePayStatus = "/updatePayStatus";
        public static final String findPatNoByPatient = "/findPatNoByPatient";
        public static final String appletSign= "/appletSign";
    }
    public static class YkyyPrescription extends BaseHospitalRequestMapping.Basic {

+ 12 - 1
gateway/ag-basic/pom.xml

@ -12,7 +12,7 @@
    <artifactId>ag-basic</artifactId>
    <version>${parent.version}</version>
    <packaging>jar</packaging>
    <packaging>war</packaging>
    <dependencies>
        <!-- 支持Tomcat启动 -->
@ -61,6 +61,17 @@
            <groupId>org.springframework.retry</groupId>
            <artifactId>spring-retry</artifactId>
        </dependency>
        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>2.4</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>

+ 81 - 0
gateway/ag-basic/src/main/java/com/yihu/jw/gateway/AesEncryptUtils.java

@ -0,0 +1,81 @@
package com.yihu.jw.gateway;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import java.util.HashMap;
import java.util.Map;
/**
 * 前后端数据传输加密工具类
 * @author monkey
 *
 */
public class AesEncryptUtils {
    //可配置到Constant中,并读取配置文件注入,16位,自己定义
    private static final String KEY = "46A61629A19AE04C";
 
    //参数分别代表 算法名称/加密模式/数据填充方式
    private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding";
 
    /**
     * 加密
     * @param content 加密的字符串
     * @param encryptKey key值
     * @return
     * @throws Exception
     */
    public static String encrypt(String content, String encryptKey) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128);
        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"));
        byte[] b = cipher.doFinal(content.getBytes("utf-8"));
        // 采用base64算法进行转码,避免出现中文乱码
        return Base64.encodeBase64String(b);
 
    }
 
    /**
     * 解密
     * @param encryptStr 解密的字符串
     * @param decryptKey 解密的key值
     * @return
     * @throws Exception
     */
    public static String decrypt(String encryptStr, String decryptKey) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128);
        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"));
        // 采用base64算法进行转码,避免出现中文乱码
        byte[] encryptBytes = Base64.decodeBase64(encryptStr);
        byte[] decryptBytes = cipher.doFinal(encryptBytes);
        return new String(decryptBytes);
    }
 
    public static String encrypt(String content) throws Exception {
        return encrypt(content, KEY);
    }
    public static String decrypt(String encryptStr) throws Exception {
        return decrypt(encryptStr, KEY);
    }
 
 
    public static void main(String[] args) throws Exception {
        Map map=new HashMap<String,String>();
        map.put("hospital","350211A1002");
        map.put("dictName","consultClose");
        String content = JSONObject.toJSONString(map);
        System.out.println("加密前:" + content);
 
        String encrypt = encrypt(content, KEY);
        System.out.println("加密后:" + encrypt);
 
        String decrypt = decrypt(encrypt, KEY);
        System.out.println("解密后:" + decrypt);
    }
}

+ 90 - 2
gateway/ag-basic/src/main/java/com/yihu/jw/gateway/filter/BasicZuulFilter.java

@ -1,8 +1,12 @@
package com.yihu.jw.gateway.filter;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.http.HttpServletRequestWrapper;
import com.netflix.zuul.http.ServletInputStreamWrapper;
import com.yihu.jw.gateway.AesEncryptUtils;
import com.yihu.jw.gateway.methlog.BaseLoginLogService;
import com.yihu.jw.gateway.methlog.BaseMethodLogService;
import com.yihu.jw.gateway.useragent.UserAgent;
@ -20,16 +24,20 @@ import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Iterator;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.*;
/**
 * Created by progr1mmer on 2017/12/27.
@ -68,6 +76,7 @@ public class BasicZuulFilter extends ZuulFilter {
    @Override
    public boolean shouldFilter() {
        return true;
    }
@ -89,9 +98,27 @@ public class BasicZuulFilter extends ZuulFilter {
        logger.info("BasicZuulFilter:"+url);
        if (!(url.contains("/open/noLogin/notify")||
            url.contains("/open/noLogin/ylzReceiveNotify")||
            url.contains("/open/noLogin/receiveNotify")||
            url.contains("/open/noLogin/getSFExpressInfoNew")||
            url.contains("/open/noLogin/sfroutepushservice")||
            url.contains("/open/noLogin/ylzSettleRecord")||
                url.contains("/weixin"))){
            logger.info("入参"+ctx.getRequestQueryParams());
            try {
                decrypt(ctx,request);
                logger.info("第一步");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //保存操作日志
        baseMethodLogService.saveMethodLog(request);
        //内部微服务有不需要认证的地址请在URL上追加/open/来进行过滤,如/api/v1.0/open/**,不要在此继续追加!!!
        if (url.contains("/auth/")//验证服务
                || url.contains("/base/wechat")//微信
@ -111,6 +138,67 @@ public class BasicZuulFilter extends ZuulFilter {
        return this.authenticate(ctx, request, url);
    }
    public void decrypt(RequestContext ctx,HttpServletRequest request) throws Exception {
        String method = request.getMethod();
        if (method.equalsIgnoreCase("GET")){
            Map<String, List<String>> map = ctx.getRequestQueryParams();
            String aes_decodedStr = AesEncryptUtils.decrypt(map.get("object").toString());
            JSONObject object = JSONObject.parseObject(aes_decodedStr);
            for(String str:object.keySet()){
                List<String> arrayList = new ArrayList<>();
                String value = object.getString(str);
                arrayList.add(value);
                map.put(str,arrayList);
            }
            map.remove("object");
            ctx.setRequestQueryParams(map);
            logger.info("解密后的参数"+ctx.getRequestQueryParams());
        }else if ("POST".equals(method) || "PUT".equals(method)) {
            InputStream in = request.getInputStream();
            String body = StreamUtils.copyToString(in, Charset.forName("UTF-8"));
            // 如果body为空初始化为空json
            if (StringUtils.isEmpty(body)) {
                body = "{}";
            }
            logger.info("body" + body);
            // 获取请求参数name
            String jsonString = request.getParameter("object");
            logger.info("canshu"+jsonString);
            if (jsonString != null) {
                body="";
                String jsonobject = AesEncryptUtils.decrypt(jsonString);
                logger.info("解密:" + jsonobject);
                JSONObject jsonObject = JSONObject.parseObject(jsonobject);
                for(String str:jsonObject.keySet()){
                    String value = jsonObject.getString(str);
                    body+=str+"="+ URLEncoder.encode(value)+"&";
                }
                String newBody = body.substring(0,body.length()-1);
                logger.info("newBody" + newBody);
                final byte[] reqBodyBytes = newBody.getBytes();
                // 重写上下文的HttpServletRequestWrapper
                ctx.setRequest(new HttpServletRequestWrapper(request) {
                    @Override
                    public ServletInputStream getInputStream() throws IOException {
                        return new ServletInputStreamWrapper(reqBodyBytes);
                    }
                    @Override
                    public int getContentLength() {
                        return reqBodyBytes.length;
                    }
                    @Override
                    public long getContentLengthLong() {
                        return reqBodyBytes.length;
                    }
                });
            }
        }
    }
    /**
     * 验证token 权限地址
     * @param ctx

+ 77 - 0
gateway/ag-basic/src/main/java/com/yihu/jw/gateway/filter/PostFilter.java

@ -0,0 +1,77 @@
package com.yihu.jw.gateway.filter;
import com.alibaba.fastjson.JSONObject;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.yihu.jw.gateway.AesEncryptUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;
import javax.servlet.http.HttpServletRequest;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;
@Component
public class PostFilter extends ZuulFilter {
 
    private static Logger logger = LoggerFactory.getLogger(PostFilter.class);
 
    @Override
    public String filterType() {
        //后置过滤器
        return "post";
    }
 
    @Override
    public int filterOrder() {
        //优先级,数字越大,优先级越低
        return 0;
    }
 
    @Override
    public boolean shouldFilter() {
        //是否执行该过滤器,true代表需要过滤
        return true;
    }
 
    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        logger.info("进入post过滤器");
        HttpServletRequest request = ctx.getRequest();
        String url = request.getRequestURI();
        InputStream stream = RequestContext.getCurrentContext().getResponseDataStream();
        try {
        byte[] bytes;
        if(RequestContext.getCurrentContext().getResponseGZipped()){
            GZIPInputStream gzipInputStream = null;
            gzipInputStream = new GZIPInputStream(stream);
            bytes = StreamUtils.copyToByteArray(gzipInputStream);
        }else {
            bytes = StreamUtils.copyToByteArray(stream);
        }
        String body = new String(bytes,"UTF8");
        JSONObject object = new JSONObject();
        object.put("status","200");
        object.put("data", AesEncryptUtils.encrypt(body));
        if (!(url.contains("/open/noLogin/notify")||
            url.contains("/open/noLogin/ylzReceiveNotify")||
            url.contains("/open/noLogin/receiveNotify")||
            url.contains("/open/noLogin/getSFExpressInfoNew")||
            url.contains("/open/noLogin/sfroutepushservice")||
            url.contains("/open/noLogin/ylzSettleRecord")||
                url.contains("/weixin"))){
            RequestContext.getCurrentContext().setResponseBody(object.toJSONString());
        }
        logger.info(ctx.getResponseBody()+"");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
 
    }
 
}

+ 10 - 0
svr/svr-internet-hospital/src/main/java/com/yihu/jw/hospital/endpoint/prescription/PrescriptionEndpoint.java

@ -2259,4 +2259,14 @@ public class PrescriptionEndpoint extends EnvelopRestEndpoint {
        return success(prescriptionService.disablePrescription(prescriptionId));
    }
    @GetMapping(value = BaseHospitalRequestMapping.Prescription.appletSign)
    @ApiOperation(value = "生成小程序秘钥")
    public Envelop appletSign(
            @ApiParam(name = "userId", value = "userId")
            @RequestParam(value = "userId",defaultValue = "",required = true) String prescriptionId) throws Exception {
        return success(prescriptionService.appletSign(prescriptionId));
    }
}