Browse Source

[callback分离][新增]

release_toaliyun_real
Stormeye Wu 7 years ago
parent
commit
d726fa6a80
41 changed files with 2518 additions and 113 deletions
  1. +1
    -30
      mallinkAdmin/src/main/java/com/iformall/controller/msg/WxMsgCallbackController.java
  2. +0
    -81
      mallinkAdmin/src/main/java/com/iformall/controller/official/WxMallApplyController.java
  3. +162
    -0
      mallinkCallback/pom.xml
  4. +52
    -0
      mallinkCallback/src/main/java/com/iformall/CallbackApplication.java
  5. +10
    -0
      mallinkCallback/src/main/java/com/iformall/annotation/SystemControllerLog.java
  6. +10
    -0
      mallinkCallback/src/main/java/com/iformall/annotation/SystemServiceLog.java
  7. +52
    -0
      mallinkCallback/src/main/java/com/iformall/config/AwsProperty.java
  8. +26
    -0
      mallinkCallback/src/main/java/com/iformall/config/MyExecutorConfig.java
  9. +145
    -0
      mallinkCallback/src/main/java/com/iformall/config/RedisConfig.java
  10. +58
    -0
      mallinkCallback/src/main/java/com/iformall/config/RestFilter.java
  11. +24
    -0
      mallinkCallback/src/main/java/com/iformall/config/RestTemplateConfig.java
  12. +307
    -0
      mallinkCallback/src/main/java/com/iformall/config/ShiroConfig.java
  13. +31
    -0
      mallinkCallback/src/main/java/com/iformall/config/ShiroLoginFilter.java
  14. +131
    -0
      mallinkCallback/src/main/java/com/iformall/config/WebConfig.java
  15. +33
    -0
      mallinkCallback/src/main/java/com/iformall/config/WechatMpConfig.java
  16. +59
    -0
      mallinkCallback/src/main/java/com/iformall/config/WechatWebProperties.java
  17. +46
    -0
      mallinkCallback/src/main/java/com/iformall/controller/base/BaseController.java
  18. +0
    -0
      mallinkCallback/src/main/java/com/iformall/controller/callback/WxCarCallBackController.java
  19. +48
    -0
      mallinkCallback/src/main/java/com/iformall/controller/callback/WxMsgCallbackController.java
  20. +0
    -0
      mallinkCallback/src/main/java/com/iformall/controller/callback/WxPayBillController.java
  21. +4
    -2
      mallinkCallback/src/main/java/com/iformall/controller/callback/WxPayController.java
  22. +0
    -0
      mallinkCallback/src/main/java/com/iformall/controller/device/WxDeviceScreenAdController.java
  23. +36
    -0
      mallinkCallback/src/main/java/com/iformall/controller/official/WxMallApplyController.java
  24. +76
    -0
      mallinkCallback/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java
  25. +72
    -0
      mallinkCallback/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java
  26. +117
    -0
      mallinkCallback/src/main/java/com/iformall/interceptor/RequestInterceptor.java
  27. +125
    -0
      mallinkCallback/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java
  28. +45
    -0
      mallinkCallback/src/main/java/com/iformall/shiro/MyRetryLimitCredentialsMatcher.java
  29. +79
    -0
      mallinkCallback/src/main/java/com/iformall/shiro/MyShiroRealm.java
  30. +32
    -0
      mallinkCallback/src/main/java/com/iformall/shiro/PasswordHelper.java
  31. +126
    -0
      mallinkCallback/src/main/java/com/iformall/shiro/ShiroService.java
  32. +11
    -0
      mallinkCallback/src/main/java/com/iformall/shiro/UserSession.java
  33. +39
    -0
      mallinkCallback/src/main/java/com/iformall/shiro/UseriFormallToken.java
  34. +37
    -0
      mallinkCallback/src/main/java/com/iformall/utils/PayUtil.java
  35. +22
    -0
      mallinkCallback/src/main/java/com/iformall/utils/UrlCheck.java
  36. +120
    -0
      mallinkCallback/src/main/resources/application-dev.yml
  37. +104
    -0
      mallinkCallback/src/main/resources/application-prod.yml
  38. +104
    -0
      mallinkCallback/src/main/resources/application-test.yml
  39. +73
    -0
      mallinkCallback/src/main/resources/application.yml
  40. +100
    -0
      mallinkCallback/src/main/resources/logback-spring.xml
  41. +1
    -0
      pom.xml

+ 1
- 30
mallinkAdmin/src/main/java/com/iformall/controller/msg/WxMsgCallbackController.java View File

@@ -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<String, String> 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<String, String> 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<String, String> param) {
logger.debug("[" + getIpAddr() + "] WxMsgCallbackController::receiveverifymodel");
logger.info(param.toString());
//解析param数据插入数据库中
wxMsgCallbackService.receiveverifymodel(tenantId, param);

}

}

+ 0
- 81
mallinkAdmin/src/main/java/com/iformall/controller/official/WxMallApplyController.java View File

@@ -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<WxMallApply> 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);
}


}

+ 162
- 0
mallinkCallback/pom.xml View File

@@ -0,0 +1,162 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<artifactId>mallink</artifactId>
<groupId>com.iformall</groupId>
<version>1.0</version>
</parent>

<artifactId>mallinkCallback</artifactId>

<properties>
<weixin-java-mp.version>3.3.0</weixin-java-mp.version>
<weixin-java-open.version>3.3.0</weixin-java-open.version>
</properties>

<dependencies>
<dependency>
<groupId>com.iformall</groupId>
<artifactId>mallinkService</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.iformall</groupId>
<artifactId>mybatis-multi-tenancy</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>

<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.3</version>
</dependency>

<dependency>
<groupId>com.github.axet</groupId>
<artifactId>kaptcha</artifactId>
<version>0.0.9</version>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
<layout>ZIP</layout>
<excludeGroupIds>
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
</excludeGroupIds>
</configuration>
</plugin>
</plugins>
</build>

</project>

+ 52
- 0
mallinkCallback/src/main/java/com/iformall/CallbackApplication.java View File

@@ -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);
}
}

+ 10
- 0
mallinkCallback/src/main/java/com/iformall/annotation/SystemControllerLog.java View File

@@ -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 "";
}

+ 10
- 0
mallinkCallback/src/main/java/com/iformall/annotation/SystemServiceLog.java View File

@@ -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 "";
}

+ 52
- 0
mallinkCallback/src/main/java/com/iformall/config/AwsProperty.java View File

@@ -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;
}
}

+ 26
- 0
mallinkCallback/src/main/java/com/iformall/config/MyExecutorConfig.java View File

@@ -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;
}
}


+ 145
- 0
mallinkCallback/src/main/java/com/iformall/config/RedisConfig.java View File

@@ -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<String, RedisCacheConfiguration> 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<Object> 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<String> cacheNames = new HashSet<>();
cacheNames.add("my-redis-cache1");
cacheNames.add("my-redis-cache2");

// 对每个缓存空间应用不同的配置
Map<String, RedisCacheConfiguration> 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<String, PushLimit> getPushLimitRedisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, PushLimit> template = new RedisTemplate<String, PushLimit>();

Jackson2JsonRedisSerializer<PushLimit> j = new Jackson2JsonRedisSerializer<PushLimit>(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<String, WxScoreRules> getScoreRuleRedisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, WxScoreRules> template = new RedisTemplate<String, WxScoreRules>();

Jackson2JsonRedisSerializer<WxScoreRules> j = new Jackson2JsonRedisSerializer<WxScoreRules>(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<String, String> getWeChatOpen(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, String> template = new RedisTemplate<String, String>();

// value值的序列化
template.setValueSerializer(new StringRedisSerializer());

// key的序列化
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());

template.setConnectionFactory(connectionFactory);
return template;
}

@Bean("cuserTokenRedisTemplate")
public RedisTemplate<String, WxCUser> getCUserTokenRedisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, WxCUser> template = new RedisTemplate<String, WxCUser>();

Jackson2JsonRedisSerializer<WxCUser> j = new Jackson2JsonRedisSerializer<WxCUser>(WxCUser.class);
// value值的序列化
template.setValueSerializer(j);
template.setHashKeySerializer(j);

// key的序列化
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());

template.setConnectionFactory(connectionFactory);
return template;
}

}

+ 58
- 0
mallinkCallback/src/main/java/com/iformall/config/RestFilter.java View File

@@ -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() {
}
}

+ 24
- 0
mallinkCallback/src/main/java/com/iformall/config/RestTemplateConfig.java View File

@@ -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;
}
}

+ 307
- 0
mallinkCallback/src/main/java/com/iformall/config/ShiroConfig.java View File

@@ -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
* <p>
* 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<String, Filter> filters = new LinkedHashMap<String, Filter>();
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<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
// 官网
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");

//<!-- 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
//<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
//自定义加载权限资源关系
// Map<String,Object> map = new HashMap<>();
// List<SysPermission> 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");
// //<!-- 记住我cookie生效时间30天 ,单位秒;-->
// 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;
// }

}

+ 31
- 0
mallinkCallback/src/main/java/com/iformall/config/ShiroLoginFilter.java View File

@@ -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()) ) ;
}
}

+ 131
- 0
mallinkCallback/src/main/java/com/iformall/config/WebConfig.java View File

@@ -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<HttpMessageConverter<?>> 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<HttpServletRequestWrapperFilter> Filters() {
FilterRegistrationBean<HttpServletRequestWrapperFilter> registrationBean = new FilterRegistrationBean<HttpServletRequestWrapperFilter>();
registrationBean.setFilter(new HttpServletRequestWrapperFilter());
registrationBean.addUrlPatterns("/*");
registrationBean.setName("koalaSignFilter");
return registrationBean;
}
}

+ 33
- 0
mallinkCallback/src/main/java/com/iformall/config/WechatMpConfig.java View File

@@ -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;
}
}

+ 59
- 0
mallinkCallback/src/main/java/com/iformall/config/WechatWebProperties.java View File

@@ -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);
}
}

+ 46
- 0
mallinkCallback/src/main/java/com/iformall/controller/base/BaseController.java View File

@@ -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;
}
}

mallinkAdmin/src/main/java/com/iformall/controller/callback/WxCarCallBackController.java → mallinkCallback/src/main/java/com/iformall/controller/callback/WxCarCallBackController.java View File


+ 48
- 0
mallinkCallback/src/main/java/com/iformall/controller/callback/WxMsgCallbackController.java View File

@@ -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<String, String> 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<String, String> 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<String, String> param) {
logger.debug("[" + getIpAddr() + "] WxMsgCallbackController::receiveverifymodel");
logger.info(param.toString());
//解析param数据插入数据库中
wxMsgCallbackService.receiveverifymodel(tenantId, param);

}

}

mallinkAdmin/src/main/java/com/iformall/controller/callback/WxPayBillController.java → mallinkCallback/src/main/java/com/iformall/controller/callback/WxPayBillController.java View File


mallinkAdmin/src/main/java/com/iformall/controller/callback/WxPayController.java → mallinkCallback/src/main/java/com/iformall/controller/callback/WxPayController.java View File

@@ -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;

mallinkAdmin/src/main/java/com/iformall/controller/device/WxDeviceScreenAdController.java → mallinkCallback/src/main/java/com/iformall/controller/device/WxDeviceScreenAdController.java View File


+ 36
- 0
mallinkCallback/src/main/java/com/iformall/controller/official/WxMallApplyController.java View File

@@ -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);
}


}

+ 76
- 0
mallinkCallback/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java View File

@@ -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;
}
}

+ 72
- 0
mallinkCallback/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java View File

@@ -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() {

}
}

+ 117
- 0
mallinkCallback/src/main/java/com/iformall/interceptor/RequestInterceptor.java View File

@@ -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<String, String> 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.<Boolean>execute(new RedisCallback<Boolean>() {
@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 {

}
}

+ 125
- 0
mallinkCallback/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java View File

@@ -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<String> notAllowedKeyWords = new HashSet<String>(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<String, String[]> getParameterMap(){
Map<String, String[]> values=super.getParameterMap();
if (values == null) {
return null;
}
Map<String, String[]> 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("<", "&lt;").replaceAll(">", "&gt;");
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;
}

}

+ 45
- 0
mallinkCallback/src/main/java/com/iformall/shiro/MyRetryLimitCredentialsMatcher.java View File

@@ -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;
}
}

+ 79
- 0
mallinkCallback/src/main/java/com/iformall/shiro/MyShiroRealm.java View File

@@ -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<String> 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);
}
*/
}

+ 32
- 0
mallinkCallback/src/main/java/com/iformall/shiro/PasswordHelper.java View File

@@ -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());
}
}

+ 126
- 0
mallinkCallback/src/main/java/com/iformall/shiro/ShiroService.java View File

@@ -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<String, String> loadFilterChainDefinitions() {
// 权限控制map.从数据库获取
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
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<String,Object> map = new HashMap<>();
// List<SysPermission> 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<String, String> chains = shiroFilterFactoryBean
.getFilterChainDefinitionMap();
for (Map.Entry<String, String> 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<Integer> userIds){
if(null == userIds || userIds.size() == 0) return ;
//获取所有session
Collection<Session> sessions = redisSessionDAO.getActiveSessions();
//定义返回
List<SimplePrincipalCollection> list = new ArrayList<SimplePrincipalCollection>();
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);
}
}*/
}

+ 11
- 0
mallinkCallback/src/main/java/com/iformall/shiro/UserSession.java View File

@@ -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";

}

+ 39
- 0
mallinkCallback/src/main/java/com/iformall/shiro/UseriFormallToken.java View File

@@ -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;
}
}

+ 37
- 0
mallinkCallback/src/main/java/com/iformall/utils/PayUtil.java View File

@@ -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<EncodeHintType, Object> 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;
}
}

+ 22
- 0
mallinkCallback/src/main/java/com/iformall/utils/UrlCheck.java View File

@@ -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");
}

}

+ 120
- 0
mallinkCallback/src/main/resources/application-dev.yml View File

@@ -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

+ 104
- 0
mallinkCallback/src/main/resources/application-prod.yml View File

@@ -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

+ 104
- 0
mallinkCallback/src/main/resources/application-test.yml View File

@@ -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

+ 73
- 0
mallinkCallback/src/main/resources/application.yml View File

@@ -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@

+ 100
- 0
mallinkCallback/src/main/resources/logback-spring.xml View File

@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="10 seconds">
<!-- 外部指定路径 -->
<springProperty scop="context" name="logPath" source="logging.path" />

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>[%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] --%mdc{client}%msg%n</Pattern>
</encoder>
</appender>

<appender name="TRACE_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${logPath}/trace.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${logPath}/daily/trace.%d{yyyy-MM-dd}.log</FileNamePattern>
<maxHistory>180</maxHistory> <!-- 保留180天 -->
</rollingPolicy>
<layout>
<pattern>[%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n</pattern>
</layout>
</appender>

<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${logPath}/info.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${logPath}/daily/info.%d{yyyy-MM-dd}.log</FileNamePattern>
<maxHistory>180</maxHistory> <!-- 保留180天 -->
</rollingPolicy>
<layout>
<pattern>[%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n</pattern>
</layout>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${logPath}/debug.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${logPath}/daily/debug.%d{yyyy-MM-dd}.log</FileNamePattern>
<maxHistory>180</maxHistory> <!-- 保留180天 -->
</rollingPolicy>
<layout>
<pattern>[%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n</pattern>
</layout>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>


<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${logPath}/warn.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${logPath}/daily/warn.%d{yyyy-MM-dd}.log</FileNamePattern>
<maxHistory>180</maxHistory> <!-- 保留180天 -->
</rollingPolicy>
<layout>
<pattern>[%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n</pattern>
</layout>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>WARN</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>



<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${logPath}/error.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${logPath}/daily/error.%d{yyyy-MM-dd}.log</FileNamePattern>
<maxHistory>180</maxHistory> <!-- 保留180天 -->
</rollingPolicy>
<layout>
<pattern>[%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n</pattern>
</layout>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<root level="TRACE">
<appender-ref ref="TRACE_FILE" />
<appender-ref ref="INFO_FILE" />
<!-- <appender-ref ref="DEBUG_FILE" /> -->
<!-- <appender-ref ref="WARN_FILE" /> -->
<appender-ref ref="ERROR_FILE" />
</root>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>

+ 1
- 0
pom.xml View File

@@ -13,6 +13,7 @@
<modules>
<module>mybatis-multi-tenancy</module>
<module>mallinkService</module>
<module>mallinkCallback</module>
<module>mallinkAdmin</module>
<module>mallinkCApi</module>
<module>mallinkBApi</module>


Loading…
Cancel
Save