From d726fa6a8016e44f026c37bdc14fd6b5edf61178 Mon Sep 17 00:00:00 2001 From: Stormeye Wu Date: Mon, 6 May 2019 09:32:35 +0800 Subject: [PATCH] =?UTF-8?q?[callback=E5=88=86=E7=A6=BB][=E6=96=B0=E5=A2=9E?= =?UTF-8?q?]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../msg/WxMsgCallbackController.java | 31 +- .../official/WxMallApplyController.java | 81 ----- mallinkCallback/pom.xml | 162 +++++++++ .../com/iformall/CallbackApplication.java | 52 +++ .../annotation/SystemControllerLog.java | 10 + .../iformall/annotation/SystemServiceLog.java | 10 + .../java/com/iformall/config/AwsProperty.java | 52 +++ .../com/iformall/config/MyExecutorConfig.java | 26 ++ .../java/com/iformall/config/RedisConfig.java | 145 +++++++++ .../java/com/iformall/config/RestFilter.java | 58 ++++ .../iformall/config/RestTemplateConfig.java | 24 ++ .../java/com/iformall/config/ShiroConfig.java | 307 ++++++++++++++++++ .../com/iformall/config/ShiroLoginFilter.java | 31 ++ .../java/com/iformall/config/WebConfig.java | 131 ++++++++ .../com/iformall/config/WechatMpConfig.java | 33 ++ .../iformall/config/WechatWebProperties.java | 59 ++++ .../controller/base/BaseController.java | 46 +++ .../callback/WxCarCallBackController.java | 0 .../callback/WxMsgCallbackController.java | 48 +++ .../callback/WxPayBillController.java | 0 .../controller/callback/WxPayController.java | 6 +- .../device/WxDeviceScreenAdController.java | 0 .../official/WxMallApplyController.java | 36 ++ .../BodyReaderHttpServletRequestWrapper.java | 76 +++++ .../HttpServletRequestWrapperFilter.java | 72 ++++ .../interceptor/RequestInterceptor.java | 117 +++++++ .../XssHttpServletRequestWrapper.java | 125 +++++++ .../shiro/MyRetryLimitCredentialsMatcher.java | 45 +++ .../java/com/iformall/shiro/MyShiroRealm.java | 79 +++++ .../com/iformall/shiro/PasswordHelper.java | 32 ++ .../java/com/iformall/shiro/ShiroService.java | 126 +++++++ .../java/com/iformall/shiro/UserSession.java | 11 + .../com/iformall/shiro/UseriFormallToken.java | 39 +++ .../main/java/com/iformall/utils/PayUtil.java | 37 +++ .../java/com/iformall/utils/UrlCheck.java | 22 ++ .../src/main/resources/application-dev.yml | 120 +++++++ .../src/main/resources/application-prod.yml | 104 ++++++ .../src/main/resources/application-test.yml | 104 ++++++ .../src/main/resources/application.yml | 73 +++++ .../src/main/resources/logback-spring.xml | 100 ++++++ pom.xml | 1 + 41 files changed, 2518 insertions(+), 113 deletions(-) delete mode 100644 mallinkAdmin/src/main/java/com/iformall/controller/official/WxMallApplyController.java create mode 100644 mallinkCallback/pom.xml create mode 100644 mallinkCallback/src/main/java/com/iformall/CallbackApplication.java create mode 100644 mallinkCallback/src/main/java/com/iformall/annotation/SystemControllerLog.java create mode 100644 mallinkCallback/src/main/java/com/iformall/annotation/SystemServiceLog.java create mode 100644 mallinkCallback/src/main/java/com/iformall/config/AwsProperty.java create mode 100644 mallinkCallback/src/main/java/com/iformall/config/MyExecutorConfig.java create mode 100644 mallinkCallback/src/main/java/com/iformall/config/RedisConfig.java create mode 100644 mallinkCallback/src/main/java/com/iformall/config/RestFilter.java create mode 100644 mallinkCallback/src/main/java/com/iformall/config/RestTemplateConfig.java create mode 100644 mallinkCallback/src/main/java/com/iformall/config/ShiroConfig.java create mode 100644 mallinkCallback/src/main/java/com/iformall/config/ShiroLoginFilter.java create mode 100644 mallinkCallback/src/main/java/com/iformall/config/WebConfig.java create mode 100644 mallinkCallback/src/main/java/com/iformall/config/WechatMpConfig.java create mode 100644 mallinkCallback/src/main/java/com/iformall/config/WechatWebProperties.java create mode 100644 mallinkCallback/src/main/java/com/iformall/controller/base/BaseController.java rename {mallinkAdmin => mallinkCallback}/src/main/java/com/iformall/controller/callback/WxCarCallBackController.java (100%) create mode 100644 mallinkCallback/src/main/java/com/iformall/controller/callback/WxMsgCallbackController.java rename {mallinkAdmin => mallinkCallback}/src/main/java/com/iformall/controller/callback/WxPayBillController.java (100%) rename {mallinkAdmin => mallinkCallback}/src/main/java/com/iformall/controller/callback/WxPayController.java (98%) rename {mallinkAdmin => mallinkCallback}/src/main/java/com/iformall/controller/device/WxDeviceScreenAdController.java (100%) create mode 100644 mallinkCallback/src/main/java/com/iformall/controller/official/WxMallApplyController.java create mode 100644 mallinkCallback/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java create mode 100644 mallinkCallback/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java create mode 100644 mallinkCallback/src/main/java/com/iformall/interceptor/RequestInterceptor.java create mode 100644 mallinkCallback/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java create mode 100644 mallinkCallback/src/main/java/com/iformall/shiro/MyRetryLimitCredentialsMatcher.java create mode 100644 mallinkCallback/src/main/java/com/iformall/shiro/MyShiroRealm.java create mode 100644 mallinkCallback/src/main/java/com/iformall/shiro/PasswordHelper.java create mode 100644 mallinkCallback/src/main/java/com/iformall/shiro/ShiroService.java create mode 100644 mallinkCallback/src/main/java/com/iformall/shiro/UserSession.java create mode 100644 mallinkCallback/src/main/java/com/iformall/shiro/UseriFormallToken.java create mode 100644 mallinkCallback/src/main/java/com/iformall/utils/PayUtil.java create mode 100644 mallinkCallback/src/main/java/com/iformall/utils/UrlCheck.java create mode 100644 mallinkCallback/src/main/resources/application-dev.yml create mode 100644 mallinkCallback/src/main/resources/application-prod.yml create mode 100644 mallinkCallback/src/main/resources/application-test.yml create mode 100644 mallinkCallback/src/main/resources/application.yml create mode 100644 mallinkCallback/src/main/resources/logback-spring.xml diff --git a/mallinkAdmin/src/main/java/com/iformall/controller/msg/WxMsgCallbackController.java b/mallinkAdmin/src/main/java/com/iformall/controller/msg/WxMsgCallbackController.java index e2d2851b3..9dfcc6cab 100644 --- a/mallinkAdmin/src/main/java/com/iformall/controller/msg/WxMsgCallbackController.java +++ b/mallinkAdmin/src/main/java/com/iformall/controller/msg/WxMsgCallbackController.java @@ -18,7 +18,7 @@ import org.springframework.web.bind.annotation.*; import java.util.Map; @RestController -@RequestMapping("wxMsgCallback") +@RequestMapping("msgCallback") public class WxMsgCallbackController extends BaseController { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @@ -79,33 +79,4 @@ public class WxMsgCallbackController extends BaseController { logger.debug("[" + getIpAddr() + "] WxMsgCallbackController::findById"); return new ResultData(Result.SUCCESS, "查询成功", wxMsgCallbackService.getById(id)); } - - - @PostMapping(value = "/receivemsg/{tenantId}") - public void receivemsg(@PathVariable String tenantId, @RequestParam Map param) { - logger.debug("[" + getIpAddr() + "] WxMsgCallbackController::receivemsg"); - logger.info(param.toString()); - //解析param数据插入数据库中 - wxMsgCallbackService.saveOrUpdate(tenantId,param); - - } - - @RequestMapping(value = "/receivemodel/{tenantId}") - public void receivemodel(@PathVariable String tenantId, @RequestParam Map param) { - logger.debug("[" + getIpAddr() + "] WxMsgCallbackController::receivemodel"); - logger.info(param.toString()); - //解析param数据插入数据库中 - wxMsgCallbackService.receivemodel(tenantId, param); - - } - - @RequestMapping(value = "/receiveverifymodel/{tenantId}") - public void receiveverifymodel(@PathVariable String tenantId, @RequestParam Map param) { - logger.debug("[" + getIpAddr() + "] WxMsgCallbackController::receiveverifymodel"); - logger.info(param.toString()); - //解析param数据插入数据库中 - wxMsgCallbackService.receiveverifymodel(tenantId, param); - - } - } diff --git a/mallinkAdmin/src/main/java/com/iformall/controller/official/WxMallApplyController.java b/mallinkAdmin/src/main/java/com/iformall/controller/official/WxMallApplyController.java deleted file mode 100644 index 6812a2c65..000000000 --- a/mallinkAdmin/src/main/java/com/iformall/controller/official/WxMallApplyController.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.iformall.controller.official; - -import com.github.pagehelper.PageInfo; -import com.iformall.common.Result; -import com.iformall.common.ResultData; -import com.iformall.controller.base.BaseController; -import com.iformall.domain.po.WxMallApply; -import com.iformall.domain.po.WxMsgValidationcode; -import com.iformall.service.WxMallApplyService; -import io.swagger.annotations.ApiImplicitParam; -import io.swagger.annotations.ApiImplicitParams; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; - -@RestController -@RequestMapping("wxMallApply") -public class WxMallApplyController extends BaseController { - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - - @Autowired - private WxMallApplyService wxMallApplyService; - - @GetMapping("list") - @ApiImplicitParams({ - @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), - @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) - public ResultData list(@ModelAttribute WxMallApply wxMallApply, Integer pageNum, Integer pageSize) { - logger.debug("[" + getIpAddr() + "] WxMallApplyController::list"); - if (null == wxMallApply) wxMallApply = new WxMallApply(); - final PageInfo page = wxMallApplyService.listAsPage(wxMallApply, pageNum, pageSize); - return new ResultData(page); - } - - @PostMapping("add") - public ResultData add(@RequestBody WxMallApply wxMallApply) { - logger.debug("[" + getIpAddr() + "] WxMallApplyController::add"); - //Assert.notNull(wxMallApply.getName(), "角色名不能为空"); - //Assert.isTrue(!checkUnique(sysRole.getName(), null), "重复的角色名"); - return wxMallApplyService.saveOrUpdate(wxMallApply); - - } - - @PostMapping("update") - public ResultData update(@RequestBody WxMallApply wxMallApply) { - logger.debug("[" + getIpAddr() + "] WxMallApplyController::update"); - return wxMallApplyService.saveOrUpdate(wxMallApply); - } - - @GetMapping("/del") - @ApiImplicitParam(name = "id", value = "id", dataType = "String", paramType = "query", required = true) - public ResultData delete(String id) { - logger.debug("[" + getIpAddr() + "] WxMallApplyController::delete"); - wxMallApplyService.deleteById(id); - return new ResultData(Result.SUCCESS, "删除成功", null); - } - - @GetMapping("/findById") - @ApiImplicitParam(name = "id", value = "id", dataType = "String", paramType = "query", required = true) - public ResultData findById(String id) { - logger.debug("[" + getIpAddr() + "] WxMallApplyController::findById"); - return new ResultData(Result.SUCCESS, "查询成功", wxMallApplyService.getById(id)); - } - - - @GetMapping("/sendvalidationcode") - @ApiImplicitParams({ - @ApiImplicitParam(name = "phone", value = "手机号", dataType = "String", paramType = "query", required = true), - @ApiImplicitParam(name = "type", value = "场景", dataType = "Integer", paramType = "query", required = true)}) - public ResultData sendvalidationcode(String phone, Integer type) { - logger.debug("[" + getIpAddr() + "] WxMallApplyController::sendvalidationcode"); - WxMsgValidationcode wxMsgValidationcode = new WxMsgValidationcode(); - wxMsgValidationcode.setTenantId("1"); - wxMsgValidationcode.setPhone(phone); - wxMsgValidationcode.setType(type); - return wxMallApplyService.sendvalidationcode(wxMsgValidationcode); - } - - -} diff --git a/mallinkCallback/pom.xml b/mallinkCallback/pom.xml new file mode 100644 index 000000000..ffcf8f888 --- /dev/null +++ b/mallinkCallback/pom.xml @@ -0,0 +1,162 @@ + + + 4.0.0 + + + mallink + com.iformall + 1.0 + + + mallinkCallback + + + 3.3.0 + 3.3.0 + + + + + com.iformall + mallinkService + 1.0 + + + com.iformall + mybatis-multi-tenancy + 1.0 + + + commons-fileupload + commons-fileupload + 1.3.3 + + + + com.google.zxing + core + 3.3.3 + + + + com.github.axet + kaptcha + 0.0.9 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + ZIP + + antlr, + cn.afterturn, + ch.qos.logback, + com.alibaba, + com.amazonaws, + com.mchange, + com.fasterxml.jackson.core, + com.fasterxml.jackson.dataformat, + com.fasterxml.jackson.datatype, + com.fasterxml.jackson.module, + com.github.axet, + com.github.binarywang, + com.github.jsqlparser, + com.github.pagehelper, + com.github.ulisesbocchio, + com.github.virtuald, + com.google.code.gson, + com.google.guava, + com.google.protobuf, + com.google.zxing, + com.jayway.jsonpath, + com.jhlabs, + com.puppycrawl.tools, + com.rabbitmq, + com.squareup.okhttp3, + com.squareup.okio, + com.sun, + com.sun.mail, + com.thoughtworks.xstream, + com.zaxxer, + commons-beanutils, + commons-cli, + commons-codec, + commons-collections, + commons-io, + commons-logging, + io.lettuce, + io.netty, + io.projectreactor, + io.springfox, + io.swagger, + io.undertow, + javax.activation, + javax.mail, + javax.persistence, + javax.xml.bind, + joda-time, + junit, + mysql, + net.bytebuddy, + net.minidev, + net.sf.saxon, + ognl, + org.antlr, + org.apache.commons, + org.apache.httpcomponents, + org.apache.logging.log4j, + org.apache.poi, + org.apache.poi.wso2, + org.apache.rocketmq, + org.apache.shiro, + org.apache.tomcat.embed, + org.apache.xmlbeans, + org.aspectj, + org.assertj, + org.bouncycastle, + org.checkerframework, + org.crazycake, + org.dom4j, + org.flowable, + org.hibernate.validator, + org.jasypt, + org.javassist, + org.jboss.spec.javax.annotation, + org.jboss.xnio, + org.jdom, + org.mockito, + org.mybatis, + org.mybatis.generator, + org.mybatis.spring.boot, + org.ow2.asm, + org.projectlombok, + org.quartz-scheduler, + org.rocketmq.spring.boot, + org.springframework, + org.springframework.amqp, + org.springframework.boot, + org.springframework.data, + org.springframework.retry, + org.springframework.ws, + org.yaml, + redis.clients, + software.amazon.ion, + tk.mybatis, + xmlpull, + xpp3 + + + + + + + \ No newline at end of file diff --git a/mallinkCallback/src/main/java/com/iformall/CallbackApplication.java b/mallinkCallback/src/main/java/com/iformall/CallbackApplication.java new file mode 100644 index 000000000..069f232b5 --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/CallbackApplication.java @@ -0,0 +1,52 @@ +package com.iformall; + +import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties; +import org.rocketmq.starter.annotation.EnableRocketMQ; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.scheduling.annotation.EnableAsync; +import springfox.documentation.swagger2.annotations.EnableSwagger2; +import tk.mybatis.spring.annotation.MapperScan; + +/** + * @author chenkx + * @date 2017-12-26 + */ +@SpringBootApplication +@MapperScan(basePackages = {"com.iformall.mapper"}) +@EnableSwagger2 +@EnableEncryptableProperties +@EnableAsync +@EnableRocketMQ +public class CallbackApplication { + + @Value("${fm.exception}") + private boolean fmException; + + @Value("${fm.exception_emails}") + private String fmExceptionEmails; + + @Value("${fm.open}") + private boolean fmOpen; + + @Bean + public boolean isFmException() { + return fmException; + } + + @Bean + public String fmExceptionEmails() { + return fmExceptionEmails; + } + + @Bean + public boolean isFmOpen() { + return fmOpen; + } + + public static void main(String[] args) { + SpringApplication.run(CallbackApplication.class, args); + } +} diff --git a/mallinkCallback/src/main/java/com/iformall/annotation/SystemControllerLog.java b/mallinkCallback/src/main/java/com/iformall/annotation/SystemControllerLog.java new file mode 100644 index 000000000..61821c134 --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/annotation/SystemControllerLog.java @@ -0,0 +1,10 @@ +package com.iformall.annotation; + +import java.lang.annotation.*; + +@Target({ElementType.PARAMETER, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface SystemControllerLog { + String description() default ""; +} diff --git a/mallinkCallback/src/main/java/com/iformall/annotation/SystemServiceLog.java b/mallinkCallback/src/main/java/com/iformall/annotation/SystemServiceLog.java new file mode 100644 index 000000000..f2cd84adf --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/annotation/SystemServiceLog.java @@ -0,0 +1,10 @@ +package com.iformall.annotation; + +import java.lang.annotation.*; + +@Target({ElementType.PARAMETER, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface SystemServiceLog { + String description() default ""; +} diff --git a/mallinkCallback/src/main/java/com/iformall/config/AwsProperty.java b/mallinkCallback/src/main/java/com/iformall/config/AwsProperty.java new file mode 100644 index 000000000..0329f1d6d --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/config/AwsProperty.java @@ -0,0 +1,52 @@ +package com.iformall.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author Stormeye + */ +@Component +@ConfigurationProperties(prefix = "aws") +public class AwsProperty { + // AWS ACCESS KEY + private String access; + + private String secret; + + private String clientRegion; + + private String bucketName; + + public String getAccess() { + return access; + } + + public void setAccess(String access) { + this.access = access; + } + + public String getSecret() { + return secret; + } + + public void setSecret(String secret) { + this.secret = secret; + } + + public String getClientRegion() { + return clientRegion; + } + + public void setClientRegion(String clientRegion) { + this.clientRegion = clientRegion; + } + + public String getBucketName() { + return bucketName; + } + + public void setBucketName(String bucketName) { + this.bucketName = bucketName; + } +} diff --git a/mallinkCallback/src/main/java/com/iformall/config/MyExecutorConfig.java b/mallinkCallback/src/main/java/com/iformall/config/MyExecutorConfig.java new file mode 100644 index 000000000..c60425e84 --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/config/MyExecutorConfig.java @@ -0,0 +1,26 @@ +package com.iformall.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.task.AsyncTaskExecutor; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.ThreadPoolExecutor; + +@Configuration +public class MyExecutorConfig { + /** + * 自定义异步线程池 + * + * @return + */ + @Bean + public AsyncTaskExecutor taskExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setThreadNamePrefix("Anno-Executor"); + executor.setMaxPoolSize(100); + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + return executor; + } +} + diff --git a/mallinkCallback/src/main/java/com/iformall/config/RedisConfig.java b/mallinkCallback/src/main/java/com/iformall/config/RedisConfig.java new file mode 100644 index 000000000..0cd431813 --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/config/RedisConfig.java @@ -0,0 +1,145 @@ +package com.iformall.config; + +import com.iformall.domain.po.PushLimit; +import com.iformall.domain.po.WxCUser; +import com.iformall.domain.po.WxScoreRules; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.cache.RedisCacheWriter; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import java.time.Duration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * Created by Stormeye on 2018/10/1. + */ +@Configuration +@EnableCaching +public class RedisConfig extends CachingConfigurerSupport { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + //缓存管理器 + @Bean + public CacheManager cacheManager(RedisConnectionFactory connectionFactory) { + /* + //user信息缓存配置 + RedisCacheConfiguration userCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(10)).disableCachingNullValues().prefixKeysWith("user"); + Map redisCacheConfigurationMap = new HashMap<>(); + redisCacheConfigurationMap.put("user", userCacheConfiguration); + //初始化一个RedisCacheWriter + RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory); + // 设置CacheManager的值序列化方式为JdkSerializationRedisSerializer,但其实RedisCacheConfiguration默认就是使用StringRedisSerializer序列化key,JdkSerializationRedisSerializer序列化value,所以以下注释代码为默认实现 + // ClassLoader loader = this.getClass().getClassLoader(); + // JdkSerializationRedisSerializer jdkSerializer = new JdkSerializationRedisSerializer(loader); + // RedisSerializationContext.SerializationPair pair = RedisSerializationContext.SerializationPair.fromSerializer(jdkSerializer); + // RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair); + RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig(); + //设置默认超过期时间是30秒 + defaultCacheConfig.entryTtl(Duration.ofSeconds(30)); + //初始化RedisCacheManager + RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig, redisCacheConfigurationMap); + return cacheManager; + */ + RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig(); // 生成一个默认配置,通过config对象即可对缓存进行自定义配置 + config = config.entryTtl(Duration.ofMinutes(1)) // 设置缓存的默认过期时间,也是使用Duration设置 + .disableCachingNullValues(); // 不缓存空值 + + // 设置一个初始化的缓存空间set集合 + Set cacheNames = new HashSet<>(); + cacheNames.add("my-redis-cache1"); + cacheNames.add("my-redis-cache2"); + + // 对每个缓存空间应用不同的配置 + Map configMap = new HashMap<>(); + configMap.put("my-redis-cache1", config); + configMap.put("my-redis-cache2", config.entryTtl(Duration.ofSeconds(120))); + + RedisCacheManager cacheManager = RedisCacheManager.builder(connectionFactory) // 使用自定义的缓存配置初始化一个cacheManager + .initialCacheNames(cacheNames) // 注意这两句的调用顺序,一定要先调用该方法设置初始化的缓存名,再初始化相关的配置 + .withInitialCacheConfigurations(configMap) + .build(); + return cacheManager; + } + + @Bean("pushLimitRedisTemplate") + public RedisTemplate getPushLimitRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(PushLimit.class); + // value值的序列化 + template.setValueSerializer(j); + template.setHashKeySerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + + template.setConnectionFactory(connectionFactory); + return template; + } + + @Bean("scoreRuleRedisTemplate") + public RedisTemplate getScoreRuleRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(WxScoreRules.class); + // value值的序列化 + template.setValueSerializer(j); + template.setHashKeySerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + + template.setConnectionFactory(connectionFactory); + return template; + } + + @Bean("openRedisTemplate") + public RedisTemplate getWeChatOpen(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + + // value值的序列化 + template.setValueSerializer(new StringRedisSerializer()); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + + template.setConnectionFactory(connectionFactory); + return template; + } + + @Bean("cuserTokenRedisTemplate") + public RedisTemplate getCUserTokenRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(WxCUser.class); + // value值的序列化 + template.setValueSerializer(j); + template.setHashKeySerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + + template.setConnectionFactory(connectionFactory); + return template; + } + +} diff --git a/mallinkCallback/src/main/java/com/iformall/config/RestFilter.java b/mallinkCallback/src/main/java/com/iformall/config/RestFilter.java new file mode 100644 index 000000000..4f9298433 --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/config/RestFilter.java @@ -0,0 +1,58 @@ +package com.iformall.config; + +import java.io.IOException; +import java.util.Optional; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * 前后端分离RESTful接口过滤器 + * + * @author xuguoqin + * + */ +public class RestFilter implements Filter { + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + HttpServletRequest req = null; + if (request instanceof HttpServletRequest) { + req = (HttpServletRequest) request; + } + HttpServletResponse res = null; + if (response instanceof HttpServletResponse) { + res = (HttpServletResponse) response; + } + if (req != null && res != null) { + //设置允许传递的参数 + res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization"); + //设置允许带上cookie + res.setHeader("Access-Control-Allow-Credentials", "true"); + String origin = Optional.ofNullable(req.getHeader("Origin")).orElse(req.getHeader("Referer")); + //设置允许的请求来源 + res.setHeader("Access-Control-Allow-Origin", origin); + //设置允许的请求方法 + res.setHeader("Access-Control-Allow-Methods", "GET, POST, PATCH, PUT, DELETE, OPTIONS"); + } + chain.doFilter(request, response); + } + + @Override + public void destroy() { + + } + +} \ No newline at end of file diff --git a/mallinkCallback/src/main/java/com/iformall/config/RestTemplateConfig.java b/mallinkCallback/src/main/java/com/iformall/config/RestTemplateConfig.java new file mode 100644 index 000000000..560a77cb5 --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/config/RestTemplateConfig.java @@ -0,0 +1,24 @@ +package com.iformall.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class RestTemplateConfig { + + @Bean + public RestTemplate restTemplate(ClientHttpRequestFactory factory) { + return new RestTemplate(factory); + } + + @Bean + public ClientHttpRequestFactory simpleClientHttpRequestFactory() { + SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); + factory.setReadTimeout(5000);//ms + factory.setConnectTimeout(10000);//ms + return factory; + } +} \ No newline at end of file diff --git a/mallinkCallback/src/main/java/com/iformall/config/ShiroConfig.java b/mallinkCallback/src/main/java/com/iformall/config/ShiroConfig.java new file mode 100644 index 000000000..27c8efd4a --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/config/ShiroConfig.java @@ -0,0 +1,307 @@ +package com.iformall.config; + +import com.iformall.service.MallPermissionService; +import com.iformall.shiro.MyRetryLimitCredentialsMatcher; +import com.iformall.shiro.MyShiroRealm; +import org.apache.shiro.mgt.SecurityManager; +import org.apache.shiro.spring.LifecycleBeanPostProcessor; +import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; +import org.apache.shiro.spring.web.ShiroFilterFactoryBean; +import org.apache.shiro.web.mgt.DefaultWebSecurityManager; +import org.apache.shiro.web.servlet.SimpleCookie; +import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; +import org.crazycake.shiro.RedisCacheManager; +import org.crazycake.shiro.RedisManager; +import org.crazycake.shiro.RedisSessionDAO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.servlet.Filter; +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; +import java.util.LinkedHashMap; +import java.util.Map; + + +/** + * Created by yangqj on 2017/4/23. + */ +@Configuration +public class ShiroConfig { + @Autowired(required = false) + private MallPermissionService resourcesService; + + @Value("${spring.redis.host}") + private String host; + + @Value("${spring.redis.port}") + private int port; + + @Value("${spring.redis.timeout}") + private int timeout; + + @Value("${spring.redis.expire}") + private int expire; + + @Value("${spring.redis.password}") + private String password; + + @Bean + public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() { + return new LifecycleBeanPostProcessor(); + } + + /** + * ShiroDialect,为了在thymeleaf里使用shiro的标签的bean + * @return + */ +// @Bean +// public ShiroDialect shiroDialect() { +// return new ShiroDialect(); +// } + + /** + * ShiroFilterFactoryBean 处理拦截资源文件问题。 + * 注意:单独一个ShiroFilterFactoryBean配置是或报错的,因为在 + * 初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager + *

+ * Filter Chain定义说明 + * 1、一个URL可以配置多个Filter,使用逗号分隔 + * 2、当设置多个过滤器时,全部验证通过,才视为通过 + * 3、部分过滤器可指定参数,如perms,roles + */ + @Bean + public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { + System.out.println("ShiroConfiguration.shirFilter()"); + ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); + // 必须设置 SecurityManager + shiroFilterFactoryBean.setSecurityManager(securityManager); + Map filters = new LinkedHashMap(); + filters.put("token", new ShiroLoginFilter()); + filters.put("corsFilter", new RestFilter()); + //filters.put("authc", new MyFormAuthenticationFilter()); + shiroFilterFactoryBean.setFilters(filters); + // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面 + shiroFilterFactoryBean.setLoginUrl("/#/"); + // 登录成功后要跳转的链接 + + shiroFilterFactoryBean.setSuccessUrl("/usersPage"); + //未授权界面; + shiroFilterFactoryBean.setUnauthorizedUrl("/403"); + //拦截器. + Map filterChainDefinitionMap = new LinkedHashMap(); + // 官网 + filterChainDefinitionMap.put("/wxMallApply/add", "anon"); + filterChainDefinitionMap.put("/wxMallApply/sendvalidationcode", "anon"); + + // 硬件访问 + filterChainDefinitionMap.put("/wxDeviceScreenAd/**", "anon"); + // callback + filterChainDefinitionMap.put("/wxPay/notify/**", "anon"); // 支付回调 + filterChainDefinitionMap.put("/wxPayBill/notify/**", "anon"); + + filterChainDefinitionMap.put("/wxMsgCallback/**", "anon"); + filterChainDefinitionMap.put("/carCallback/**", "anon"); + + // static files + filterChainDefinitionMap.put("/css/**", "anon"); + filterChainDefinitionMap.put("/js/**", "anon"); + filterChainDefinitionMap.put("/img/**", "anon"); + filterChainDefinitionMap.put("/font-awesome/**", "anon"); + + //:这是一个坑呢,一不小心代码就不好使了; + // + //自定义加载权限资源关系 +// Map map = new HashMap<>(); +// List resourcesList = resourcesService.list(map); +// for(SysPermission resources:resourcesList){ +// +// if (StringUtil.isNotEmpty(resources.getUrl())) { +// String permission = "perms[" + resources.getUrl()+ "]"; +// filterChainDefinitionMap.put(resources.getUrl(),permission); +// } +// } + // swagger-ui + filterChainDefinitionMap.put("/swagger-ui.html", "anon"); + filterChainDefinitionMap.put("/v2/**", "anon"); + filterChainDefinitionMap.put("/swagger-resources/**", "anon"); + filterChainDefinitionMap.put("/webjars/**", "anon"); + + filterChainDefinitionMap.put("/version", "anon"); + +// filterChainDefinitionMap.put("/role/**", "corsFilter,token"); + + //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了 + filterChainDefinitionMap.put("/logout", "authc"); + + filterChainDefinitionMap.put("/**", "corsFilter,token,authc"); +// filterChainDefinitionMap.put("/**", "anon"); + + + shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); + return shiroFilterFactoryBean; + } + + + public static boolean isAjax(ServletRequest request) { + String header = ((HttpServletRequest) request).getHeader("X-Requested-With"); + if ("XMLHttpRequest".equalsIgnoreCase(header)) { + System.out.println("当前请求为Ajax请求"); + return Boolean.TRUE; + } + System.out.println("当前请求非Ajax请求"); + return Boolean.FALSE; + } + + @Bean + public SecurityManager securityManager(@Qualifier("myRetryLimitCredentialsMatcher") MyRetryLimitCredentialsMatcher matcher) { + DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); + //设置realm. + securityManager.setRealm(myShiroRealm(matcher)); + // 自定义缓存实现 使用redis + //securityManager.setCacheManager(cacheManager()); + // 自定义session管理 使用redis + securityManager.setSessionManager(sessionManager()); + return securityManager; + } + + @Bean + public MyShiroRealm myShiroRealm(MyRetryLimitCredentialsMatcher matcher) { + MyShiroRealm myShiroRealm = new MyShiroRealm(); + myShiroRealm.setCredentialsMatcher(matcher); + return myShiroRealm; + } + + + /** + * 密码匹配凭证管理器 凭证匹配器 + * (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了 + * 所以我们需要修改下doGetAuthenticationInfo中的代码; + * ) + * + * @return + */ + @Bean(name = "myRetryLimitCredentialsMatcher") + public MyRetryLimitCredentialsMatcher hashedCredentialsMatcher() { + MyRetryLimitCredentialsMatcher hashedCredentialsMatcher = new MyRetryLimitCredentialsMatcher(); + + hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法; + hashedCredentialsMatcher.setHashIterations(2);//散列的次数,比如散列两次,相当于 md5(md5("")); + + return hashedCredentialsMatcher; + } + + + /** + * 开启shiro aop注解支持. + * 使用代理方式;所以需要开启代码支持; + * + * @param securityManager + * @return + */ + @Bean + public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { + AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); + authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); + return authorizationAttributeSourceAdvisor; + } + + /** + * 配置shiro redisManager + * 使用的是shiro-redis开源插件 + * + * @return + */ + public RedisManager redisManager() { + RedisManager redisManager = new RedisManager(); + redisManager.setHost(host); + redisManager.setPort(port); + //redisManager.setExpire(expire);// 配置缓存过期时间 + redisManager.setTimeout(timeout); + redisManager.setPassword(password); + return redisManager; + } + + /** + * cacheManager 缓存 redis实现 + * 使用的是shiro-redis开源插件 + * + * @return + */ + public RedisCacheManager cacheManager() { + RedisCacheManager redisCacheManager = new RedisCacheManager(); + redisCacheManager.setRedisManager(redisManager()); + return redisCacheManager; + } + + + /** + * RedisSessionDAO shiro sessionDao层的实现 通过redis + * 使用的是shiro-redis开源插件 + */ + @Bean + public RedisSessionDAO redisSessionDAO() { + RedisSessionDAO redisSessionDAO = new RedisSessionDAO(); + redisSessionDAO.setRedisManager(redisManager()); + return redisSessionDAO; + } + + /** + * shiro session的管理 + */ + @Bean + public DefaultWebSessionManager sessionManager() { + DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); + //设置session过期时间为1小时(单位:毫秒),默认为30分钟 + sessionManager.setGlobalSessionTimeout(60 * 60 * 1000); + sessionManager.setSessionValidationSchedulerEnabled(true); + sessionManager.setSessionIdUrlRewritingEnabled(false); + + sessionManager.setSessionDAO(redisSessionDAO()); + sessionManager.setSessionIdCookie(simpleCookie()); + return sessionManager; + } + + @Bean + public SimpleCookie simpleCookie() { + SimpleCookie simpleCookie = new SimpleCookie("SSIDS"); + simpleCookie.setDomain(""); + return simpleCookie; + } + +// @Bean +// public SimpleCookie rememberMeCookie(){ +// //System.out.println("ShiroConfiguration.rememberMeCookie()"); +// //这个参数是cookie的名称,对应前端的checkbox的name = rememberMe +// SimpleCookie simpleCookie = new SimpleCookie("rememberMe"); +// // +// simpleCookie.setMaxAge(60*30); +// return simpleCookie; +// } + +// @Bean +// public CookieRememberMeManager rememberMeManager(){ +// //System.out.println("ShiroConfiguration.rememberMeManager()"); +// CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager(); +// cookieRememberMeManager.setCookie(rememberMeCookie()); +// //rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位) +// cookieRememberMeManager.setCipherKey(Base64.decodeBytes("2AvVhdsgUs0FSA3SDFAdag==")); +// return cookieRememberMeManager; +// } + +// @Bean(name = "securityManager") +// public DefaultWebSecurityManager defaultWebSecurityManager(MyShiroRealm realm){ +// DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); +// //设置realm +// securityManager.setRealm(realm); +// //用户授权/认证信息Cache, 采用EhCache缓存 +// securityManager.setCacheManager(cacheManager()); +// //注入记住我管理器 +// securityManager.setRememberMeManager(rememberMeManager()); +// return securityManager; +// } + +} diff --git a/mallinkCallback/src/main/java/com/iformall/config/ShiroLoginFilter.java b/mallinkCallback/src/main/java/com/iformall/config/ShiroLoginFilter.java new file mode 100644 index 000000000..67c07385e --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/config/ShiroLoginFilter.java @@ -0,0 +1,31 @@ +package com.iformall.config; + +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; + +import org.apache.shiro.web.filter.authc.FormAuthenticationFilter; + +import com.alibaba.fastjson.JSON; +import com.iformall.common.ResultData; +public class ShiroLoginFilter extends FormAuthenticationFilter { + + @Override + protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/json"); + ResultData resultData = new ResultData(ResultData.UNLOGIN,"用户未登录"); + response.getWriter().write(JSON.toJSONString(resultData)); + return false; + } + + /** + * 判断ajax请求 + * @param request + * @return + */ + boolean isAjax(HttpServletRequest request){ + return (request.getHeader("X-Requested-With") != null && "XMLHttpRequest".equals( request.getHeader("X-Requested-With").toString()) ) ; + } + +} \ No newline at end of file diff --git a/mallinkCallback/src/main/java/com/iformall/config/WebConfig.java b/mallinkCallback/src/main/java/com/iformall/config/WebConfig.java new file mode 100644 index 000000000..8b1ecddc9 --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/config/WebConfig.java @@ -0,0 +1,131 @@ +package com.iformall.config; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationConfig; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.iformall.interceptor.HttpServletRequestWrapperFilter; +import com.iformall.interceptor.RequestInterceptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CharacterEncodingFilter; +import org.springframework.web.filter.CorsFilter; +import org.springframework.web.servlet.config.annotation.*; + +import javax.servlet.Filter; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.text.SimpleDateFormat; +import java.util.List; + +@Configuration +@EnableWebMvc +@EnableConfigurationProperties({AwsProperty.class}) +public class WebConfig implements WebMvcConfigurer { + + @Autowired + private RequestInterceptor requestInterceptor; + + @Bean + public CorsFilter corsFilter() { + final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource(); + final CorsConfiguration corsConfiguration = new CorsConfiguration(); + // 允许cookies跨域 + corsConfiguration.setAllowCredentials(true); + // 允许向该服务器提交请求的URI, *表示全部允许 + corsConfiguration.addAllowedOrigin("*"); + // 允许访问的头信息,*表示全部 + corsConfiguration.addAllowedHeader("*"); + // 允许提交请求的方法, *表示全部允许 + corsConfiguration.addAllowedMethod("*"); + urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration); + return new CorsFilter(urlBasedCorsConfigurationSource); + } + + /** + * 用于处理编码问题 + * + * @return + */ + @Bean + public Filter characterEncodingFilter() { + CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter(); + characterEncodingFilter.setEncoding("UTF-8"); + characterEncodingFilter.setForceEncoding(true); + return characterEncodingFilter; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(requestInterceptor).addPathPatterns("/**"); + } + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("swagger-ui.html") + .addResourceLocations("classpath:/META-INF/resources/"); + registry.addResourceHandler("/webjars/**") + .addResourceLocations("classpath:/META-INF/resources/webjars/"); + + } + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins("*") + .allowCredentials(true) + .allowedMethods("GET", "POST", "DELETE", "PUT") + .maxAge(3600); + } + + @Override + public void configureMessageConverters(List> converters) { + MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter(); + //ObjectMapper 是Jackson库的主要类。它提供一些功能将转换成Java对象匹配JSON结构,反之亦然 + ObjectMapper objectMapper = new ObjectMapper(); + SimpleModule simpleModule = new SimpleModule(); + + //不显示为null的字段 + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + + DeserializationConfig dc = objectMapper.getDeserializationConfig(); + // 设置反序列化日期格式、忽略不存在get、set的属性 + objectMapper.setConfig( + dc.with(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")) + .without(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + ); + + //序列化将Long转String类型 + simpleModule.addSerializer(Long.class, ToStringSerializer.instance); + simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance); + SimpleModule bigIntegerModule = new SimpleModule(); + //序列化将BigInteger转String类型 + bigIntegerModule.addSerializer(BigInteger.class, ToStringSerializer.instance); + SimpleModule bigDecimalModule = new SimpleModule(); + //序列化将BigDecimal转String类型 + bigDecimalModule.addSerializer(BigDecimal.class, ToStringSerializer.instance); + objectMapper.registerModule(simpleModule); + objectMapper.registerModule(bigDecimalModule); + objectMapper.registerModule(bigIntegerModule); + jackson2HttpMessageConverter.setObjectMapper(objectMapper); + converters.add(jackson2HttpMessageConverter); + } + + @Bean + public FilterRegistrationBean Filters() { + FilterRegistrationBean registrationBean = new FilterRegistrationBean(); + registrationBean.setFilter(new HttpServletRequestWrapperFilter()); + registrationBean.addUrlPatterns("/*"); + registrationBean.setName("koalaSignFilter"); + return registrationBean; + } +} diff --git a/mallinkCallback/src/main/java/com/iformall/config/WechatMpConfig.java b/mallinkCallback/src/main/java/com/iformall/config/WechatMpConfig.java new file mode 100644 index 000000000..4dff6c762 --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/config/WechatMpConfig.java @@ -0,0 +1,33 @@ +package com.iformall.config; + +import me.chanjar.weixin.mp.api.WxMpConfigStorage; +import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Component; + +@Component +public class WechatMpConfig { + + @Autowired + private WechatWebProperties wechatWebProperties; + + @Bean + public WxMpService wxMpService() { + //创建WxMpService实例并设置appid和sectret + WxMpService wxMpService = new WxMpServiceImpl(); + //这里的设置方式是跟着这个sdk的文档写的 + wxMpService.setWxMpConfigStorage(wxConfigProvider()); + return wxMpService; + } + + @Bean + public WxMpConfigStorage wxConfigProvider(){ + WxMpInMemoryConfigStorage wxConfigProvider = new WxMpInMemoryConfigStorage(); + wxConfigProvider.setAppId(wechatWebProperties.getAppId()); + wxConfigProvider.setSecret(wechatWebProperties.getSecret()); + return wxConfigProvider; + } +} diff --git a/mallinkCallback/src/main/java/com/iformall/config/WechatWebProperties.java b/mallinkCallback/src/main/java/com/iformall/config/WechatWebProperties.java new file mode 100644 index 000000000..0b9047399 --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/config/WechatWebProperties.java @@ -0,0 +1,59 @@ +package com.iformall.config; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * Stormeye + */ +@Component +@ConfigurationProperties(prefix = "wechat.web") +public class WechatWebProperties { + /** + * 设置微信第三方平台-微信登录的web应用appid + */ + private String appId; + + /** + * 设置微信第三方平台-微信登录的web应用app secret + */ + private String secret; + + /** + * 网页URL + * @return + */ + private String url; + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public String getSecret() { + return secret; + } + + public void setSecret(String secret) { + this.secret = secret; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, + ToStringStyle.MULTI_LINE_STYLE); + } +} diff --git a/mallinkCallback/src/main/java/com/iformall/controller/base/BaseController.java b/mallinkCallback/src/main/java/com/iformall/controller/base/BaseController.java new file mode 100644 index 000000000..b770e6240 --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/controller/base/BaseController.java @@ -0,0 +1,46 @@ +package com.iformall.controller.base; + +import com.iformall.utils.IPUtil; +import org.springframework.web.bind.WebDataBinder; +import org.springframework.web.bind.annotation.InitBinder; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import java.beans.PropertyEditorSupport; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +@RestController +public class BaseController { + + @InitBinder + public void InitBinder(WebDataBinder dataBinder) { + dataBinder.registerCustomEditor(Date.class, new PropertyEditorSupport() { + public void setAsText(String value) { + try { + setValue(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(value)); + } catch(ParseException e) { + try { + setValue(new SimpleDateFormat("yyyy-MM-dd ").parse(value)); + } catch (ParseException e1) { + setValue(null); + } + } + } + + public String getAsText() { + return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date) getValue()); + } + + }); + } + + public String getIpAddr() { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + String ipaddress = IPUtil.getIpAddr(request); + return ipaddress; + } +} diff --git a/mallinkAdmin/src/main/java/com/iformall/controller/callback/WxCarCallBackController.java b/mallinkCallback/src/main/java/com/iformall/controller/callback/WxCarCallBackController.java similarity index 100% rename from mallinkAdmin/src/main/java/com/iformall/controller/callback/WxCarCallBackController.java rename to mallinkCallback/src/main/java/com/iformall/controller/callback/WxCarCallBackController.java diff --git a/mallinkCallback/src/main/java/com/iformall/controller/callback/WxMsgCallbackController.java b/mallinkCallback/src/main/java/com/iformall/controller/callback/WxMsgCallbackController.java new file mode 100644 index 000000000..982646556 --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/controller/callback/WxMsgCallbackController.java @@ -0,0 +1,48 @@ +package com.iformall.controller.callback; + +import com.iformall.controller.base.BaseController; +import com.iformall.service.WxMsgCallbackService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +@RestController +@RequestMapping("wxMsgCallback") +public class WxMsgCallbackController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxMsgCallbackService wxMsgCallbackService; + + + @PostMapping(value = "/receivemsg/{tenantId}") + public void receivemsg(@PathVariable String tenantId, @RequestParam Map param) { + logger.debug("[" + getIpAddr() + "] WxMsgCallbackController::receivemsg"); + logger.info(param.toString()); + //解析param数据插入数据库中 + wxMsgCallbackService.saveOrUpdate(tenantId,param); + + } + + @RequestMapping(value = "/receivemodel/{tenantId}") + public void receivemodel(@PathVariable String tenantId, @RequestParam Map param) { + logger.debug("[" + getIpAddr() + "] WxMsgCallbackController::receivemodel"); + logger.info(param.toString()); + //解析param数据插入数据库中 + wxMsgCallbackService.receivemodel(tenantId, param); + + } + + @RequestMapping(value = "/receiveverifymodel/{tenantId}") + public void receiveverifymodel(@PathVariable String tenantId, @RequestParam Map param) { + logger.debug("[" + getIpAddr() + "] WxMsgCallbackController::receiveverifymodel"); + logger.info(param.toString()); + //解析param数据插入数据库中 + wxMsgCallbackService.receiveverifymodel(tenantId, param); + + } + +} diff --git a/mallinkAdmin/src/main/java/com/iformall/controller/callback/WxPayBillController.java b/mallinkCallback/src/main/java/com/iformall/controller/callback/WxPayBillController.java similarity index 100% rename from mallinkAdmin/src/main/java/com/iformall/controller/callback/WxPayBillController.java rename to mallinkCallback/src/main/java/com/iformall/controller/callback/WxPayBillController.java diff --git a/mallinkAdmin/src/main/java/com/iformall/controller/callback/WxPayController.java b/mallinkCallback/src/main/java/com/iformall/controller/callback/WxPayController.java similarity index 98% rename from mallinkAdmin/src/main/java/com/iformall/controller/callback/WxPayController.java rename to mallinkCallback/src/main/java/com/iformall/controller/callback/WxPayController.java index b31089b71..b25eab215 100644 --- a/mallinkAdmin/src/main/java/com/iformall/controller/callback/WxPayController.java +++ b/mallinkCallback/src/main/java/com/iformall/controller/callback/WxPayController.java @@ -13,9 +13,11 @@ import org.apache.commons.io.IOUtils; import org.jdom2.JDOMException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.http.MediaType; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import java.io.ByteArrayOutputStream; diff --git a/mallinkAdmin/src/main/java/com/iformall/controller/device/WxDeviceScreenAdController.java b/mallinkCallback/src/main/java/com/iformall/controller/device/WxDeviceScreenAdController.java similarity index 100% rename from mallinkAdmin/src/main/java/com/iformall/controller/device/WxDeviceScreenAdController.java rename to mallinkCallback/src/main/java/com/iformall/controller/device/WxDeviceScreenAdController.java diff --git a/mallinkCallback/src/main/java/com/iformall/controller/official/WxMallApplyController.java b/mallinkCallback/src/main/java/com/iformall/controller/official/WxMallApplyController.java new file mode 100644 index 000000000..20120b8a2 --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/controller/official/WxMallApplyController.java @@ -0,0 +1,36 @@ +package com.iformall.controller.official; + +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxMsgValidationcode; +import com.iformall.service.WxMallApplyService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("wxMallApply") +public class WxMallApplyController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxMallApplyService wxMallApplyService; + + @GetMapping("/sendvalidationcode") + @ApiImplicitParams({ + @ApiImplicitParam(name = "phone", value = "手机号", dataType = "String", paramType = "query", required = true), + @ApiImplicitParam(name = "type", value = "场景", dataType = "Integer", paramType = "query", required = true)}) + public ResultData sendvalidationcode(String phone, Integer type) { + logger.debug("[" + getIpAddr() + "] WxMallApplyController::sendvalidationcode"); + WxMsgValidationcode wxMsgValidationcode = new WxMsgValidationcode(); + wxMsgValidationcode.setTenantId("1"); + wxMsgValidationcode.setPhone(phone); + wxMsgValidationcode.setType(type); + return wxMallApplyService.sendvalidationcode(wxMsgValidationcode); + } + + +} diff --git a/mallinkCallback/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java b/mallinkCallback/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java new file mode 100644 index 000000000..7be788b6e --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java @@ -0,0 +1,76 @@ +package com.iformall.interceptor; + +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import java.io.*; + +public class BodyReaderHttpServletRequestWrapper extends XssHttpServletRequestWrapper { + private final String body; + + public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException { + super(request); + StringBuffer stringBuilder = new StringBuffer(); + BufferedReader bufferedReader = null; + try { + InputStream inputStream = request.getInputStream(); + if (inputStream != null) { + bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"utf-8")); + char[] charBuffer = new char[1024]; + int bytesRead = -1; + while ((bytesRead = bufferedReader.read(charBuffer)) > 0) { + stringBuilder.append(charBuffer, 0, bytesRead); + } + } else { + stringBuilder.append(""); + } + } catch (IOException ex) { + throw ex; + } finally { + if (bufferedReader != null) { + try { + bufferedReader.close(); + } catch (IOException ex) { + throw ex; + } + } + } + body = stringBuilder.toString(); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + final ByteArrayInputStream byteArrayInputStream = + new ByteArrayInputStream(body.getBytes("utf-8")); + return new ServletInputStream() { + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) { + + } + + @Override + public int read() throws IOException { + return byteArrayInputStream.read(); + } + }; + } + + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(this.getInputStream())); + } + + public String getBody() { + return this.body; + } +} diff --git a/mallinkCallback/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java b/mallinkCallback/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java new file mode 100644 index 000000000..aebf7d874 --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java @@ -0,0 +1,72 @@ +package com.iformall.interceptor; + +import com.iformall.utils.UrlCheck; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Arrays; + +public class HttpServletRequestWrapperFilter implements Filter { + private static final Logger logger = LoggerFactory.getLogger(HttpServletRequestWrapperFilter.class); + // 多个跨域域名设置 + // public static final String[] ALLOW_DOMAIN = {"https://admin.malls.iformall.com"}; + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + + ServletRequest requestWrapper = null; + /* // 跨域访问 + HttpServletRequest req = (HttpServletRequest) request; + HttpServletResponse res = (HttpServletResponse) response; + String originHeader = req.getHeader("Origin"); + + if (Arrays.asList(ALLOW_DOMAIN).contains(originHeader)) { + //通过在响应 header 中设置 ‘*’ 来允许来自所有域的跨域请求访问。 + res.setHeader("Access-Control-Allow-Origin", originHeader); + //通过对 Credentials 参数的设置,就可以保持跨域 Ajax 时的 Cookie + //设置了Allow-Credentials,Allow-Origin就不能为*,需要指明具体的url域 + res.setHeader("Access-Control-Allow-Credentials", "true"); + //请求方式 + res.setHeader("Access-Control-Allow-Methods", "*"); + //(预检请求)的返回结果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息) 可以被缓存多久 + res.setHeader("Access-Control-Max-Age", "86400"); + //首部字段用于预检请求的响应。其指明了实际请求中允许携带的首部字段 + //res.setHeader("Access-Control-Allow-Headers", "*"); + res.setHeader("Access-Control-Allow-Headers", + "Timestamp,Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token,Access-Control-Allow-Headers"); + } + */ + + //sql,xss过滤 + XssHttpServletRequestWrapper xssHttpServletRequestWrapper = new XssHttpServletRequestWrapper((HttpServletRequest)request); + + if (request instanceof HttpServletRequest) { + String url = ((HttpServletRequest) request).getRequestURI(); + if (!UrlCheck.checkUrl(url)) { + requestWrapper = new BodyReaderHttpServletRequestWrapper((HttpServletRequest) request); + } + } + if (null == requestWrapper) { + chain.doFilter(xssHttpServletRequestWrapper, response); + } else { + chain.doFilter(requestWrapper, response); + } + + } + + + @Override + public void destroy() { + + } +} diff --git a/mallinkCallback/src/main/java/com/iformall/interceptor/RequestInterceptor.java b/mallinkCallback/src/main/java/com/iformall/interceptor/RequestInterceptor.java new file mode 100644 index 000000000..d01a11de5 --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/interceptor/RequestInterceptor.java @@ -0,0 +1,117 @@ +package com.iformall.interceptor; + +import com.iformall.common.ErrorCode; +import com.iformall.exception.MallinkException; +import com.iformall.utils.HashUtil; +import com.iformall.utils.IPUtil; +import com.iformall.utils.UrlCheck; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.dao.DataAccessException; +import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.data.redis.core.RedisCallback; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; +import redis.clients.jedis.Protocol; +import redis.clients.util.SafeEncoder; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.Enumeration; +import java.util.concurrent.TimeUnit; + +/** + * 幂等检查 + * @author stormeye.wu + * @email wuguoqiang@iformall.com + * @date 2017-03-23 15:38 + */ +@Component +public class RequestInterceptor extends HandlerInterceptorAdapter { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Resource + private RedisTemplate redisTemplate; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + if ("GET".equalsIgnoreCase(request.getMethod())) { + // 获取不检查幂等 + return true; + } + + String ipaddress = IPUtil.getIpAddr(request); + String url = request.getRequestURL().toString(); + if (UrlCheck.checkUrl(url)) { + // pvlog不检查幂等 + // awsFileUpload不检查幂等 + // ueditor 不检查幂等 + return true; + } + StringBuilder sb = new StringBuilder(); + sb.append(url); + sb.append("method=").append(request.getMethod()).append("&"); + sb.append("ip=").append(ipaddress).append("&"); + + final Enumeration parameterNames = request.getParameterNames(); + while (parameterNames.hasMoreElements()) { + String key = (String) parameterNames.nextElement(); + if(key.equalsIgnoreCase("ran")) // 跳过ran + continue; + String parameter = request.getParameter(key); + sb.append(key).append("=").append(parameter).append("&"); + } + + InputStream inStream = request.getInputStream(); + ByteArrayOutputStream outSteam = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int len = 0; + while ((len = inStream.read(buffer)) != -1) { + outSteam.write(buffer, 0, len); + } + String resultBody = new String(outSteam.toByteArray(), Charset.forName("UTF-8")); + inStream.close(); + outSteam.close(); + + sb.append(resultBody); + + String key = "request:A:" + HashUtil.md5(sb.toString()); + Boolean isAbsent = redisTemplate.execute(new RedisCallback() { + @Override + public Boolean doInRedis(RedisConnection connection) throws DataAccessException { + RedisSerializer valueSerializer = redisTemplate.getValueSerializer(); + RedisSerializer keySerializer = redisTemplate.getKeySerializer(); + Object obj = connection.execute("set", keySerializer.serialize(key), + valueSerializer.serialize(key), + SafeEncoder.encode("NX"), + SafeEncoder.encode("EX"), + Protocol.toByteArray(3)); // 3s + return obj != null; + } + }); + if (isAbsent) { + logger.info(key + ": 第一次提交"); + return true; + } + logger.info(key + ": 第二次提交"); + throw new MallinkException(ErrorCode.SYS_REPEAT_SUBMIT_EXCEPTION); + } + + @Override + public void postHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { + + } + + @Override + public void afterCompletion(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, Exception ex) throws Exception { + + } +} diff --git a/mallinkCallback/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java b/mallinkCallback/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java new file mode 100644 index 000000000..1d954d163 --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java @@ -0,0 +1,125 @@ +package com.iformall.interceptor; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * 防止sql注入,xss攻击 + * 前端可以对输入信息做预处理,后端也可以做处理。 + */ +public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { + private final Logger log = LoggerFactory.getLogger(getClass()); + private static String key = "and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+"; + private static Set notAllowedKeyWords = new HashSet(0); + private static String replacedString="INVALID"; + static { + String keyStr[] = key.split("\\|"); + for (String str : keyStr) { + notAllowedKeyWords.add(str); + } + } + + private String currentUrl; + + public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) { + super(servletRequest); + currentUrl = servletRequest.getRequestURI(); + } + + + /**覆盖getParameter方法,将参数名和参数值都做xss过滤。 + * 如果需要获得原始的值,则通过super.getParameterValues(name)来获取 + * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖 + */ + @Override + public String getParameter(String parameter) { + String value = super.getParameter(parameter); + if (value == null) { + return null; + } + return cleanXSS(value); + } + @Override + public String[] getParameterValues(String parameter) { + String[] values = super.getParameterValues(parameter); + if (values == null) { + return null; + } + int count = values.length; + String[] encodedValues = new String[count]; + for (int i = 0; i < count; i++) { + encodedValues[i] = cleanXSS(values[i]); + } + return encodedValues; + } + @Override + public Map getParameterMap(){ + Map values=super.getParameterMap(); + if (values == null) { + return null; + } + Map result=new HashMap<>(); + for(String key:values.keySet()){ + String encodedKey=cleanXSS(key); + int count=values.get(key).length; + String[] encodedValues = new String[count]; + for (int i = 0; i < count; i++){ + encodedValues[i]=cleanXSS(values.get(key)[i]); + } + result.put(encodedKey,encodedValues); + } + return result; + } + /** + * 覆盖getHeader方法,将参数名和参数值都做xss过滤。 + * 如果需要获得原始的值,则通过super.getHeaders(name)来获取 + * getHeaderNames 也可能需要覆盖 + */ + @Override + public String getHeader(String name) { + if(name.equalsIgnoreCase("user-agent")) { + return super.getHeader(name); + } + String value = super.getHeader(name); + if (value == null) { + return null; + } + return cleanXSS(value); + } + + private String cleanXSS(String valueP) { + // You'll need to remove the spaces from the html entities below + String value = valueP.replaceAll("<", "<").replaceAll(">", ">"); + value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;"); + value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;"); + value = value.replaceAll("'", "& #39;"); + value = value.replaceAll("eval\\((.*)\\)", ""); + value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\""); + value = value.replaceAll("script", ""); + value = cleanSqlKeyWords(value); + return value; + } + + private String cleanSqlKeyWords(String value) { + String paramValue = value; + for (String keyword : notAllowedKeyWords) { + if (paramValue.length() > keyword.length() + 4 + && (paramValue.contains(" "+keyword)||paramValue.contains(keyword+" ")||paramValue.contains(" "+keyword+" "))) { + paramValue = StringUtils.replace(paramValue, keyword, replacedString); + log.error(this.currentUrl + "已被过滤,因为参数中包含不允许sql的关键词(" + keyword + + ")"+";参数:"+value+";过滤后的参数:"+paramValue); + } + } + return paramValue; + } + +} diff --git a/mallinkCallback/src/main/java/com/iformall/shiro/MyRetryLimitCredentialsMatcher.java b/mallinkCallback/src/main/java/com/iformall/shiro/MyRetryLimitCredentialsMatcher.java new file mode 100644 index 000000000..e71e52c61 --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/shiro/MyRetryLimitCredentialsMatcher.java @@ -0,0 +1,45 @@ +package com.iformall.shiro; + +import com.iformall.common.ErrorCode; +import com.iformall.domain.po.MallUserInfo; +import com.iformall.enums.EnumLoginType; +import com.iformall.enums.EnumMallUserStatus; +import com.iformall.service.MallUserInfoService; +import org.apache.shiro.authc.AuthenticationInfo; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.authc.DisabledAccountException; +import org.apache.shiro.authc.UnknownAccountException; +import org.apache.shiro.authc.credential.HashedCredentialsMatcher; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.Resource; + +@Configuration +public class MyRetryLimitCredentialsMatcher extends HashedCredentialsMatcher { + @Resource + private MallUserInfoService userService; + + @Override + public boolean doCredentialsMatch(AuthenticationToken authcToken, AuthenticationInfo info) { + if(authcToken instanceof UseriFormallToken) { + UseriFormallToken tk = (UseriFormallToken) authcToken; + if(tk.getType().equals(EnumLoginType.NOPASSWD)){ + // 获取用户的输入的账号. + String username = (String)tk.getPrincipal(); + MallUserInfo user = userService.getByUsername(username); + if(user == null) { + throw new UnknownAccountException(ErrorCode.USER_IS_EMPTY.getMessage()); + } + // 用户被禁用 + if(user.getStatus()==null ||!EnumMallUserStatus.VALID.getCode().equals(user.getStatus())) { + throw new DisabledAccountException(ErrorCode.USER_IS_LOCKED.getMessage()); + } + return true; + } + boolean matches = super.doCredentialsMatch(authcToken, info); + return matches; + } + boolean matches =super.doCredentialsMatch(authcToken, info); + return matches; + } +} diff --git a/mallinkCallback/src/main/java/com/iformall/shiro/MyShiroRealm.java b/mallinkCallback/src/main/java/com/iformall/shiro/MyShiroRealm.java new file mode 100644 index 000000000..e20788087 --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/shiro/MyShiroRealm.java @@ -0,0 +1,79 @@ +package com.iformall.shiro; + +import com.iformall.common.ErrorCode; +import com.iformall.domain.po.MallUserInfo; +import com.iformall.enums.EnumMallUserStatus; +import com.iformall.service.MallUserInfoService; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.authc.*; +import org.apache.shiro.authz.AuthorizationInfo; +import org.apache.shiro.authz.SimpleAuthorizationInfo; +import org.apache.shiro.realm.AuthorizingRealm; +import org.apache.shiro.session.Session; +import org.apache.shiro.subject.PrincipalCollection; +import org.apache.shiro.util.ByteSource; + +import javax.annotation.Resource; +import java.util.Set; + +/** + * Created by yangqj on 2017/4/21. + */ +public class MyShiroRealm extends AuthorizingRealm { + + @Resource + private MallUserInfoService userService; + + //授权 + @Override + protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { + MallUserInfo user= (MallUserInfo) SecurityUtils.getSubject().getPrincipal(); + Set permissionSet = userService.getUserPermissions(user); + SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); + info.setStringPermissions(permissionSet); + return info; + } + + //认证 + @Override + protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { + //获取用户的输入的账号. + String username = (String)token.getPrincipal(); + MallUserInfo user = userService.getByUsername(username); + if(user == null) { + throw new UnknownAccountException(ErrorCode.USER_IS_EMPTY.getMessage()); + } + if(user.getTenantId().equals("1")) { + // 只支持租户为1的用户 + throw new UnknownAccountException("租户不支持"); + } + if(user.getStatus()==null || + !EnumMallUserStatus.VALID.getCode().equals(user.getStatus())) {//用户被禁用 + throw new DisabledAccountException(ErrorCode.USER_IS_LOCKED.getMessage()); + } + SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( + user, //用户 + user.getPassword(), //密码 + ByteSource.Util.bytes(username), + getName() //realm name + ); + // 当验证都通过后,把用户信息放在session里 + Session session = SecurityUtils.getSubject().getSession(); + session.setAttribute(UserSession.userInfo, user); + session.setAttribute(UserSession.userId, user.getId()); + session.setAttribute(UserSession.tenantId, user.getTenantId()); + return authenticationInfo; + } + + + /** + * 指定principalCollection 清除 + */ + /* public void clearCachedAuthorizationInfo(PrincipalCollection principalCollection) { + + SimplePrincipalCollection principals = new SimplePrincipalCollection( + principalCollection, getName()); + super.clearCachedAuthorizationInfo(principals); + } +*/ +} diff --git a/mallinkCallback/src/main/java/com/iformall/shiro/PasswordHelper.java b/mallinkCallback/src/main/java/com/iformall/shiro/PasswordHelper.java new file mode 100644 index 000000000..f64052666 --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/shiro/PasswordHelper.java @@ -0,0 +1,32 @@ +package com.iformall.shiro; + + +import com.iformall.domain.po.MallUserInfo; +import org.apache.shiro.crypto.hash.SimpleHash; +import org.apache.shiro.util.ByteSource; + + +public class PasswordHelper { + //private RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator(); + private String algorithmName = "md5"; + private int hashIterations = 2; + + public void encryptPassword(MallUserInfo user) { + //String salt=randomNumberGenerator.nextBytes().toHex(); + String newPassword = new SimpleHash(algorithmName, user.getPassword(), ByteSource.Util.bytes(user.getUsername()), hashIterations).toHex(); + //String newPassword = new SimpleHash(algorithmName, user.getPassword()).toHex(); + user.setPassword(newPassword); + + } + + public static void main(String[] args) { + MallUserInfo user = new MallUserInfo(); + user.setUsername("fmkjadmin"); + user.setPassword("fmkjadmin790"); + PasswordHelper passwordHelper = new PasswordHelper(); + passwordHelper.encryptPassword(user); + System.out.println(user); + System.out.println(user.getPassword()); + } + +} diff --git a/mallinkCallback/src/main/java/com/iformall/shiro/ShiroService.java b/mallinkCallback/src/main/java/com/iformall/shiro/ShiroService.java new file mode 100644 index 000000000..a9621c7b7 --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/shiro/ShiroService.java @@ -0,0 +1,126 @@ +package com.iformall.shiro; + +import com.iformall.service.MallPermissionService; +import org.apache.shiro.spring.web.ShiroFilterFactoryBean; +import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager; +import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver; +import org.apache.shiro.web.servlet.AbstractShiroFilter; +import org.crazycake.shiro.RedisSessionDAO; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Created by yangqj on 2017/4/30. + */ +//@Service +public class ShiroService { + @Autowired + private ShiroFilterFactoryBean shiroFilterFactoryBean; + @Autowired + private MallPermissionService resourcesService; + @Autowired + private RedisSessionDAO redisSessionDAO; + /** + * 初始化权限 + */ + public Map loadFilterChainDefinitions() { + // 权限控制map.从数据库获取 + Map filterChainDefinitionMap = new LinkedHashMap(); + filterChainDefinitionMap.put("/logout", "logout"); + filterChainDefinitionMap.put("/css/**","anon"); + filterChainDefinitionMap.put("/js/**","anon"); + filterChainDefinitionMap.put("/img/**","anon"); + filterChainDefinitionMap.put("/user/**","anon"); + filterChainDefinitionMap.put("/font-awesome/**","anon"); +// Map map = new HashMap<>(); +// List resourcesList = resourcesService.list(map); +// for(SysPermission resources:resourcesList){ +// +// if (StringUtil.isNotEmpty(resources.getUrl())) { +// String permission = "perms[" + resources.getUrl()+ "]"; +// filterChainDefinitionMap.put(resources.getUrl(),permission); +// } +// } + filterChainDefinitionMap.put("/**", "authc"); + return filterChainDefinitionMap; + } + + /** + * 重新加载权限 + */ + public void updatePermission() { + + synchronized (shiroFilterFactoryBean) { + + AbstractShiroFilter shiroFilter = null; + try { + shiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean + .getObject(); + } catch (Exception e) { + throw new RuntimeException( + "get ShiroFilter from shiroFilterFactoryBean error!"); + } + + PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter + .getFilterChainResolver(); + DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver + .getFilterChainManager(); + + // 清空老的权限控制 + manager.getFilterChains().clear(); + + shiroFilterFactoryBean.getFilterChainDefinitionMap().clear(); + shiroFilterFactoryBean + .setFilterChainDefinitionMap(loadFilterChainDefinitions()); + // 重新构建生成 + Map chains = shiroFilterFactoryBean + .getFilterChainDefinitionMap(); + for (Map.Entry entry : chains.entrySet()) { + String url = entry.getKey(); + String chainDefinition = entry.getValue().trim() + .replace(" ", ""); + manager.createChain(url, chainDefinition); + } + + System.out.println("更新权限成功!!"); + } + } + + /** + * 根据userId 清除当前session存在的用户的权限缓存 + * @param userIds 已经修改了权限的userId + */ + /* public void clearUserAuthByUserId(List userIds){ + if(null == userIds || userIds.size() == 0) return ; + //获取所有session + Collection sessions = redisSessionDAO.getActiveSessions(); + //定义返回 + List list = new ArrayList(); + for (Session session:sessions){ + //获取session登录信息。 + Object obj = session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY); + if(null != obj && obj instanceof SimplePrincipalCollection){ + //强转 + SimplePrincipalCollection spc = (SimplePrincipalCollection)obj; + //判断用户,匹配用户ID。 + obj = spc.getPrimaryPrincipal(); + if(null != obj && obj instanceof User){ + User user = (User) obj; + System.out.println("user:"+user); + //比较用户ID,符合即加入集合 + if(null != user && userIds.contains(user.getId())){ + list.add(spc); + } + } + } + } + RealmSecurityManager securityManager = + (RealmSecurityManager) SecurityUtils.getSecurityManager(); + MyShiroRealm realm = (MyShiroRealm)securityManager.getRealms().iterator().next(); + for (SimplePrincipalCollection simplePrincipalCollection : list) { + realm.clearCachedAuthorizationInfo(simplePrincipalCollection); + } + }*/ +} diff --git a/mallinkCallback/src/main/java/com/iformall/shiro/UserSession.java b/mallinkCallback/src/main/java/com/iformall/shiro/UserSession.java new file mode 100644 index 000000000..02a7aca87 --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/shiro/UserSession.java @@ -0,0 +1,11 @@ +package com.iformall.shiro; + +public class UserSession { + + public static String userInfo="userSession"; + + public static String userId ="userSessionId"; + + public static String tenantId ="TENANT_ID"; + +} diff --git a/mallinkCallback/src/main/java/com/iformall/shiro/UseriFormallToken.java b/mallinkCallback/src/main/java/com/iformall/shiro/UseriFormallToken.java new file mode 100644 index 000000000..04f525a73 --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/shiro/UseriFormallToken.java @@ -0,0 +1,39 @@ +package com.iformall.shiro; + +import com.iformall.enums.EnumLoginType; +import org.apache.shiro.authc.UsernamePasswordToken; + +public class UseriFormallToken extends UsernamePasswordToken { + private static final long serialVersionUID = -2564928913725078138L; + + private EnumLoginType type; + + public UseriFormallToken() { + super(); + } + + public UseriFormallToken(String username, String password, EnumLoginType type, boolean rememberMe, String host) { + super(username, password, rememberMe, host); + this.type = type; + } + + /** 免密登录 */ + public UseriFormallToken(String username) { + super(username, "", false, null); + this.type = EnumLoginType.NOPASSWD; + } + /** 账号密码登录 */ + public UseriFormallToken(String username, String pwd) { + super(username, pwd, false, null); + this.type = EnumLoginType.PASSWORD; + } + + public EnumLoginType getType() { + return type; + } + + + public void setType(EnumLoginType type) { + this.type = type; + } +} diff --git a/mallinkCallback/src/main/java/com/iformall/utils/PayUtil.java b/mallinkCallback/src/main/java/com/iformall/utils/PayUtil.java new file mode 100644 index 000000000..9776aad04 --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/utils/PayUtil.java @@ -0,0 +1,37 @@ +package com.iformall.utils; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.EncodeHintType; +import com.google.zxing.MultiFormatWriter; +import com.google.zxing.WriterException; +import com.google.zxing.common.BitMatrix; +import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; + +import java.awt.image.BufferedImage; +import java.util.Hashtable; +import java.util.Map; + +public class PayUtil { + /** + * 根据url生成二位图片对象 + * + * @param codeUrl + * @return + * @throws WriterException + */ + public static BufferedImage getQRCodeImge(String codeUrl) throws WriterException { + Map hints = new Hashtable(); + hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M); + hints.put(EncodeHintType.CHARACTER_SET, "UTF8"); + int width = 256; + BitMatrix bitMatrix = (new MultiFormatWriter()).encode(codeUrl, BarcodeFormat.QR_CODE, width, width, hints); + BufferedImage image = new BufferedImage(width, width, 1); + for(int x = 0; x < width; ++x) { + for(int y = 0; y < width; ++y) { + image.setRGB(x, y, bitMatrix.get(x, y) ? -16777216 : -1); + } + } + + return image; + } +} diff --git a/mallinkCallback/src/main/java/com/iformall/utils/UrlCheck.java b/mallinkCallback/src/main/java/com/iformall/utils/UrlCheck.java new file mode 100644 index 000000000..2a4dcf90a --- /dev/null +++ b/mallinkCallback/src/main/java/com/iformall/utils/UrlCheck.java @@ -0,0 +1,22 @@ +package com.iformall.utils; + +/** + * @author gongbiao + */ +public class UrlCheck { + + public static boolean checkUrl(String url) { + return url.contains("awsFileUpload") + || url.contains("awsFilesUpload") + || url.contains("downQrCode") + || url.contains("cimgUpload") + || url.contains("ueditor/exec") + || url.contains("/wxCUserBasicInfo/importTemplate") + || url.contains("/wxCUserBasicInfo/countByFilter") + || url.contains("/wxCUserBasicInfo/listByFilter") + || url.contains("wxMsgCallback") + || url.contains("notify") + || url.contains("pvlog"); + } + +} diff --git a/mallinkCallback/src/main/resources/application-dev.yml b/mallinkCallback/src/main/resources/application-dev.yml new file mode 100644 index 000000000..fe51e0daf --- /dev/null +++ b/mallinkCallback/src/main/resources/application-dev.yml @@ -0,0 +1,120 @@ +spring: + profiles: + include: rabbitMQ + # JDBC + datasource: + url: jdbc:mysql://202.165.179.86:3306/mallinkDev?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useUnicode=true&useSSL=false&useAffectedRows=true + username: ENC(dZ8fmrtuBMQYaRytKQgTqg==) + password: ENC(WGu0+1DPIHrqorDhrbq1+7wr7xNG53mN) + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + filters: stat + maxActive: 20 + initialSize: 1 + maxWait: 60000 + minIdle: 1 + timeBetweenEvictionRunsMillis: 28000 + minEvictableIdleTimeMillis: 28000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + connectionProperties: "druid.stat.mergeSql=true;druid.stat.slowSqlMillis=6000" + #jackson: + #date-format: yyyy-MM-dd HH:mm:ss + # REDIS + redis: + host: 202.165.179.86 + port: 6379 + password: ENC(aYJ3Wr2UWtkORRQjjrWWpz2ZeTISsHOA) + timeout: 3600 + expire: 1800 #30分钟 + database: 1 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 500 + max-wait: -1 + min-idle: 10 + # EMAIL + mail: + host: smtp.exmail.qq.com + username: ENC(lknBjZsA24AaQEXuy0fFw3acd4v4Xsf3CsgDcRZgjlYnNAL9R07d/w==) + password: ENC(gIkVPuYMmJ/EDxry8QIfGumIAk4plAwolGrfg1fiM3U=) # 授权密码 + properties: + mail: + smtp: + auth: true + starttls: + enable: true + socketFactory: + port: 465 + class: javax.net.ssl.SSLSocketFactory + # ROCKETMQ + rocketmq: + nameServer: 127.0.0.1:9876 + producer: + retry-times-when-send-async-failed: 0 + send-msg-timeout: 300000 + compress-msg-body-over-howmuch: 4096 + max-message-size: 4194304 + retry-another-broker-when-not-store-ok: false + retry-times-when-send-failed: 2 + # RABBITMQ + rabbitmq: + host: 202.165.179.86 + port: 5672 + username: fumao + password: f8l89&*%%u7f1t22 + publisher-confirms: true + virtual-host: / + +aws: + clientRegion: cn-northwest-1 + bucketName: iformall-net + access: ENC(3gx5ghDFBqGrEhO3Wf8aYmXsnwHO7Cj3HNKJGOeUj0o=) + secret: ENC(HVKIJwCJKVXLlUpGlQPwNqJOlnpxn4xYuy91SH0seTSm2uAttIQHvA49fXWWax90v5wloIk0QuU=) + +wechat: + web: + appId: "wxe31beafbfd8295ba" + secret: "c689fabf3c4c9f5b6424ff2a36a26727" + url: "https://mall.youlane.cn" + open: + componentAppId: "wx897e4673286c915d" + componentSecret: "cdfdfda65c45689beb6766c4c427eed2" + componentToken: "formall2018" + componentAesKey: "htKq8EjBMPNndfZQK9JiFojFaqFwFpw42VfeWFtx7HN" + redis: + host: 202.165.179.86 + port: 6379 + password: ENC(aYJ3Wr2UWtkORRQjjrWWpz2ZeTISsHOA) + timeout: 3600 + expire: 1800 #30分钟 + database: 2 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 500 + max-wait: -1 + min-idle: 10 + +jasypt: + encryptor: + password: oRqdnDbK5pj3eMmB + +fm: + exception: false + exception_emails: hupeng@iformall.com,wuguoqiang@iformall.com,gongbiao@iformall.com,luozukai@iformall.com,hanxueda@iformall.com + deploy: 1 + open: true + +logging: + level: + tk.mybatis: debug + com.iformall: debug + path: ./logs/admin \ No newline at end of file diff --git a/mallinkCallback/src/main/resources/application-prod.yml b/mallinkCallback/src/main/resources/application-prod.yml new file mode 100644 index 000000000..69ed3a0a3 --- /dev/null +++ b/mallinkCallback/src/main/resources/application-prod.yml @@ -0,0 +1,104 @@ +spring: + profiles: + include: rabbitMQ + # JDBC + datasource: + url: jdbc:mysql://formalldb.cfqyqflkdlit.rds.cn-northwest-1.amazonaws.com.cn:3306/mallink?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false&useAffectedRows=true + username: ENC(NUzgQOdJnCbVLKT6BaX0aw==) + password: ENC(mvuoDRiu0jqYaKNRwwTuXZ6U7aoIaqsjdiPqTLgi/nY=) + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + filters: stat + maxActive: 20 + initialSize: 1 + maxWait: 60000 + minIdle: 1 + timeBetweenEvictionRunsMillis: 28000 + minEvictableIdleTimeMillis: 28000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + connectionProperties: "druid.stat.mergeSql=true;druid.stat.slowSqlMillis=6000" + # REDIS + redis: + host: 127.0.0.1 + port: 6379 + password: ENC(8gYU47Fu93NUJPhwPCiPbAT+6VFA1YDx1egK4Z0Nl6w=) + timeout: 3600 + expire: 1800 #30分钟 + database: 1 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 20 + max-wait: -1 + min-idle: 0 + # EMAIL + mail: + host: smtp.exmail.qq.com + username: ENC(IiL/PHP9wCkpibWHRH/Mts8K9fh4izYqaiaF66bDrqtEHP+KUcJRRg==) + password: ENC(m7L57m8mk6tApVoa4XIDQnXF0VxnYjKe4LVdzcgb+xY=) # 授权密码 + properties: + mail: + smtp: + auth: true + starttls: + enable: true + socketFactory: + port: 465 + class: javax.net.ssl.SSLSocketFactory + # RABBITMQ + rabbitmq: + host: localhost + port: 5672 + username: ENC(lRmLd6EzgeY1RT5ktcHv9g==) + password: ENC(gBI8mCjr3OC0v57jcnSb660Ux7mW03K2oePgvohhg7w=) + publisher-confirms: true + virtual-host: / + +aws: + clientRegion: cn-northwest-1 + bucketName: iformall-net + access: ENC(a6SN1sZ1enNL49ypiOXkg/pPPAnZD8H4buQFTTKN08s=) + secret: ENC(5P5ff4bTMJUbXVR4ZsM03UHzOKZ4+Zg5Iutcdkyp/Quny/oXg+A4KpfwEyGarlLu3vQMJahGP5M=) + +wechat: + web: + appId: "wx9cc4ca09eb20fe03" + secret: "af1d7f7a1268022a73cb4ce0b9cf0985" + url: "https://admin.malls.iformall.com" + open: + componentAppId: ENC(b3JG0MUZgQfz5Zj+DC2ZM1zDeLOiGTmmeokfe2O8kaM=) + componentSecret: ENC(QVyc4BPGdnSjXGs2ivgpDBE1v8wPWHLLRMYI7Vv8uYwC0SiZHQz0QpyyQV/b48Pb) + componentToken: ENC(rkxj0733WxFFDLgA9x01m2s5Fi2L+0PC) + componentAesKey: ENC(EIbJUBpbYOrLb4YQ/HXLQmxlxgAqIp2ZmpnGICC8pu5xiTz3Cqfkbwd2S8raCcK/IvYcX2GmedI=) + redis: + host: 127.0.0.1 + port: 6379 + password: ENC(8gYU47Fu93NUJPhwPCiPbAT+6VFA1YDx1egK4Z0Nl6w=) + timeout: 3600 + expire: 1800 #30分钟 + database: 2 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 100 + max-wait: -1 + min-idle: 10 + +fm: + exception: true + exception_emails: hupeng@iformall.com,wuguoqiang@iformall.com,gongbiao@iformall.com,luozukai@iformall.com,hanxueda@iformall.com + deploy: 3 + open: true + +logging: + level: + tk.mybatis: debug + com.iformall.mapper: debug + path: ./logs/admin \ No newline at end of file diff --git a/mallinkCallback/src/main/resources/application-test.yml b/mallinkCallback/src/main/resources/application-test.yml new file mode 100644 index 000000000..e69fc6b72 --- /dev/null +++ b/mallinkCallback/src/main/resources/application-test.yml @@ -0,0 +1,104 @@ +spring: + profiles: + include: rabbitMQ + # JDBC + datasource: + url: jdbc:mysql://formalldb.cfqyqflkdlit.rds.cn-northwest-1.amazonaws.com.cn:3306/mallinkTest?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false&useAffectedRows=true + username: ENC(Uc0AjgkytxHHCwZrmDASWg==) + password: ENC(nV4Mi3bEbBx0Fj7uUyYH55eTaqsFMjKvmNzagicH4pc=) + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + filters: stat + maxActive: 20 + initialSize: 1 + maxWait: 60000 + minIdle: 1 + timeBetweenEvictionRunsMillis: 28000 + minEvictableIdleTimeMillis: 28000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + connectionProperties: "druid.stat.mergeSql=true;druid.stat.slowSqlMillis=6000" + # REDIS + redis: + host: 127.0.0.1 + port: 6379 + password: ENC(QFwqv3NshvvGhFPiP8rwhvbnxk+rFSqhJi8Pw6TogSg=) + timeout: 3600 + expire: 1800 #30分钟 + database: 1 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 20 + max-wait: -1 + min-idle: 0 + # EMAIL + mail: + host: smtp.exmail.qq.com + username: ENC(TtJQE2C4cWo8CpVGMMl5hiy5eykepd96J5XjsW3Kj5fgP+6+5ctDNQ==) + password: ENC(Zh6A6kRtA2ABtH6nzdvsqQSO1/8p3mparJr8neI2BLU=) # 授权密码 + properties: + mail: + smtp: + auth: true + starttls: + enable: true + socketFactory: + port: 465 + class: javax.net.ssl.SSLSocketFactory + # RABBITMQ + rabbitmq: + host: 127.0.0.1 + port: 5672 + username: ENC(aSRr6mnSryEqzHHz1hJf1g==) + password: ENC(GnjF/mdqKdvmDYC0tIIso7+20/jBALPw39tiWCYJ4iw=) + publisher-confirms: true + virtual-host: / + +aws: + clientRegion: cn-northwest-1 + bucketName: iformall-net + access: ENC(NCLcmjwKpAWdn/abD17OKIY7yKepVLWzEpqRYUlURCw=) + secret: ENC(TRcZqql0Rq5PExlMeH/4WiZ/i02b8FXKmLTBChJmbluTa1uoLS9LrHyNEMrqe1DK+QgOAdvqGBo=) + +wechat: + web: + appId: "wx091907dd0bfd3f6b" + secret: "2a2ca10738998b9ef92c1fe8a4d366a6" + url: "https://admintest.malls.iformall.com" + open: + componentAppId: ENC(hnH31XdNzArfMfikKgBFpqQuJUl6rVOPFFcAVyb595o=) + componentSecret: ENC(t/GUVX5L+U7LCwSvZ5WmxAnmTMrc/Uy1nljsrokuzzsBL2j6BEVnrS/n7DCdGc/G) + componentToken: ENC(gUF1m0YgCCI2IY54fX6sGLZVlCswA8tG) + componentAesKey: ENC(TYHcrIkICtfrCfGq4HW6s1b/pHf7OD2uyPN11SzJNB0acqJ/4JVX1nuljo/cAtgMG4O05TImLQc=) + redis: + host: 127.0.0.1 + port: 6379 + password: ENC(QFwqv3NshvvGhFPiP8rwhvbnxk+rFSqhJi8Pw6TogSg=) + timeout: 3600 + expire: 1800 #30分钟 + database: 2 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 100 + max-wait: -1 + min-idle: 10 + +fm: + exception: true + exception_emails: hupeng@iformall.com,wuguoqiang@iformall.com,gongbiao@iformall.com,luozukai@iformall.com,hanxueda@iformall.com + deploy: 2 + open: true + +logging: + level: + tk.mybatis: debug + com.iformall: debug + path: ./logs/admin \ No newline at end of file diff --git a/mallinkCallback/src/main/resources/application.yml b/mallinkCallback/src/main/resources/application.yml new file mode 100644 index 000000000..08ae707ba --- /dev/null +++ b/mallinkCallback/src/main/resources/application.yml @@ -0,0 +1,73 @@ +server: + port: 9100 + servlet: + context-path: / + +spring: + application: + name: mallink + profiles: + active: dev + jackson: + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + default-property-inclusion: non_null + servlet: + multipart: + max-file-size: 2MB + max-request-size: 2MB + cache: + type: REDIS + cache-names: redis_cache #缓存的名字(可以不指定) + redis: + time-to-live: 60000ms #很重要,缓存的有效时间,以便缓存的过期(单位为毫秒) + rocketmq: + nameServer: 202.165.179.86:9876 + producer: + retry-times-when-send-async-failed: 0 + send-msg-timeout: 300000 + compress-msg-body-over-howmuch: 4096 + max-message-size: 4194304 + retry-another-broker-when-not-store-ok: false + retry-times-when-send-failed: 2 + rabbitmq: + host: 202.165.179.86 + port: 5672 + username: guest + password: guest + publisher-confirms: true + virtual-host: / + aop: + proxy-target-class: true + auto: true + + +# @{link} https://github.com/abel533 +#Mybatis +mybatis: + type-aliases-package: com.iformall.domain.po + mapper-locations: classpath:mapper/*Mapper.xml + configuration: + map-underscore-to-camel-case: true + cache-enabled: true + lazy-loading-enabled: true + use-generated-keys: true + default-fetch-size: 100 + default-statement-timeout: 10 + + +#PageHelper +pagehelper: + helperDialect: mysql + reasonable: false + supportMethodsArguments: true + params: count=countSql + offset-as-page-num: true + page-size-zero: true + row-bounds-with-count: true + +mapper: + mappers: + - com.iformall.common.CommonMapper + +version: @project.version@ diff --git a/mallinkCallback/src/main/resources/logback-spring.xml b/mallinkCallback/src/main/resources/logback-spring.xml new file mode 100644 index 000000000..2525413f1 --- /dev/null +++ b/mallinkCallback/src/main/resources/logback-spring.xml @@ -0,0 +1,100 @@ + + + + + + + + [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] --%mdc{client}%msg%n + + + + + ${logPath}/trace.log + + ${logPath}/daily/trace.%d{yyyy-MM-dd}.log + 180 + + + [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n + + + + + ${logPath}/info.log + + ${logPath}/daily/info.%d{yyyy-MM-dd}.log + 180 + + + [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n + + + INFO + ACCEPT + DENY + + + + + ${logPath}/debug.log + + ${logPath}/daily/debug.%d{yyyy-MM-dd}.log + 180 + + + [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n + + + DEBUG + ACCEPT + DENY + + + + + + ${logPath}/warn.log + + ${logPath}/daily/warn.%d{yyyy-MM-dd}.log + 180 + + + [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n + + + WARN + ACCEPT + DENY + + + + + + + ${logPath}/error.log + + ${logPath}/daily/error.%d{yyyy-MM-dd}.log + 180 + + + [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n + + + ERROR + ACCEPT + DENY + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 5a91c9ee8..1b82c52bc 100644 --- a/pom.xml +++ b/pom.xml @@ -13,6 +13,7 @@ mybatis-multi-tenancy mallinkService + mallinkCallback mallinkAdmin mallinkCApi mallinkBApi