Commit b182ecef authored by eddie.woo's avatar eddie.woo

merge

parents 244ad198 51c6f913
...@@ -11,3 +11,4 @@ rebel.xml ...@@ -11,3 +11,4 @@ rebel.xml
**/*.iml **/*.iml
**/.idea/ **/.idea/
atms-api/~ atms-api/~
/bin/
jdbc.driverClass=com.mysql.jdbc.Driver jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.connectionURL=jdbc:mysql://10.157.107.89:3306/tax_admin?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true jdbc.connectionURL=jdbc:mysql://10.157.107.89:3306/tax_longi?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
jdbc.userId=root jdbc.userId=root
jdbc.password=tax@Admin2018 jdbc.password=tax@Admin2018
...@@ -2,4 +2,4 @@ rem see http://www.mybatis.org/generator/running/runningFromCmdLine.html ...@@ -2,4 +2,4 @@ rem see http://www.mybatis.org/generator/running/runningFromCmdLine.html
cd /d %~dp0 cd /d %~dp0
call java -classpath .;./* org.mybatis.generator.api.ShellRunner -configfile vatGeneratorConfig.xml -overwrite -verbose -tables data_source call java -classpath .;./* org.mybatis.generator.api.ShellRunner -configfile vatGeneratorConfig.xml -overwrite -verbose -tables data_source
echo @@@@@@@@@@@ DONE @@@@@@@@@@@ echo @@@@@@@@@@@ DONE @@@@@@@@@@@
pause pause
\ No newline at end of file
...@@ -188,7 +188,7 @@ ...@@ -188,7 +188,7 @@
<dependency> <dependency>
<groupId>commons-codec</groupId> <groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId> <artifactId>commons-codec</artifactId>
<version>1.10</version> <version>1.11</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
...@@ -230,7 +230,7 @@ ...@@ -230,7 +230,7 @@
<dependency> <dependency>
<groupId>commons-collections</groupId> <groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId> <artifactId>commons-collections</artifactId>
<version>3.2.1</version> <version>3.2.2</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>commons-beanutils</groupId> <groupId>commons-beanutils</groupId>
...@@ -316,6 +316,30 @@ ...@@ -316,6 +316,30 @@
<artifactId>guava</artifactId> <artifactId>guava</artifactId>
<version>24.0-jre</version> <version>24.0-jre</version>
</dependency> </dependency>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.4</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.5</version>
</dependency>
<!-- reflectasm -->
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>reflectasm</artifactId>
<version>1.11.7</version>
</dependency>
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
...@@ -328,15 +352,15 @@ ...@@ -328,15 +352,15 @@
<version>4.5.5</version> <version>4.5.5</version>
</dependency> </dependency>
<!--<dependency>--> <!--<dependency>-->
<!--<groupId>org.eclipse.jetty.aggregate</groupId>--> <!--<groupId>org.eclipse.jetty.aggregate</groupId>-->
<!--<artifactId>jetty-all</artifactId>--> <!--<artifactId>jetty-all</artifactId>-->
<!--<version>9.4.10.v20180503</version>--> <!--<version>9.4.10.v20180503</version>-->
<!--<type>pom</type>--> <!--<type>pom</type>-->
<!--</dependency>--> <!--</dependency>-->
<!--<dependency>--> <!--<dependency>-->
<!--<groupId>org.eclipse.jetty</groupId>--> <!--<groupId>org.eclipse.jetty</groupId>-->
<!--<artifactId>apache-jsp</artifactId>--> <!--<artifactId>apache-jsp</artifactId>-->
<!--<version>9.4.10.v20180503</version>--> <!--<version>9.4.10.v20180503</version>-->
<!--</dependency>--> <!--</dependency>-->
</dependencies> </dependencies>
......
package pwc.taxtech.atms; package pwc.taxtech.atms;
import pwc.taxtech.atms.dto.user.UserDto; import pwc.taxtech.atms.dto.user.UserDto;
import pwc.taxtech.atms.service.OperationLogService; import pwc.taxtech.atms.service.OperationLogService;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
public class AppCachePool { public class AppCachePool {
private static Map<String, UserDto> CACHED_USERS = null; private static Map<String, UserDto> CACHED_USERS = null;
private static Object _locker = new Object(); private static Object _locker = new Object();
static { static {
CACHED_USERS = new HashMap<>(); CACHED_USERS = new HashMap<>();
} }
public static UserDto getCachedUser(String name) { public static UserDto getCachedUser(String name) {
String userName = name.toLowerCase(); String userName = name.toLowerCase();
synchronized (_locker) { synchronized (_locker) {
if (!CACHED_USERS.containsKey(userName)) { if (!CACHED_USERS.containsKey(userName)) {
UserDto dto = new UserDto();//TODO:should fixed to load from db (neo) UserDto dto = new UserDto();//TODO:should fixed to load from db (neo)
dto.setUserName("cach_test"); dto.setUserName("cach_test");
dto.setID("1"); dto.setID("1");
CACHED_USERS.put(userName,dto); CACHED_USERS.put(userName,dto);
} }
return CACHED_USERS.get(userName); return CACHED_USERS.get(userName);
} }
} }
} }
...@@ -25,7 +25,7 @@ public class SwaggerConfig { ...@@ -25,7 +25,7 @@ public class SwaggerConfig {
@Bean @Bean
public Docket petApi() { public Docket petApi() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select() return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()
.apis(RequestHandlerSelectors.basePackage("pwc.taxtech.atms.controller")) .apis(RequestHandlerSelectors.basePackage("pwc.taxtech.atms.controller.*"))
.paths(PathSelectors.regex("/api/.*")).build() .paths(PathSelectors.regex("/api/.*")).build()
.globalOperationParameters(buildGlobalOperationParameters()); .globalOperationParameters(buildGlobalOperationParameters());
......
...@@ -8,8 +8,11 @@ import org.springframework.beans.factory.InitializingBean; ...@@ -8,8 +8,11 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource; import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.commons.CommonsMultipartResolver; import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.MapperFeature;
...@@ -80,4 +83,17 @@ public class WebMvcConfig implements InitializingBean { ...@@ -80,4 +83,17 @@ public class WebMvcConfig implements InitializingBean {
return new CommonsMultipartResolver(); return new CommonsMultipartResolver();
} }
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
return new RestTemplate(factory);
}
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setReadTimeout(5000);//单位为ms
factory.setConnectTimeout(5000);//单位为ms
return factory;
}
} }
package pwc.taxtech.atms.common;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class AopLogger {
private static Logger logger = LoggerFactory.getLogger(AopLogger.class);
@Pointcut("execution(public * pwc.taxtech.atms.service.*.*(..))")
public void pointCut() {
// 定义Pointcut 此方法不能有返回值,该方法只是一个标示
}
@Before("pointCut()")
public void before(JoinPoint joinPoint) {
if (logger.isDebugEnabled()) {
logger.debug("aop before:{}", joinPoint);
}
}
@After("pointCut()")
public void after(JoinPoint joinPoint) {
if (logger.isDebugEnabled()) {
logger.debug("aop after:{}", joinPoint);
}
}
@AfterThrowing(pointcut = "pointCut()", throwing = "error")
public void afterThrowing(JoinPoint joinPoint, Throwable error) {
if (logger.isWarnEnabled()) {
logger.warn("aop afterThrowing:{}, exception class:{}, exception message:{} ", joinPoint,
error.getClass().toString(), error.getMessage());
}
}
// @After("pointCut()")
// public void doAfter(JoinPoint joinPoint) {
// System.out.println("AOP After Advice...");
// }
//
// @AfterReturning(pointcut = "pointCut()", returning = "returnVal")
// public void afterReturn(JoinPoint joinPoint, Object returnVal) {
// System.out.println("AOP AfterReturning Advice:" + returnVal);
// }
//
//
// @Around("pointCut()")
// public void around(ProceedingJoinPoint pjp) {
// System.out.println("AOP Aronud before...");
// try {
// pjp.proceed();
// } catch (Throwable e) {
// e.printStackTrace();
// }
// System.out.println("AOP Aronud after...");
// }
}
\ No newline at end of file
...@@ -17,7 +17,7 @@ import org.springframework.util.StringUtils; ...@@ -17,7 +17,7 @@ import org.springframework.util.StringUtils;
import pwc.taxtech.atms.dao.UserMapper; import pwc.taxtech.atms.dao.UserMapper;
import pwc.taxtech.atms.entitiy.User; import pwc.taxtech.atms.entitiy.User;
import pwc.taxtech.atms.exception.ApplicationException; import pwc.taxtech.atms.security.JwtUser;
@Component @Component
public class AuthUserHelperImpl implements AuditorAware<String>, AuthUserHelper { public class AuthUserHelperImpl implements AuditorAware<String>, AuthUserHelper {
...@@ -57,12 +57,19 @@ public class AuthUserHelperImpl implements AuditorAware<String>, AuthUserHelper ...@@ -57,12 +57,19 @@ public class AuthUserHelperImpl implements AuditorAware<String>, AuthUserHelper
*/ */
@Override @Override
public String getCurrentUserID() { public String getCurrentUserID() {
String userName = getCurrentAuditor(); SecurityContext context = SecurityContextHolder.getContext();
User user = userMapper.selectByUserNameIgnoreCase(userName); if (context == null) {
if (user == null) { throw new ApplicationException("security context is null");
}
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !authentication.isAuthenticated()) {
throw new ApplicationException("authentication failed");
}
JwtUser jwtUser = (JwtUser) authentication.getPrincipal();
if (jwtUser == null) {
return ""; return "";
} }
return user.getID(); return jwtUser.getUserid();
} }
/* /*
......
package pwc.taxtech.atms.common.exception;
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import pwc.taxtech.atms.common.ServiceException;
import pwc.taxtech.atms.dto.ApiResultDto;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@ControllerAdvice
public class CustomExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(CustomExceptionHandler.class);
@ExceptionHandler(value = Throwable.class)
public ApiResultDto handle(HttpServletResponse response) {
return ApiResultDto.fail("error.");
}
@ExceptionHandler(value = ServiceException.class)
public void customHandle(ServiceException exception, HttpServletResponse response) {
try {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=UTF-8");
response.getWriter().write(JSON.toJSONString(ApiResultDto.fail(exception.getMessage())));
} catch (IOException e) {
logger.error("customHandle error.", e);
}
}
}
package pwc.taxtech.atms.common.util;
import com.esotericsoftware.reflectasm.FieldAccess;
import com.esotericsoftware.reflectasm.MethodAccess;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
@Component
public class BeanUtil {
private static final String PREFIX_GET = "get";
private static final String PREFIX_SET = "set";
/**
* 拷贝属性
*
* @param sourceObject 数据源
* @param targetObject 目标对象
* @return T
*/
public <T> T copyProperties(Object sourceObject, T targetObject) {
if (sourceObject == null) {
throw new IllegalArgumentException("sourceObject is null");
}
if (targetObject == null) {
throw new IllegalArgumentException("targetObject is null");
}
MethodAccess targetMa = getMethodAccess(targetObject.getClass());
FieldAccess targetFa = getFieldAccess(targetObject.getClass());
Field[] targetFields = targetFa.getFields();
MethodAccess sourceMa = getMethodAccess(sourceObject.getClass());
FieldAccess sourceFa = getFieldAccess(sourceObject.getClass());
for (Field field : targetFields) {
String name = field.getName();
try {
sourceFa.getIndex(name);
} catch (Exception e) {
//不包含此属性 跳过
continue;
}
String upperName = upperCaseFirstChar(name);
targetMa.invoke(targetObject, PREFIX_SET + upperName,
sourceMa.invoke(sourceObject, PREFIX_GET + upperName));
}
return targetObject;
}
@Cacheable(value = "reflectCache", key = "'ma_' + #className.getName()")
public MethodAccess getMethodAccess(Class className) {
return MethodAccess.get(className);
}
@Cacheable(value = "reflectCache", key = "'fa_' + #className.getName()")
public FieldAccess getFieldAccess(Class className) {
return FieldAccess.get(className);
}
/**
* 首字母大写
*
* @param str str
* @return str
*/
public String upperCaseFirstChar(String str) {
char[] ch = str.toCharArray();
if (ch[0] >= 'a' && ch[0] <= 'z') {
ch[0] = (char) (ch[0] - 32);
}
return new String(ch);
}
}
package pwc.taxtech.atms.common.util;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.TreeMap;
public class SignatureUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(SignatureUtil.class);
public static final String SIGN_NONCE_STR = "nonceStr"; //随机数
public static final String SIGN_TIMESTAMP = "timestamp"; //时间戳
public static final String SIGN_APP_ID = "appId"; //应用ID
public static final String SIGN_SIGNATURE = "signature"; //生成的签名
public static final String SIGN_API = "api"; //接口地址
public static final String SIGN_API_TOKEN = "apiToken"; //密钥
public static final String AND = "=";
public static final String SPLIT = "&";
public static final int TIME_RANGE = 120;//2分钟
/**
* 生成签名
*
* @param key 密钥
* @param api 请求地址
* @param nonceStr 随机字符串
* @param timestamp 时间戳
* @return string
*/
public static String generate(String key, String api, String nonceStr, String timestamp) {
TreeMap<String, String> paramMap = new TreeMap<>();
paramMap.put(SIGN_API_TOKEN, key);
paramMap.put(SIGN_API, api);
paramMap.put(SIGN_NONCE_STR, nonceStr);
paramMap.put(SIGN_TIMESTAMP, timestamp);
StringBuilder sb = new StringBuilder();
paramMap.forEach((k, v) -> {
sb.append(k).append(AND).append(v).append(SPLIT);
});
String tmp = sb.substring(0, sb.length() - 1);
return DigestUtils.sha1Hex(tmp);
}
/**
* 校验签名
*
* @param key 密钥
* @param api 请求地址
* @param nonceStr 随机字符串
* @param timestamp 时间戳
* @param signature 接收的签名
* @return boolean
*/
public static boolean validate(String key, String api, String nonceStr, String timestamp, String signature) {
try {
if (StringUtils.isAnyBlank(key, api, nonceStr, timestamp, signature)) {
return false;
}
int now = (int) (System.currentTimeMillis() / 1000);
int time = Integer.valueOf(timestamp);
if (now - time <= TIME_RANGE) {
return StringUtils.equals(signature, generate(key, api, nonceStr, timestamp));
}
} catch (Exception e) {
LOGGER.error("invalid signature.", e);
}
return false;
}
}
package pwc.taxtech.atms.dto;
import org.apache.commons.lang3.StringUtils;
public class ApiResultDto {
private int code;
private Object data;
private String message;
public static final int SUCCESS = 0; //接口成功code
public static final int FAILED = -1; //通用失败code
/**
* 返回成功
*
* @param data data
* @return ApiResultDto
*/
public static ApiResultDto success(Object data) {
return new ApiResultDto(SUCCESS, data, StringUtils.EMPTY);
}
/**
* 返回成功
*
* @return ApiResultDto
*/
public static ApiResultDto success() {
return new ApiResultDto(SUCCESS, null, StringUtils.EMPTY);
}
/**
* 返回失败
*
* @param code fail code
* @param message msg
* @return ApiResultDto
*/
public static ApiResultDto fail(int code, String message) {
return new ApiResultDto(code, null, message);
}
/**
* 返回失败
*
* @param message msg
* @return ApiResultDto
*/
public static ApiResultDto fail(String message) {
return new ApiResultDto(FAILED, null, message);
}
public static ApiResultDto fail() {
return new ApiResultDto(FAILED, null, StringUtils.EMPTY);
}
public ApiResultDto() {
}
public ApiResultDto(int code, Object data, String message) {
this.code = code;
this.data = data;
this.message = message;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
package pwc.taxtech.atms.dto.input;
public class CamelPagingDto {
private Integer totalCount;
private Integer pageIndex;
private Integer pageSize;
public Integer getTotalCount() {
return totalCount;
}
public void setTotalCount(Integer totalCount) {
this.totalCount = totalCount;
}
public Integer getPageIndex() {
return pageIndex;
}
public void setPageIndex(Integer pageIndex) {
this.pageIndex = pageIndex;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
}
package pwc.taxtech.atms.dto.input;
import java.util.List;
import com.alibaba.fastjson.annotation.JSONField;
public class CamelPagingResultDto<T> {
@JSONField(name="List")
private List<T> list;
@JSONField(name="PageInfo")
private CamelPagingDto pageInfo;
private T calculateData;
public CamelPagingResultDto() {
super();
}
public List<T> getList() {
return list;
}
public void setList(List<T> list) {
this.list = list;
}
public CamelPagingDto getPageInfo() {
return pageInfo;
}
public void setPageInfo(CamelPagingDto pageInfo) {
this.pageInfo = pageInfo;
}
public T getCalculateData() {
return calculateData;
}
public void setCalculateData(T calculateData) {
this.calculateData = calculateData;
}
}
package pwc.taxtech.atms.entitiy;
import java.util.Date;
public class BaseEntity {
private String createBy;
private String updateBy;
private Date createTime;
private Date updateTime;
public BaseEntity() {
Date now = new Date();
this.createTime = now;
this.updateTime = now;
}
public String getCreateBy() {
return createBy;
}
public void setCreateBy(String createBy) {
this.createBy = createBy;
}
public String getUpdateBy() {
return updateBy;
}
public void setUpdateBy(String updateBy) {
this.updateBy = updateBy;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Date getUpdateTime() {
return updateTime == null ? new Date() : updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
}
package pwc.taxtech.atms.security; package pwc.taxtech.atms.security;
import java.io.IOException; import io.jsonwebtoken.impl.DefaultClaims;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.FilterChain; import org.springframework.beans.factory.annotation.Value;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFilter { public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
@Value("${jwt.expireSecond}")
private Integer jwtExpireSecond;
@Value("${jwt.refreshSecond}")
private Integer jwtRefreshSecond;
@Autowired
private JwtUtil jwtUtil;
public JwtAuthenticationFilter() { public JwtAuthenticationFilter() {
super("/**"); super("/**");
} }
...@@ -58,6 +69,27 @@ public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFil ...@@ -58,6 +69,27 @@ public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFil
// As this authentication is in HTTP header, after success we need to continue // As this authentication is in HTTP header, after success we need to continue
// the request normally // the request normally
// and return the response as if the resource was not secured at all // and return the response as if the resource was not secured at all
try {
JwtUser jwtUser = (JwtUser) authResult.getPrincipal();
if (null != jwtUser) {
DefaultClaims claims = jwtUser.getDefaultClaims();
if (claims.getExpiration().getTime() - System.currentTimeMillis() <= jwtRefreshSecond * 1000) {
String newToken = jwtUtil.generateToken(jwtUser.getUsername(), jwtUser.getDatabaseUsername(),
jwtUser.getUserid());
response.setHeader("Access-Control-Expose-Headers", "refreshToken");
response.setHeader("refreshToken", newToken);
logger.debug("refreshToken: " + newToken);
}
}
} catch (Exception e) {
logger.error("", e);
}
chain.doFilter(request, response); chain.doFilter(request, response);
} }
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
super.unsuccessfulAuthentication(request, response, failed);
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
} }
\ No newline at end of file
package pwc.taxtech.atms.security; package pwc.taxtech.atms.security;
import io.jsonwebtoken.ExpiredJwtException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
...@@ -31,7 +32,14 @@ public class JwtAuthenticationProvider extends AbstractUserDetailsAuthentication ...@@ -31,7 +32,14 @@ public class JwtAuthenticationProvider extends AbstractUserDetailsAuthentication
JwtAuthenticationToken jwtAuthenticationToken = (JwtAuthenticationToken) authentication; JwtAuthenticationToken jwtAuthenticationToken = (JwtAuthenticationToken) authentication;
String token = jwtAuthenticationToken.getToken(); String token = jwtAuthenticationToken.getToken();
JwtUser parsedUser = jwtUtil.parseToken(token); JwtUser parsedUser;
try {
parsedUser = jwtUtil.parseToken(token);
} catch (ExpiredJwtException e) {
throw new BadCredentialsException("Expired jwt token");
} catch (Exception e) {
throw new BadCredentialsException("Bad jwt token", e);
}
if (parsedUser == null) { if (parsedUser == null) {
throw new BadCredentialsException("JWT token is not valid"); throw new BadCredentialsException("JWT token is not valid");
......
...@@ -2,6 +2,7 @@ package pwc.taxtech.atms.security; ...@@ -2,6 +2,7 @@ package pwc.taxtech.atms.security;
import java.util.Collection; import java.util.Collection;
import io.jsonwebtoken.impl.DefaultClaims;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
...@@ -14,12 +15,15 @@ public class JwtUser implements UserDetails { ...@@ -14,12 +15,15 @@ public class JwtUser implements UserDetails {
private final String databaseUsername; private final String databaseUsername;
private final Collection<? extends GrantedAuthority> authorities; private final Collection<? extends GrantedAuthority> authorities;
private DefaultClaims defaultClaims;
public JwtUser(String userid, String username, String databaseUsername, public JwtUser(String userid, String username, String databaseUsername,
Collection<? extends GrantedAuthority> authorities) { DefaultClaims defaultClaims, Collection<? extends GrantedAuthority> authorities) {
this.userid = userid; this.userid = userid;
this.username = username; this.username = username;
this.databaseUsername = databaseUsername; this.databaseUsername = databaseUsername;
this.authorities = authorities; this.authorities = authorities;
this.defaultClaims = defaultClaims;
} }
@Override @Override
...@@ -65,4 +69,11 @@ public class JwtUser implements UserDetails { ...@@ -65,4 +69,11 @@ public class JwtUser implements UserDetails {
return databaseUsername; return databaseUsername;
} }
public DefaultClaims getDefaultClaims() {
return defaultClaims;
}
public void setDefaultClaims(DefaultClaims defaultClaims) {
this.defaultClaims = defaultClaims;
}
} }
...@@ -4,21 +4,18 @@ import java.util.ArrayList; ...@@ -4,21 +4,18 @@ import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import io.jsonwebtoken.*;
import org.nutz.lang.Times; import org.nutz.lang.Times;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.DefaultClaims; import io.jsonwebtoken.impl.DefaultClaims;
import io.jsonwebtoken.impl.DefaultJws; import io.jsonwebtoken.impl.DefaultJws;
import io.jsonwebtoken.lang.Assert; import io.jsonwebtoken.lang.Assert;
...@@ -31,6 +28,8 @@ public class JwtUtil implements InitializingBean { ...@@ -31,6 +28,8 @@ public class JwtUtil implements InitializingBean {
@Autowired @Autowired
private AtmsApiSettings atmsApiSettings; private AtmsApiSettings atmsApiSettings;
@Value("${jwt.expireSecond}")
private Integer jwtExpireSecond;
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
...@@ -51,24 +50,17 @@ public class JwtUtil implements InitializingBean { ...@@ -51,24 +50,17 @@ public class JwtUtil implements InitializingBean {
@SuppressWarnings({ "unchecked", "rawtypes" }) @SuppressWarnings({ "unchecked", "rawtypes" })
public JwtUser parseToken(String token) { public JwtUser parseToken(String token) {
if (StringUtils.hasText(jwtPowerToken) && jwtPowerToken.equals(token)) { if (StringUtils.hasText(jwtPowerToken) && jwtPowerToken.equals(token)) {
return new JwtUser("test_userid", "admin", "Admin", getAuthorities()); return new JwtUser("test_userid", "admin", "Admin", null, getAuthorities());
} }
JwtParser parser = Jwts.parser().setSigningKey(jwtBase64Secret); JwtParser parser = Jwts.parser().setSigningKey(jwtBase64Secret);
Jwt jwt = null; Jwt jwt = parser.parseClaimsJws(token);
DefaultJws<DefaultClaims> defaultJws = null; DefaultJws<DefaultClaims> defaultJws = (DefaultJws<DefaultClaims>) jwt;
try {
jwt = parser.parseClaimsJws(token);
defaultJws = (DefaultJws<DefaultClaims>) jwt;
} catch (Exception e) {
logger.warn("Bad jwt token", e);
throw new BadCredentialsException("invalid token:" + e.getMessage());
}
DefaultClaims defaultClaims = defaultJws.getBody(); DefaultClaims defaultClaims = defaultJws.getBody();
String databaseUsername = String.valueOf(defaultClaims.get("databaseUsername")); String databaseUsername = String.valueOf(defaultClaims.get("databaseUsername"));
String username = String.valueOf(defaultClaims.get("username")); String username = String.valueOf(defaultClaims.get("username"));
String userid = String.valueOf(defaultClaims.get("userid")); String userid = String.valueOf(defaultClaims.get("userid"));
return new JwtUser(userid, username, databaseUsername, getAuthorities()); return new JwtUser(userid, username, databaseUsername, defaultClaims, getAuthorities());
} }
private List<SimpleGrantedAuthority> getAuthorities() { private List<SimpleGrantedAuthority> getAuthorities() {
...@@ -81,7 +73,7 @@ public class JwtUtil implements InitializingBean { ...@@ -81,7 +73,7 @@ public class JwtUtil implements InitializingBean {
/*** /***
* @param username * @param username
* 登录名,大小写不限,可以是全大写或全小写,如:admin, ADMIN * 登录名,大小写不限,可以是全大写或全小写,如:admin, ADMIN
* @param loginname * @param databaseUsername
* 数据库用户名, 比如Admin * 数据库用户名, 比如Admin
* @param userid * @param userid
* 用户ID * 用户ID
...@@ -97,7 +89,7 @@ public class JwtUtil implements InitializingBean { ...@@ -97,7 +89,7 @@ public class JwtUtil implements InitializingBean {
Date now = new Date(); Date now = new Date();
// 过期时间设置为2天 // 过期时间设置为2天
int expireSecond = 3600 * 24 * 2; int expireSecond = jwtExpireSecond;
Date expiration = Times.nextSecond(now, expireSecond); Date expiration = Times.nextSecond(now, expireSecond);
JwtBuilder jwtBuilder = Jwts.builder(); JwtBuilder jwtBuilder = Jwts.builder();
// 设置Subject为登录用户名 // 设置Subject为登录用户名
......
package pwc.taxtech.atms.security.vendor;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.ImmutableMap;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pwc.taxtech.atms.common.util.SignatureUtil;
import pwc.taxtech.atms.dto.ApiResultDto;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Map;
public class ApiSignatureFilter implements Filter {
private static final Logger LOGGER = LoggerFactory.getLogger(ApiSignatureFilter.class);
private static String INVALID_RESULT = JSON.toJSONString(ApiResultDto.fail("invalid api signature"));
private static Map<String, String> keyMap = new ImmutableMap.Builder<String, String>()
.put("longi", "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJsb25naSIsImV4cCI6MzI0ODczMDE1NjAsImlhdCI6MTUyOTkyMjM2MSwibmJmIjoxNTI5OTIxNzYxLCJqdGkiOiIyNURFRDEyRi0yRTBBLTRERDUtQjkyOS0xRjlCOTI1QzA2MjciLCJhcHBJZCI6ImxvbmdpIn0.fPddvBGXjViEXNrYA7BesndVjM5eYHA0cX_sKZprHbIasD75Sn8vWNVKb5hMDk3wk3M34k7VgkTFHnpj9BF2uw")
.build();
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
try {
HttpServletRequest request = (HttpServletRequest) servletRequest;
String appId = StringUtils.defaultString(request.getParameter(SignatureUtil.SIGN_APP_ID));
String nonceStr = StringUtils.defaultString(request.getParameter(SignatureUtil.SIGN_NONCE_STR));
String timestamp = StringUtils.defaultString(request.getParameter(SignatureUtil.SIGN_TIMESTAMP));
String signature = StringUtils.defaultString(request.getParameter(SignatureUtil.SIGN_SIGNATURE));
String api = StringUtils.defaultString(request.getParameter(SignatureUtil.SIGN_API));
if (StringUtils.isAnyBlank(appId, signature, timestamp, nonceStr, api)) {
writeError(servletResponse, INVALID_RESULT);
return;
}
String key = keyMap.get(appId);
if (StringUtils.isBlank(key)) {
writeError(servletResponse, INVALID_RESULT);
return;
}
if (!SignatureUtil.validate(key, api, nonceStr, timestamp, signature)) {
writeError(servletResponse, INVALID_RESULT);
return;
}
filterChain.doFilter(servletRequest, servletResponse);
} catch (Exception e) {
LOGGER.error("invalid api signature: {}", JSON.toJSONString(servletRequest.getParameterMap()), e);
writeError(servletResponse, INVALID_RESULT);
}
}
@Override
public void destroy() {
}
private void writeError(ServletResponse servletResponse, String msg) throws IOException {
servletResponse.setCharacterEncoding("UTF-8");
servletResponse.setContentType("application/json; charset=UTF-8");
servletResponse.getWriter().write(msg);
}
}
...@@ -3,8 +3,10 @@ package pwc.taxtech.atms.service.impl; ...@@ -3,8 +3,10 @@ package pwc.taxtech.atms.service.impl;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.client.RestTemplate;
import pwc.taxtech.atms.common.AtmsApiSettings; import pwc.taxtech.atms.common.AtmsApiSettings;
import pwc.taxtech.atms.common.AuthUserHelper; import pwc.taxtech.atms.common.AuthUserHelper;
import pwc.taxtech.atms.common.util.BeanUtil;
import pwc.taxtech.atms.service.OperationLogService; import pwc.taxtech.atms.service.OperationLogService;
public class BaseService { public class BaseService {
...@@ -16,5 +18,11 @@ public class BaseService { ...@@ -16,5 +18,11 @@ public class BaseService {
protected AtmsApiSettings atmsApiSettings; protected AtmsApiSettings atmsApiSettings;
@Autowired @Autowired
protected OperationLogService operationLogService; protected OperationLogService operationLogService;
@Autowired
protected DistributedIDService idService;
@Autowired
protected BeanUtil beanUtil;
@Autowired
protected RestTemplate restTemplate;
} }
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd "> http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
<!-- 添加properties文件 --> <!-- 添加properties文件 -->
<bean id="standardPBEStringEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor"> <bean id="standardPBEStringEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
<property name="password" value="${atms_password:k5Cs7OmB5HdtVDOw94Py2V8HOvfmgbzeX9UCWDciqcjfhOulQLRuuJZkgV9zyIvO6QG22ZxOoYiJlCKrYP07O6nPFpcmN3XyNLJ}" /> <property name="password" value="${atms_password:k5Cs7OmB5HdtVDOw94Py2V8HOvfmgbzeX9UCWDciqcjfhOulQLRuuJZkgV9zyIvO6QG22ZxOoYiJlCKrYP07O6nPFpcmN3XyNLJ}" />
...@@ -69,4 +71,14 @@ ...@@ -69,4 +71,14 @@
<tx:annotation-driven proxy-target-class="true" /> <tx:annotation-driven proxy-target-class="true" />
<!-- 缓存配置 -->
<!-- 启用缓存注解功能(请将其配置在Spring主配置文件中) -->
<cache:annotation-driven cache-manager="cacheManager"/>
<bean id="cacheManagerFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml"/>
</bean>
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager" ref="cacheManagerFactory"/>
</bean>
</beans> </beans>
\ No newline at end of file
...@@ -13,6 +13,8 @@ web.url=${web.url} ...@@ -13,6 +13,8 @@ web.url=${web.url}
jwt.base64Secret=${jwt.base64Secret} jwt.base64Secret=${jwt.base64Secret}
jwt.powerToken=${jwt.powerToken} jwt.powerToken=${jwt.powerToken}
jwt.expireSecond=${jwt.expireSecond}
jwt.refreshSecond=${jwt.refreshSecond}
#FTP Config #FTP Config
ftp.host=${ftp.host} ftp.host=${ftp.host}
......
...@@ -13,6 +13,8 @@ web.url=http://localhost:8080 ...@@ -13,6 +13,8 @@ web.url=http://localhost:8080
#web.url=* #web.url=*
jwt.base64Secret=TXppQjFlZFBSbnJzMHc0Tg== jwt.base64Secret=TXppQjFlZFBSbnJzMHc0Tg==
jwt.powerToken=xxxx jwt.powerToken=xxxx
jwt.expireSecond=180000
jwt.refreshSecond=600
ftp.host=cnshaappulv003.asia.pwcinternal.com ftp.host=cnshaappulv003.asia.pwcinternal.com
ftp.port=21 ftp.port=21
......
...@@ -13,6 +13,8 @@ web.url=http://192.168.1.102:10000 ...@@ -13,6 +13,8 @@ web.url=http://192.168.1.102:10000
jwt.base64Secret=TXppQjFlZFBSbnJzMHc0Tg== jwt.base64Secret=TXppQjFlZFBSbnJzMHc0Tg==
jwt.powerToken= jwt.powerToken=
jwt.expireSecond=1800
jwt.refreshSecond=900
ftp.host=cnshaappulv004.asia.pwcinternal.com ftp.host=cnshaappulv004.asia.pwcinternal.com
ftp.port=21 ftp.port=21
......
...@@ -13,6 +13,8 @@ web.url=http://cnshaappulv004:8080 ...@@ -13,6 +13,8 @@ web.url=http://cnshaappulv004:8080
jwt.base64Secret=TXppQjFlZFBSbnJzMHc0Tg== jwt.base64Secret=TXppQjFlZFBSbnJzMHc0Tg==
jwt.powerToken=xxxx jwt.powerToken=xxxx
jwt.expireSecond=1800
jwt.refreshSecond=900
ftp.host=cnshaappulv003.asia.pwcinternal.com ftp.host=cnshaappulv003.asia.pwcinternal.com
ftp.port=21 ftp.port=21
......
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<diskStore path="java.io.tmpdir"/>
<defaultCache maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="false"/>
<!-- 进项发票list缓存 -->
<cache name="inputInvoiceCache"
maxElementsOnDisk="1000"
maxElementsInMemory="2000"
eternal="false"
overflowToDisk="false"
diskPersistent="false"/>
<!-- reflect缓存 -->
<cache name="reflectCache"
maxElementsOnDisk="1000"
maxElementsInMemory="1000"
eternal="true"
overflowToDisk="false"
diskPersistent="false"/>
<!-- 扫描结果缓存 -->
<cache name="scanResultCache"
maxElementsOnDisk="100"
maxElementsInMemory="100"
eternal="false"
timeToIdleSeconds="86400"
timeToLiveSeconds="86400"
overflowToDisk="false"
diskPersistent="false"/>
</ehcache>
<!--
<diskStore>==========当内存缓存中对象数量超过maxElementsInMemory时,将缓存对象写到磁盘缓存中(需对象实现序列化接口)
<diskStore path="">==用来配置磁盘缓存使用的物理路径,Ehcache磁盘缓存使用的文件后缀名是*.data和*.index
name=================缓存名称,cache的唯一标识(ehcache会把这个cache放到HashMap里)
maxElementsOnDisk====磁盘缓存中最多可以存放的元素数量,0表示无穷大
maxElementsInMemory==内存缓存中最多可以存放的元素数量,若放入Cache中的元素超过这个数值,则有以下两种情况
1)若overflowToDisk=true,则会将Cache中多出的元素放入磁盘文件中
2)若overflowToDisk=false,则根据memoryStoreEvictionPolicy策略替换Cache中原有的元素
eternal==============缓存中对象是否永久有效,即是否永驻内存,true时将忽略timeToIdleSeconds和timeToLiveSeconds
timeToIdleSeconds====缓存数据在失效前的允许闲置时间(单位:秒),仅当eternal=false时使用,默认值是0表示可闲置时间无穷大,此为可选属性
即访问这个cache中元素的最大间隔时间,若超过这个时间没有访问此Cache中的某个元素,那么此元素将被从Cache中清除
timeToLiveSeconds====缓存数据在失效前的允许存活时间(单位:秒),仅当eternal=false时使用,默认值是0表示可存活时间无穷大
即Cache中的某元素从创建到清楚的生存时间,也就是说从创建开始计时,当超过这个时间时,此元素将从Cache中清除
overflowToDisk=======内存不足时,是否启用磁盘缓存(即内存中对象数量达到maxElementsInMemory时,Ehcache会将对象写到磁盘中)
会根据标签中path值查找对应的属性值,写入磁盘的文件会放在path文件夹下,文件的名称是cache的名称,后缀名是data
diskPersistent=======是否持久化磁盘缓存,当这个属性的值为true时,系统在初始化时会在磁盘中查找文件名为cache名称,后缀名为index的文件
这个文件中存放了已经持久化在磁盘中的cache的index,找到后会把cache加载到内存
要想把cache真正持久化到磁盘,写程序时注意执行net.sf.ehcache.Cache.put(Element element)后要调用flush()方法
diskExpiryThreadIntervalSeconds==磁盘缓存的清理线程运行间隔,默认是120秒
diskSpoolBufferSizeMB============设置DiskStore(磁盘缓存)的缓存区大小,默认是30MB
memoryStoreEvictionPolicy========内存存储与释放策略,即达到maxElementsInMemory限制时,Ehcache会根据指定策略清理内存
共有三种策略,分别为LRU(最近最少使用)、LFU(最常用的)、FIFO(先进先出)
-->
\ No newline at end of file
...@@ -2,11 +2,56 @@ ...@@ -2,11 +2,56 @@
PUBLIC "-//mybatis.org//DTD Config 3.0//EN" PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd"> "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration> <configuration>
<!-- 全局setting配置,根据需要添加 -->
<!--<settings>-->
<!--<setting name="logImpl" value="LOG4J" /> -->
<!--</settings>-->
<!-- <mappers> <mapper class="org.apache.ibatis.submitted.basetest.Mapper" /> </mappers> --> <!-- 配置别名 -->
<!--<typeAliases>-->
<!--<package name="pwc.taxtech.atms.entitiy"/>-->
<!--</typeAliases>-->
<!-- <settings> <setting name="logImpl" value="LOG4J" /> </settings> --> <!-- 插件 -->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
</configuration> <!-- 4.0.0以后版本可以不设置该参数 -->
\ No newline at end of file <property name="diaect" value="mysql"/>
<!--
该参数默认为false
设置为true时,会将RowBounds第一个参数offset当成pageNum页码使用
和startPage中的pageNum效果一样
-->
<property name="offsetAsPageNum" value="true"/>
<!--
该参数默认为false
设置为true时,使用RowBounds分页会进行count查询
-->
<property name="rowBoundsWithCount" value="true"/>
<!--
设置为true时,如果pageSize=0或者RowBounds.limit=0就会查询出全部的结果
(相当于没有执行分页查询,只是返回结果仍然是Page类型)
-->
<property name="pageSizeZero" value="true"/>
<!--
3.3.0版本可用-分页参数合理化,默认false禁用
启用合理化时,如果pageNum<1会查询第一页,如果pageNum>pages会查询最后一页
禁用合理化时,如果pageNum<1或pages会返回空数据
-->
<property name="reasonable" value="true"/>
<!--
3.5.0版本可用-为了支持startPage(Object params)方法
增加了一个'params'参数来配置参数映射,用于从Map或ServletRequest中取值
可以配置pageNum,pageSize,count,pageSizeZero,reasonable,orderBy,不配置映射的用默认值
不理解该含义的前提下,不要随便复制该配置
-->
<property name="params" value="pageNum=start;pageSize=limit;"/>
<!-- 支持通过Mapper接口参数来传递分页参数 -->
<property name="supportMethodsArguments" value="true"/>
<!-- always重视返回PageInfo类型,check检查返回类型是否为PageInfo,none返回Page -->
<property name="returnPageInfo" value="check"/>
</plugin>
</plugins>
</configuration>
\ No newline at end of file
...@@ -25,6 +25,10 @@ ...@@ -25,6 +25,10 @@
</param-value> </param-value>
</context-param> </context-param>
<filter>
<filter-name>apiSignatureFilter</filter-name>
<filter-class>pwc.taxtech.atms.security.vendor.ApiSignatureFilter</filter-class>
</filter>
<filter> <filter>
<filter-name>corsFilter</filter-name> <filter-name>corsFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
...@@ -46,6 +50,10 @@ ...@@ -46,6 +50,10 @@
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter> </filter>
<filter-mapping>
<filter-name>apiSignatureFilter</filter-name>
<url-pattern>/vendor/*</url-pattern>
</filter-mapping>
<filter-mapping> <filter-mapping>
<filter-name>corsFilter</filter-name> <filter-name>corsFilter</filter-name>
<url-pattern>/*</url-pattern> <url-pattern>/*</url-pattern>
......
package pwc.taxtech.atms.common;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class MyBatisGeneratorTest {
public static void main(String[] args) throws Exception {
try {
List<String> warnings = new ArrayList<>();
boolean overwrite = true;
//指定 逆向工程配置文件
File configFile = new File(MyBatisGeneratorTest.class.getClassLoader().getResource("generatorConfig.xml").getPath());
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);
} catch (Exception e) {
e.printStackTrace();
}
}
}
package pwc.taxtech.atms.controller;
import static org.assertj.core.api.Assertions.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import pwc.taxtech.atms.service.CacheService;
@RunWith(MockitoJUnitRunner.class)
public class CacheControllerTest {
@Mock
private CacheService cacheService;
@InjectMocks
private CacheController cacheController;
@Test
public void getCacheByKey() {
assertThat(cacheController.getCacheByKey("cacheKey1")).isNull();
}
@Test
public void getAllCache() {
assertThat(cacheController.getAllCache()).isEmpty();
}
}
package pwc.taxtech.atms.plugin;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.Interface;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import java.util.List;
public class MapperAnnotationPlugin extends PluginAdapter {
@Override
public boolean validate(List<String> warnings) {
return true;
}
@Override
public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass,
IntrospectedTable introspectedTable) {
interfaze.addImportedType(new FullyQualifiedJavaType("org.apache.ibatis.annotations.Mapper"));
interfaze.addAnnotation("@Mapper");
interfaze.addImportedType(new FullyQualifiedJavaType("org.springframework.stereotype.Repository"));
interfaze.addAnnotation("@Repository");
return true;
}
}
package pwc.taxtech.atms.security;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.junit.Test;
import org.nutz.lang.Times;
import pwc.taxtech.atms.common.CommonUtils;
import pwc.taxtech.atms.dto.vendor.LgItemDto;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
public class JwtGneratorTest {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, 2999);
Date now = new Date();
JwtBuilder jwtBuilder = Jwts.builder();
// 设置Subject为登录用户名
jwtBuilder.setSubject("longi");
jwtBuilder.setExpiration(calendar.getTime());
jwtBuilder.setIssuedAt(now);
// 设置时钟误差偏移量,即10分钟
Date notBefore = Times.nextSecond(now, -600);
jwtBuilder.setNotBefore(notBefore);
jwtBuilder.setId(CommonUtils.getUUID());
jwtBuilder.claim("appId", "longi");
// 设置body.username为数据库用户名
jwtBuilder.signWith(SignatureAlgorithm.HS512, "TXppQjFlZFBSbnJzMHc0Tg==");
System.out.println(jwtBuilder.compact());
}
@Test
public void tt() {
}
}
package pwc.taxtech.atms.service.impl;
import static org.assertj.core.api.Assertions.*;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import pwc.taxtech.atms.CommonIT;
import pwc.taxtech.atms.common.CommonUtils;
import pwc.taxtech.atms.entitiy.Cache;
import pwc.taxtech.atms.service.CacheService;
public class CacheServiceIT extends CommonIT {
@Autowired
private CacheService cacheService;
@Before
public void setUp() {
cacheMapper.deleteByExample(null);
}
@Test
public void getAllCache() {
insertData();
// see assertj document
// http://joel-costigliola.github.io/assertj/assertj-core-quick-start.html
assertThat(cacheService.getAllCache()).isNotEmpty().filteredOn(x -> x.getCacheKey().equals("cachekey1"))
.isNotEmpty().extracting("lastModifyTime").contains("2017-10-18T14:11:01.840+08:00");
}
@Test
public void shoudWork() {
insertData();
assertThat(cacheService.getCacheByKey("cachekey1")).isNotNull().extracting("lastModifyTime")
.contains("2017-10-18T14:11:01.840+08:00");
}
private void insertData() {
Cache record = new Cache();
record.setID(CommonUtils.getUUID());
record.setCacheKey("cachekey1");
record.setLastModifyTime("2017-10-18T14:11:01.840+08:00");
cacheMapper.insert(record);
}
}
package pwc.taxtech.atms.service.impl;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import java.text.ParseException;
import pwc.taxtech.atms.CommonIT;
import pwc.taxtech.atms.constant.enums.EnumInputInvoiceType;
import pwc.taxtech.atms.constant.enums.EnumTbImportType;
import pwc.taxtech.atms.dto.input.InputInvoiceQueryDto;
import pwc.taxtech.atms.service.InvoiceManageService;
public class InvoiceManageServiceImplTest extends CommonIT{
private static final Logger logger = LoggerFactory.getLogger(InvoiceManageServiceImplTest.class);
@Autowired
private InvoiceManageService invoiceManageService;
@Test
public void testGetInputInvoiceList() {
InputInvoiceQueryDto inputInvoiceQueryDto=new InputInvoiceQueryDto();
//inputInvoiceQueryDto.setBuyerBankName("aa");
//inputInvoiceQueryDto.setAmount(amount);
// inputInvoiceQueryDto.setInvoiceDate(new Date());
// inputInvoiceQueryDto.setInvoiceEntityType(1);
// inputInvoiceQueryDto.setInvoiceNumber("11");
// inputInvoiceQueryDto.setInvoiceSourceType(1);
// inputInvoiceQueryDto.setInvoiceType(1);
// inputInvoiceQueryDto.setSellerName("bb");
// inputInvoiceQueryDto.setSerialNo("sdada");
// inputInvoiceQueryDto.setStaffId("12231");
// inputInvoiceQueryDto.setStatus(1);
// inputInvoiceQueryDto.setUploadDate(new Date());
// inputInvoiceQueryDto.setUploadType(1);
// inputInvoiceQueryDto.setAmount(new BigDecimal(10));
// CamelPagingDto camelPagingDto=new CamelPagingDto();
// camelPagingDto.setPageIndex(1);
// camelPagingDto.setPageSize(10);
// inputInvoiceQueryDto.setPagingDto(camelPagingDto);
// List<InputInvoice> list=new InvoiceManageServiceImpl().getInputInvoiceList(inputInvoiceQueryDto);
}
public static Date StrToDate(String str) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = null;
try {
date = format.parse(str);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
public static void main(String[] args) throws ParseException {
Date date = new SimpleDateFormat("yyyy/MM/dd").parse("2018/06/04");
System.out.println(date);
//System.out.println(StrToDate("2018/06/04"));
for (EnumTbImportType e : EnumTbImportType.values()) {
System.out.println(e.name()+":"+e.getCode());
}
for (EnumInputInvoiceType e : EnumInputInvoiceType.values()) {
System.out.println(e.name()+":"+e.getCode()+":"+e.getName());
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!-- See: http://www.mybatis.org/generator/configreference/commentGenerator.html -->
<!--<properties resource="generator.properties" />-->
<!-- <classPathEntry location="../hsqldb/hsqldb-2.3.5.jar" /> -->
<context id="contextId" targetRuntime="MyBatis3">
<!-- 考虑需要兼容DB2与ORCAL数据库, 大部份字段不需要加双引号,autoDelimitKeywords设置为false -->
<property name="autoDelimitKeywords" value="true" />
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<property name="javaFileEncoding" value="UTF-8" />
<plugin type="pwc.taxtech.atms.plugin.MapperAnnotationPlugin" />
<plugin type="org.mybatis.generator.plugins.RowBoundsPlugin" />
<plugin type="org.mybatis.generator.plugins.ToStringPlugin" />
<!--<plugin type="org.mybatis.generator.plugins.SerializablePlugin" />-->
<commentGenerator>
<property name="suppressDate" value="true" />
<property name="addRemarkComments" value="true" />
</commentGenerator>
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://10.157.107.89:3306/tax_longi?useUnicode=true&amp;characterEncoding=utf-8&amp;zeroDateTimeBehavior=convertToNull&amp;allowMultiQueries=true"
userId="root" password="tax@Admin2018">
</jdbcConnection>
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<javaModelGenerator targetPackage="pwc.taxtech.atms.entitiy" targetProject="./src/main/java">
<property name="trimStrings" value="true" />
<property name="rootClass" value="pwc.taxtech.atms.entitiy.BaseEntity"/>
</javaModelGenerator>
<sqlMapGenerator targetPackage="pwc.taxtech.atms.dao" targetProject="./src/main/resources">
</sqlMapGenerator>
<javaClientGenerator type="XMLMAPPER" targetPackage="pwc.taxtech.atms.dao" targetProject="./src/main/java">
<property name="rootInterface" value="pwc.taxtech.atms.MyMapper" />
</javaClientGenerator>
<!--<table tableName="input_invoice" domainObjectName="InputInvoice">-->
<!--<property name="ignoreQualifiersAtRuntime" value="true"/>-->
<!--<columnOverride column="invoice_type" javaType="java.lang.Integer"/>-->
<!--<columnOverride column="upload_type" javaType="java.lang.Integer"/>-->
<!--<columnOverride column="invoice_entity_type" javaType="java.lang.Integer"/>-->
<!--<columnOverride column="invoice_source_type" javaType="java.lang.Integer"/>-->
<!--<columnOverride column="status" javaType="java.lang.Integer"/>-->
<!--<columnOverride column="deductible" javaType="java.lang.Boolean"/>-->
<!--<columnOverride column="has_down_file" javaType="java.lang.Boolean"/>-->
<!--<columnOverride column="verify_type" javaType="java.lang.Integer"/>-->
<!--<columnOverride column="deductible_result" javaType="java.lang.Integer"/>-->
<!--<columnOverride column="is_red_invoice" javaType="java.lang.Boolean"/>-->
<!--</table>-->
<!--<table tableName="input_invoice_additional" domainObjectName="InputInvoiceAdditional">-->
<!--<property name="ignoreQualifiersAtRuntime" value="true"/>-->
<!--<columnOverride column="type" javaType="java.lang.Integer"/>-->
<!--</table>-->
<table tableName="input_invoice_file" domainObjectName="InputInvoiceFile">
<property name="ignoreQualifiersAtRuntime" value="true"/>
</table>
<!--<table tableName="input_invoice_item" domainObjectName="InputInvoiceItem">-->
<!--<property name="ignoreQualifiersAtRuntime" value="true"/>-->
<!--</table>-->
<!--<table tableName="input_invoice_item_original" domainObjectName="InputInvoiceItemOriginal">-->
<!--<property name="ignoreQualifiersAtRuntime" value="true"/>-->
<!--</table>-->
<!--<table tableName="input_invoice_not_received" domainObjectName="InputInvoiceNotReceived">-->
<!--<property name="ignoreQualifiersAtRuntime" value="true"/>-->
<!--<columnOverride column="invoice_type" javaType="java.lang.Integer"/>-->
<!--<columnOverride column="upload_type" javaType="java.lang.Integer"/>-->
<!--<columnOverride column="invoice_entity_type" javaType="java.lang.Integer"/>-->
<!--<columnOverride column="invoice_source_type" javaType="java.lang.Integer"/>-->
<!--<columnOverride column="status" javaType="java.lang.Integer"/>-->
<!--<columnOverride column="deductible" javaType="java.lang.Boolean"/>-->
<!--<columnOverride column="has_down_file" javaType="java.lang.Boolean"/>-->
<!--<columnOverride column="verify_type" javaType="java.lang.Integer"/>-->
<!--<columnOverride column="deductible_result" javaType="java.lang.Integer"/>-->
<!--</table>-->
<!--<table tableName="input_invoice_original" domainObjectName="InputInvoiceOriginal">-->
<!--<property name="ignoreQualifiersAtRuntime" value="true"/>-->
<!--<columnOverride column="invoice_type" javaType="java.lang.Integer"/>-->
<!--<columnOverride column="upload_type" javaType="java.lang.Integer"/>-->
<!--<columnOverride column="invoice_entity_type" javaType="java.lang.Integer"/>-->
<!--<columnOverride column="invoice_source_type" javaType="java.lang.Integer"/>-->
<!--<columnOverride column="status" javaType="java.lang.Integer"/>-->
<!--<columnOverride column="deductible" javaType="java.lang.Boolean"/>-->
<!--<columnOverride column="has_down_file" javaType="java.lang.Boolean"/>-->
<!--<columnOverride column="verify_type" javaType="java.lang.Integer"/>-->
<!--<columnOverride column="deductible_result" javaType="java.lang.Integer"/>-->
<!--<columnOverride column="is_red_invoice" javaType="java.lang.Boolean"/>-->
<!--</table>-->
<!--<table tableName="api_cache" domainObjectName="ApiCache">-->
<!--<property name="ignoreQualifiersAtRuntime" value="true"/>-->
<!--<columnOverride column="source_type" javaType="java.lang.Integer"/>-->
<!--</table>-->
<!--<table tableName="input_material_item" domainObjectName="InputMaterialItem">-->
<!--<property name="ignoreQualifiersAtRuntime" value="true"/>-->
<!--</table>-->
<!--<table tableName="input_material_item_category" domainObjectName="InputMaterialItemCategory">-->
<!--<property name="ignoreQualifiersAtRuntime" value="true"/>-->
<!--</table>-->
<!--<table tableName="input_vendor" domainObjectName="InputVendor">-->
<!--<property name="ignoreQualifiersAtRuntime" value="true"/>-->
<!--</table>-->
<!--<table tableName="input_vendor_address" domainObjectName="InputVendorAddress">-->
<!--<property name="ignoreQualifiersAtRuntime" value="true"/>-->
<!--</table>-->
<!--<table tableName="input_vendor_bank_account" domainObjectName="InputVendorBankAccount">-->
<!--<property name="ignoreQualifiersAtRuntime" value="true"/>-->
<!--</table>-->
<!--<table tableName="input_vendor_contactor" domainObjectName="InputVendorContactor">-->
<!--<property name="ignoreQualifiersAtRuntime" value="true"/>-->
<!--</table>-->
<!--<table tableName="input_vendor_site" domainObjectName="InputVendorSite">-->
<!--<property name="ignoreQualifiersAtRuntime" value="true"/>-->
<!--</table>-->
<!--<table tableName="input_device" domainObjectName="InputDevice">-->
<!--<property name="ignoreQualifiersAtRuntime" value="true"/>-->
<!--<columnOverride column="type" javaType="java.lang.Integer"/>-->
<!--</table>-->
<!--<table tableName="task_list" domainObjectName="TaskList">-->
<!--<property name="ignoreQualifiersAtRuntime" value="true"/>-->
<!--<columnOverride column="type" javaType="java.lang.Integer"/>-->
<!--<columnOverride column="status" javaType="java.lang.Integer"/>-->
<!--</table>-->
</context>
</generatorConfiguration>
\ No newline at end of file
api.url=http://localhost:8180/ api.url=http://localhost:8180/
cookie.maxAgeSeconds=3600 cookie.maxAgeSeconds=86400
api.url=http://192.168.1.102:8180/atms-api api.url=http://192.168.1.102:8180/atms-api
cookie.maxAgeSeconds=3600 cookie.maxAgeSeconds=86400
api.url=http://cnshaappulv004:8180/ api.url=http://cnshaappulv004:8180/
cookie.maxAgeSeconds=3600 cookie.maxAgeSeconds=86400
/// <reference path="../../app.js" /> /// <reference path="../../app.js" />
// apiInterceptor is responsible to handle the aspect of each request and response. // apiInterceptor is responsible to handle the aspect of each request and response.
webservices.factory('apiInterceptor', ['$q', 'loginContext', '$log', '$window', '$injector', webservices.factory('apiInterceptor', ['$q', 'loginContext', '$log', '$window', '$injector','$cookies',
function ($q, loginContext, $log, $window, $injector) { function ($q, loginContext, $log, $window, $injector,$cookies) {
'use strict'; 'use strict';
$log.debug('apiInterceptor.ctor()...'); $log.debug('apiInterceptor.ctor()...');
...@@ -18,7 +18,9 @@ webservices.factory('apiInterceptor', ['$q', 'loginContext', '$log', '$window', ...@@ -18,7 +18,9 @@ webservices.factory('apiInterceptor', ['$q', 'loginContext', '$log', '$window',
return { return {
//token save to services for further usage //token save to services for further usage
tokenType: tokenType, tokenType: tokenType,
apiToken: apiToken, apiToken: function () {
return apiToken;
},
webApiHostUrl: webApiHostUrl, webApiHostUrl: webApiHostUrl,
//for vat api //for vat api
vatWebApiHostUrl: vatWebApiHostUrl, vatWebApiHostUrl: vatWebApiHostUrl,
...@@ -40,14 +42,15 @@ webservices.factory('apiInterceptor', ['$q', 'loginContext', '$log', '$window', ...@@ -40,14 +42,15 @@ webservices.factory('apiInterceptor', ['$q', 'loginContext', '$log', '$window',
} }
config.withCredentials = true; config.withCredentials = true;
//废弃 token有效期会自动判断
// before each api call, try to ensure user account has not been expired // before each api call, try to ensure user account has not been expired
// otherwise, force user to login again // otherwise, force user to login again
var $http = $injector.get('$http'); // var $http = $injector.get('$http');
$http.get(loginContext.serverUrl + '/Account/CheckLoginStatus?_=' + (new Date).valueOf(), { isBusyRequest: true }).success(function (data) { // $http.get(loginContext.serverUrl + '/Account/CheckLoginStatus?_=' + (new Date).valueOf(), { isBusyRequest: false }).success(function (data) {
if (data === false) { // if (data === false) {
redirectToLogOut(); // redirectToLogOut();
} // }
}); // });
} }
return config; return config;
...@@ -64,6 +67,11 @@ webservices.factory('apiInterceptor', ['$q', 'loginContext', '$log', '$window', ...@@ -64,6 +67,11 @@ webservices.factory('apiInterceptor', ['$q', 'loginContext', '$log', '$window',
if (response.status === 401) { if (response.status === 401) {
redirectToLogOut(); redirectToLogOut();
} }
var tmpToken = response.headers('refreshToken');
if (!!tmpToken) {
apiToken = tmpToken;
$log.info('refresh token: ' + apiToken);
}
return response || $q.when(response); return response || $q.when(response);
}, },
// On response failture // On response failture
...@@ -168,12 +176,12 @@ webservices.factory('apiConfig', ['$log', 'vatSessionService', ...@@ -168,12 +176,12 @@ webservices.factory('apiConfig', ['$log', 'vatSessionService',
} }
cfg.isWebApiRequest = true; cfg.isWebApiRequest = true;
if (config && config.dbName) {//TODO:from is not allowed ,future should open (neo) if (config && config.dbName) {
cfg.headers = { 'from': config.dbName + '@cn.pwc.com' }; cfg.headers = { 'from': config.dbName + '@cn.pwc.com' };
} }
else { else {
if (vatSessionService.project && vatSessionService.project.dbName) { if (vatSessionService.project && vatSessionService.project.dbName) {
cfg.headers = { 'from': vatSessionService.project.dbName + '@cn.pwc.com' }; cfg.headers = { 'from': vatSessionService.project.dbName + '@cn.pwc.com' };
} }
} }
return cfg; return cfg;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment