Commit 65324010 authored by Java-刘 彧阳's avatar Java-刘 彧阳

Merge branch 'master' into log_without_phone

Conflicts:
	src/main/java/cn/quantgroup/xyqb/controller/external/user/WeChatController.java
	src/test/java/user/TestUserLogin.java
parents 3cc775b3 0c126d5d
<?xml version="1.0" encoding="UTF-8"?> <?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" <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 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> <modelVersion>4.0.0</modelVersion>
...@@ -40,6 +40,12 @@ ...@@ -40,6 +40,12 @@
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId> <artifactId>spring-boot-starter-jdbc</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
...@@ -207,6 +213,78 @@ ...@@ -207,6 +213,78 @@
<artifactId>quantgroup-config-sdk</artifactId> <artifactId>quantgroup-config-sdk</artifactId>
<version>1.0.3-SNAPSHOT</version> <version>1.0.3-SNAPSHOT</version>
</dependency> </dependency>
<!-- motan -->
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-core</artifactId>
<version>0.2.2</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>com.caucho</groupId>
<artifactId>hessian</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>cn.quantgroup</groupId>
<artifactId>hession-bugfix</artifactId>
<version>4.0.38</version>
</dependency>
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-transport-netty</artifactId>
<version>0.2.2</version>
</dependency>
<!-- only needed for spring-based features -->
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-springsupport</artifactId>
<version>0.2.2</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>cn.quantgroup</groupId>
<artifactId>xyqb-user-rpc-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-registry-zookeeper</artifactId>
<version>0.2.1</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- spring security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>3.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.2.7.RELEASE</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
...@@ -249,49 +327,49 @@ ...@@ -249,49 +327,49 @@
</build> </build>
</profile> </profile>
<profile> <profile>
<id>dev</id> <id>dev</id>
<properties> <properties>
<profiles.activation>dev</profiles.activation> <profiles.activation>dev</profiles.activation>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>cn.quantgroup</groupId> <groupId>cn.quantgroup</groupId>
<artifactId>quantgroup-sms-sdk</artifactId> <artifactId>quantgroup-sms-sdk</artifactId>
<version>2.0.0.3-SNAPSHOT</version> <version>2.0.0.3-SNAPSHOT</version>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
<resources> <resources>
<resource> <resource>
<directory> <directory>
${project.basedir}/src/main/resources/config/dev ${project.basedir}/src/main/resources/config/dev
</directory> </directory>
</resource> </resource>
</resources> </resources>
</build> </build>
</profile> </profile>
<profile> <profile>
<id>test</id> <id>test</id>
<properties> <properties>
<profiles.activation>test</profiles.activation> <profiles.activation>test</profiles.activation>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>cn.quantgroup</groupId> <groupId>cn.quantgroup</groupId>
<artifactId>quantgroup-sms-sdk</artifactId> <artifactId>quantgroup-sms-sdk</artifactId>
<version>1.0.5-SNAPSHOT</version> <version>1.0.5-SNAPSHOT</version>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
<resources> <resources>
<resource> <resource>
<directory> <directory>
${project.basedir}/src/main/resources/config/test ${project.basedir}/src/main/resources/config/test
</directory> </directory>
</resource> </resource>
</resources> </resources>
</build> </build>
</profile> </profile>
</profiles> </profiles>
</project> </project>
package cn.quantgroup.xyqb; package cn.quantgroup.xyqb;
import com.weibo.api.motan.common.MotanConstants;
import com.weibo.api.motan.util.MotanSwitcherUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.PropertySource; import org.springframework.context.annotation.PropertySource;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableAsync;
@ComponentScan(basePackages = {"cn.quantgroup.xyqb", "cn.quantgroup.cloudconfig"}) @ComponentScan(basePackages = {"cn.quantgroup.xyqb", "cn.quantgroup.cloudconfig"})
...@@ -18,9 +23,20 @@ import org.springframework.scheduling.annotation.EnableAsync; ...@@ -18,9 +23,20 @@ import org.springframework.scheduling.annotation.EnableAsync;
@Configuration @Configuration
@EnableAspectJAutoProxy @EnableAspectJAutoProxy
@EnableAsync @EnableAsync
@Slf4j
public class Bootstrap { public class Bootstrap {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(Bootstrap.class, args); SpringApplication springApplication = new SpringApplication(Bootstrap.class);
} springApplication.addListeners(new ApplicationListener<ContextRefreshedEvent>() {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
MotanSwitcherUtil.setSwitcherValue(MotanConstants.REGISTRY_HEARTBEAT_SWITCHER, true);
log.info("注册zookeeper成功");
}
});
springApplication.setRegisterShutdownHook(true);
springApplication.run(args);
log.info("server start...");
}
} }
package cn.quantgroup.xyqb; package cn.quantgroup.xyqb;
/** /**
* Created by Miraculous on 15/7/5. * Created by Miraculous on 15/7/5.
*/ */
public interface Constants { public interface Constants {
// zero fill with 4 chars... // zero fill with 4 chars...
String ZERO_FILL_TEMPLATE = "%04d"; String ZERO_FILL_TEMPLATE = "%04d";
String PASSWORD_SALT = "_lkb"; String PASSWORD_SALT = "_lkb";
String IMAGE_CAPTCHA_KEY = "img_captcha:"; String IMAGE_CAPTCHA_KEY = "img_captcha:";
String REDIS_CAPTCHA_KEY = "auth:"; String REDIS_CAPTCHA_KEY = "auth:";
String REDIS_CAPTCHA_KEY_PATTERN = REDIS_CAPTCHA_KEY + IMAGE_CAPTCHA_KEY + "*"; String REDIS_CAPTCHA_KEY_PATTERN = REDIS_CAPTCHA_KEY + IMAGE_CAPTCHA_KEY + "*";
String CONFIG_CAPTCHA = "cfg_captcha_%"; String CONFIG_CAPTCHA = "cfg_captcha_%";
// app 后端白名单 // app 后端白名单
String CONFIG_CAPTCHA_WHITEIP_LIST = "cfg_captcha_white_ip_appbackend"; String CONFIG_CAPTCHA_WHITEIP_LIST = "cfg_captcha_white_ip_appbackend";
// 每个 IP 每分钟 captcha 限制 // 每个 IP 每分钟 captcha 限制
String CONFIG_CAPTCHA_PERIP_PERMIN = "cfg_captcha_per_ip_per_min"; String CONFIG_CAPTCHA_PERIP_PERMIN = "cfg_captcha_per_ip_per_min";
// 是否启用万能验证码 // 是否启用万能验证码
String CONFIG_CAPTCHA_MAGIC_CODE_ENABLED = "cfg_captcha_magic_code_enabled"; String CONFIG_CAPTCHA_MAGIC_CODE_ENABLED = "cfg_captcha_magic_code_enabled";
String REDIS_PREFIX_VERIFICATION_CODE = "verificationCode_"; String REDIS_PREFIX_VERIFICATION_CODE = "verificationCode_";
/** /**
* redis中token的key值前缀 * redis中token的key值前缀
*/ */
String SESSION_PREFIX = "spring:session:sessions:"; String SESSION_PREFIX = "spring:session:sessions:";
interface Jr58 { interface Jr58 {
int ERROR_PHONE_NUMBER = 20007; // 手机号码格式不正确 int ERROR_PHONE_NUMBER = 20007; // 手机号码格式不正确
int ERROR_ID_CARD = 20009; // 身份证格式不正确 int ERROR_ID_CARD = 20009; // 身份证格式不正确
int ERROR_ACCOUNT = 20010; // 授权账号为空 int ERROR_ACCOUNT = 20010; // 授权账号为空
int ERROR_AUTH_TYPE = 20011; // 授权类型为空 int ERROR_AUTH_TYPE = 20011; // 授权类型为空
} }
interface Channel { interface Channel {
long LKB = 1; // 量化派 long LKB = 1; // 量化派
long JR58 = 175; // 58金融 long JR58 = 175; // 58金融
long BAITIAO = 222L; long BAITIAO = 222L;
String LKB_CODE = "0002"; // 量化派channnel_code String LKB_CODE = "0002"; // 量化派channnel_code
long WECHAT = 198L; long WECHAT = 198L;
} }
interface Session{ interface Session {
String USER_SESSION_CACHE = "user:session:"; String USER_SESSION_CACHE = "user:session:";
String USER_SESSION_ID_CACHE = "userid-sessionvalue:cache:"; String USER_SESSION_ID_CACHE = "userid-sessionvalue:cache:";
Long ONE_DAY = 24 * 60 * 60L; Long ONE_DAY = 24 * 60 * 60L;
} }
interface WeChat { interface WeChat {
String APP_ID = "wx0a7c0bce0c3ac523"; String APP_ID = "wx0a7c0bce0c3ac523";
String REDIRECT_URL = "http://wechattest.xyqb.com/webchat/receiveCode"; String REDIRECT_URL = "http://wechattest.xyqb.com/webchat/receiveCode";
String SCOPE = "snsapi_userinfo"; String SCOPE = "snsapi_userinfo";
} }
} }
...@@ -40,82 +40,82 @@ import java.util.UUID; ...@@ -40,82 +40,82 @@ import java.util.UUID;
@Component @Component
public class CaptchaValidateAdvisor { public class CaptchaValidateAdvisor {
private static final Logger LOGGER = LoggerFactory.getLogger(CaptchaValidateAdvisor.class); private static final Logger LOGGER = LoggerFactory.getLogger(CaptchaValidateAdvisor.class);
private static final String SUPER_CAPTCHA_ID = UUID.nameUUIDFromBytes("__QG_APPCLIENT_AGENT__".getBytes(Charset.forName("UTF-8"))).toString(); private static final String SUPER_CAPTCHA_ID = UUID.nameUUIDFromBytes("__QG_APPCLIENT_AGENT__".getBytes(Charset.forName("UTF-8"))).toString();
private static final String SUPER_CAPTCHA = "__SUPERQG__"; private static final String SUPER_CAPTCHA = "__SUPERQG__";
@Autowired @Autowired
@Qualifier("stringRedisTemplate") @Qualifier("stringRedisTemplate")
private RedisTemplate<String, String> redisTemplate; private RedisTemplate<String, String> redisTemplate;
@Autowired @Autowired
@Qualifier("customCaptchaService") @Qualifier("customCaptchaService")
private AbstractManageableImageCaptchaService imageCaptchaService; private AbstractManageableImageCaptchaService imageCaptchaService;
/** /**
* 自动化测试忽略验证码 * 自动化测试忽略验证码
*/ */
@Value("${xyqb.auth.captcha.autotest.enable:false}") @Value("${xyqb.auth.captcha.autotest.enable:false}")
private boolean autoTestCaptchaEnabled; private boolean autoTestCaptchaEnabled;
/** /**
* 图形验证码切面 * 图形验证码切面
*/ */
@Pointcut("@annotation(cn.quantgroup.xyqb.aspect.captcha.CaptchaValidator)") @Pointcut("@annotation(cn.quantgroup.xyqb.aspect.captcha.CaptchaValidator)")
private void needCaptchaValidate() { private void needCaptchaValidate() {
}
/**
* 在受图形验证码保护的接口方法执行前, 执行图形验证码校验
*
* @param pjp
* @return
* @throws Throwable
*/
@Around("needCaptchaValidate()")
private Object doCapchaValidate(ProceedingJoinPoint pjp) throws Throwable {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String registerFrom = Optional.ofNullable(request.getParameter("registerFrom")).orElse("");
String captchaId = Optional.ofNullable(request.getParameter("captchaId")).orElse("");
Object captchaValue = request.getParameter("captchaValue");
if (shouldSkipCaptchaValidate(registerFrom, captchaId, captchaValue)) {
LOGGER.info("使用超级图形验证码校验, registerFrom={}, clientIp={}", registerFrom, request.getRemoteAddr());
return pjp.proceed();
} }
JsonResult result = JsonResult.buildSuccessResult("图形验证码错误, 请重新输入", "");
/** result.setBusinessCode("0002");
* 在受图形验证码保护的接口方法执行前, 执行图形验证码校验 if (captchaValue != null) {
* String captcha = String.valueOf(captchaValue);
* @param pjp // 忽略用户输入的大小写
* @return captcha = StringUtils.lowerCase(captcha);
* @throws Throwable // 验证码校验
*/ Boolean validCaptcha = false;
@Around("needCaptchaValidate()") try {
private Object doCapchaValidate(ProceedingJoinPoint pjp) throws Throwable { validCaptcha = imageCaptchaService.validateResponseForID(Constants.IMAGE_CAPTCHA_KEY + captchaId, captcha);
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); } catch (CaptchaServiceException ex) {
String registerFrom = Optional.ofNullable(request.getParameter("registerFrom")).orElse(""); LOGGER.error("验证码校验异常, {}, {}", ex.getMessage(), ex);
String captchaId = Optional.ofNullable(request.getParameter("captchaId")).orElse(""); }
Object captchaValue = request.getParameter("captchaValue");
if (validCaptcha) {
if (shouldSkipCaptchaValidate(registerFrom, captchaId, captchaValue)) { return pjp.proceed();
LOGGER.info("使用超级图形验证码校验, registerFrom={}, clientIp={}", registerFrom, request.getRemoteAddr()); }
return pjp.proceed();
}
JsonResult result = JsonResult.buildSuccessResult("图形验证码错误, 请重新输入", "");
result.setBusinessCode("0002");
if (captchaValue != null) {
String captcha = String.valueOf(captchaValue);
// 忽略用户输入的大小写
captcha = StringUtils.lowerCase(captcha);
// 验证码校验
Boolean validCaptcha = false;
try {
validCaptcha = imageCaptchaService.validateResponseForID(Constants.IMAGE_CAPTCHA_KEY + captchaId, captcha);
} catch (CaptchaServiceException ex) {
LOGGER.error("验证码校验异常, {}, {}", ex.getMessage(), ex);
}
if (validCaptcha) {
return pjp.proceed();
}
}
return result;
} }
private boolean shouldSkipCaptchaValidate(String registerFrom, String captchaId, Object captchaValue) { return result;
}
// 如果启用了超级验证码功能, 检查超级验证码, 超级验证码区分大小写 private boolean shouldSkipCaptchaValidate(String registerFrom, String captchaId, Object captchaValue) {
if (autoTestCaptchaEnabled) {
return true;
}
return StringUtils.equals(SUPER_CAPTCHA_ID, String.valueOf(captchaId)) && StringUtils.equals(SUPER_CAPTCHA, String.valueOf(captchaValue)); // 如果启用了超级验证码功能, 检查超级验证码, 超级验证码区分大小写
if (autoTestCaptchaEnabled) {
return true;
} }
return StringUtils.equals(SUPER_CAPTCHA_ID, String.valueOf(captchaId)) && StringUtils.equals(SUPER_CAPTCHA, String.valueOf(captchaValue));
}
} }
package cn.quantgroup.xyqb.aspect.captcha; package cn.quantgroup.xyqb.aspect.captcha;
import java.lang.annotation.Documented; import java.lang.annotation.*;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** /**
* 类名称:CaptchaValidate * 类名称:CaptchaValidate
......
package cn.quantgroup.xyqb.aspect.fplock; package cn.quantgroup.xyqb.aspect.fplock;
import java.lang.annotation.Documented; import java.lang.annotation.*;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** /**
* Created by Miraculous on 15/11/10. * Created by Miraculous on 15/11/10.
...@@ -14,6 +10,7 @@ import java.lang.annotation.Target; ...@@ -14,6 +10,7 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface FPLock { public @interface FPLock {
String uniqueName(); String uniqueName();
FPRestriction[] restrictions() default {};
FPRestriction[] restrictions() default {};
} }
package cn.quantgroup.xyqb.aspect.fplock; package cn.quantgroup.xyqb.aspect.fplock;
import java.lang.annotation.Documented; import java.lang.annotation.*;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
...@@ -14,12 +10,15 @@ import java.util.concurrent.TimeUnit; ...@@ -14,12 +10,15 @@ import java.util.concurrent.TimeUnit;
@Target(ElementType.METHOD) @Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface FPRestriction { public @interface FPRestriction {
// 持续时间 // 持续时间
int duration() default 1; int duration() default 1;
// 持续时间单位
TimeUnit type() default TimeUnit.MINUTES; // 持续时间单位
// 限制值, -1表示不限制 TimeUnit type() default TimeUnit.MINUTES;
int limit() default -1;
// 使用可覆盖 // 限制值, -1表示不限制
boolean override() default true; int limit() default -1;
// 使用可覆盖
boolean override() default true;
} }
...@@ -23,23 +23,23 @@ import org.springframework.data.redis.core.RedisTemplate; ...@@ -23,23 +23,23 @@ import org.springframework.data.redis.core.RedisTemplate;
@Configuration @Configuration
public class CaptchaConfig { public class CaptchaConfig {
@Bean @Bean
public CaptchaEngine initCaptchaEngine() { public CaptchaEngine initCaptchaEngine() {
return new CustomJCaptchaEngine(); return new CustomJCaptchaEngine();
} }
@Bean @Bean
@Autowired @Autowired
@Qualifier("stringRedisTemplate") @Qualifier("stringRedisTemplate")
public CaptchaStore initStringCaptchaStore(RedisTemplate<String, String> stringRedisTemplate) { public CaptchaStore initStringCaptchaStore(RedisTemplate<String, String> stringRedisTemplate) {
return new RedisCaptchaStore(stringRedisTemplate); return new RedisCaptchaStore(stringRedisTemplate);
} }
@Bean(name = "customCaptchaService") @Bean(name = "customCaptchaService")
@Autowired @Autowired
public AbstractManageableImageCaptchaService initCaptchaService(CaptchaStore captchaStore, CaptchaEngine captchaEngine) { public AbstractManageableImageCaptchaService initCaptchaService(CaptchaStore captchaStore, CaptchaEngine captchaEngine) {
return new CustomJCaptchaService(captchaStore, captchaEngine); return new CustomJCaptchaService(captchaStore, captchaEngine);
} }
} }
...@@ -35,44 +35,44 @@ import java.awt.image.ImageFilter; ...@@ -35,44 +35,44 @@ import java.awt.image.ImageFilter;
*/ */
public class CustomJCaptchaEngine extends ListImageCaptchaEngine { public class CustomJCaptchaEngine extends ListImageCaptchaEngine {
private static final int MIN_WORD_LEN = 4; private static final int MIN_WORD_LEN = 4;
private static final int MAX_WORD_LEN = 4; private static final int MAX_WORD_LEN = 4;
@Override @Override
protected void buildInitialFactories() { protected void buildInitialFactories() {
int minWordLength = 4; int minWordLength = 4;
int maxWordLength = 4; int maxWordLength = 4;
int fontSize = 16; int fontSize = 16;
int imageWidth = 80; int imageWidth = 80;
int imageHeight = 28; int imageHeight = 28;
WordGenerator wordGenerator = new RandomWordGenerator("1234567890"); WordGenerator wordGenerator = new RandomWordGenerator("1234567890");
SingleColorGenerator colorGenerator = new SingleColorGenerator(Color.WHITE); SingleColorGenerator colorGenerator = new SingleColorGenerator(Color.WHITE);
//文字干扰器--- 可以创建多个 //文字干扰器--- 可以创建多个
BaffleTextDecorator baffleTextDecorator = new BaffleTextDecorator(1,colorGenerator, 1);//气泡干扰 BaffleTextDecorator baffleTextDecorator = new BaffleTextDecorator(1, colorGenerator, 1);//气泡干扰
// LineTextDecorator lineTextDecorator = new LineTextDecorator(1,colorGenerator, 1);//曲线干扰 // LineTextDecorator lineTextDecorator = new LineTextDecorator(1,colorGenerator, 1);//曲线干扰
// TextDecorator[] textDecorators = new TextDecorator[]{baffleTextDecorator, lineTextDecorator}; // TextDecorator[] textDecorators = new TextDecorator[]{baffleTextDecorator, lineTextDecorator};
TextDecorator[] textDecorators = new TextDecorator[]{baffleTextDecorator}; TextDecorator[] textDecorators = new TextDecorator[]{baffleTextDecorator};
TextPaster randomPaster = new DecoratedRandomTextPaster(minWordLength, TextPaster randomPaster = new DecoratedRandomTextPaster(minWordLength,
maxWordLength, new RandomListColorGenerator(new Color[]{ maxWordLength, new RandomListColorGenerator(new Color[]{
new Color(23, 170, 27), new Color(220, 34, 11), new Color(23, 170, 27), new Color(220, 34, 11),
new Color(23, 67, 172)}), textDecorators); new Color(23, 67, 172)}), textDecorators);
BackgroundGenerator background = new UniColorBackgroundGenerator(imageWidth, imageHeight, colorGenerator); BackgroundGenerator background = new UniColorBackgroundGenerator(imageWidth, imageHeight, colorGenerator);
FontGenerator font = new RandomFontGenerator(fontSize, fontSize, FontGenerator font = new RandomFontGenerator(fontSize, fontSize,
new Font[]{new Font("nyala", Font.BOLD, fontSize), new Font[]{new Font("nyala", Font.BOLD, fontSize),
new Font("Bell MT", Font.PLAIN, fontSize), new Font("Bell MT", Font.PLAIN, fontSize),
new Font("Credit valley", Font.BOLD, fontSize)}); new Font("Credit valley", Font.BOLD, fontSize)});
ImageDeformation postDef = new ImageDeformationByFilters(new ImageFilter[]{}); ImageDeformation postDef = new ImageDeformationByFilters(new ImageFilter[]{});
ImageDeformation backDef = new ImageDeformationByFilters(new ImageFilter[]{}); ImageDeformation backDef = new ImageDeformationByFilters(new ImageFilter[]{});
ImageDeformation textDef = new ImageDeformationByFilters(new ImageFilter[]{}); ImageDeformation textDef = new ImageDeformationByFilters(new ImageFilter[]{});
WordToImage word2image = new DeformedComposedWordToImage(font, WordToImage word2image = new DeformedComposedWordToImage(font,
background, randomPaster, backDef, textDef, postDef); background, randomPaster, backDef, textDef, postDef);
addFactory(new CustomGimpyFactory(wordGenerator, word2image)); addFactory(new CustomGimpyFactory(wordGenerator, word2image));
} }
} }
...@@ -24,84 +24,84 @@ import java.util.Locale; ...@@ -24,84 +24,84 @@ import java.util.Locale;
*/ */
public class CustomJCaptchaService extends AbstractManageableImageCaptchaService { public class CustomJCaptchaService extends AbstractManageableImageCaptchaService {
private static final Logger LOGGER = LoggerFactory.getLogger(CustomJCaptchaService.class); private static final Logger LOGGER = LoggerFactory.getLogger(CustomJCaptchaService.class);
/* /*
* 验证码管理策略: * 验证码管理策略:
* 1, 生成验证码时, 会进行配额检查, 当达到配额时, 进行垃圾验证码清理 * 1, 生成验证码时, 会进行配额检查, 当达到配额时, 进行垃圾验证码清理
* 2, 一个验证码校验完成后, 不管成功失败, 都会直接失效, 删除? * 2, 一个验证码校验完成后, 不管成功失败, 都会直接失效, 删除?
* */ * */
private static final Integer MIN_GUARANTED_STORAGE_DELAY_IN_SECONDS = 120; // 默认值, 执行垃圾清理时, 存活超过180s的验证码都会被清除 private static final Integer MIN_GUARANTED_STORAGE_DELAY_IN_SECONDS = 120; // 默认值, 执行垃圾清理时, 存活超过180s的验证码都会被清除
private static final Integer MAX_CAPTCHA_STORE_SIZE = 70000; // 最大容量, 默认值是10w private static final Integer MAX_CAPTCHA_STORE_SIZE = 70000; // 最大容量, 默认值是10w
private static final Integer CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION = 52500; // 配额, 超过此配额时执行一次垃圾清除, 默认值是:75000 private static final Integer CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION = 52500; // 配额, 超过此配额时执行一次垃圾清除, 默认值是:75000
public CustomJCaptchaService(CaptchaStore captchaStore, CaptchaEngine captchaEngine) {
this(captchaStore, captchaEngine, MIN_GUARANTED_STORAGE_DELAY_IN_SECONDS, MAX_CAPTCHA_STORE_SIZE, CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION);
}
public CustomJCaptchaService(CaptchaStore captchaStore, CaptchaEngine captchaEngine) {
this(captchaStore, captchaEngine, MIN_GUARANTED_STORAGE_DELAY_IN_SECONDS, MAX_CAPTCHA_STORE_SIZE, CAPTCHA_STORE_LOAD_BEFORE_GARBAGE_COLLECTION);
}
protected CustomJCaptchaService(CaptchaStore captchaStore, CaptchaEngine captchaEngine, int minGuarantedStorageDelayInSeconds, int maxCaptchaStoreSize, int captchaStoreLoadBeforeGarbageCollection) {
super(captchaStore, captchaEngine, minGuarantedStorageDelayInSeconds, maxCaptchaStoreSize, captchaStoreLoadBeforeGarbageCollection);
}
@Override
public long getCustomStoreSize() {
return this.store.getSize();
}
/** protected CustomJCaptchaService(CaptchaStore captchaStore, CaptchaEngine captchaEngine, int minGuarantedStorageDelayInSeconds, int maxCaptchaStoreSize, int captchaStoreLoadBeforeGarbageCollection) {
* 重写校验, 需要将原来的 key 失效 super(captchaStore, captchaEngine, minGuarantedStorageDelayInSeconds, maxCaptchaStoreSize, captchaStoreLoadBeforeGarbageCollection);
* }
* @param id
* @param response
* @return
* @throws CaptchaServiceException
*/
@Override
public Boolean validateResponseForID(String id, Object response) throws CaptchaServiceException {
if (StringUtils.isBlank(id)) {
return false;
}
boolean valid;
try {
Captcha captcha = this.store.getCaptcha(id);
if (null == captcha || captcha.hasGetChalengeBeenCalled()) {
return false;
}
valid = captcha.validateResponse(response);
} catch (Exception ex) {
LOGGER.warn("can not get captcha from redis");
valid = false;
}
this.getTimes().remove(id); @Override
if(valid) { public long getCustomStoreSize() {
addNumberOfCorrectResponse(1); return this.store.getSize();
} else { }
addNumberOfUncorrectResponse(1);
}
return valid; /**
* 重写校验, 需要将原来的 key 失效
*
* @param id
* @param response
* @return
* @throws CaptchaServiceException
*/
@Override
public Boolean validateResponseForID(String id, Object response) throws CaptchaServiceException {
if (StringUtils.isBlank(id)) {
return false;
} }
boolean valid;
/** try {
* 请求新的图形验证码 Captcha captcha = this.store.getCaptcha(id);
* if (null == captcha || captcha.hasGetChalengeBeenCalled()) {
* @param ID return false;
* @param locale }
* @return valid = captcha.validateResponse(response);
* @throws CaptchaServiceException } catch (Exception ex) {
*/ LOGGER.warn("can not get captcha from redis");
public Object getChallengeForID(String ID, Locale locale) throws CaptchaServiceException { valid = false;
Captcha captcha = this.generateAndStoreCaptcha(locale, ID);
Object challenge = this.getChallengeClone(captcha);
captcha.disposeChallenge();
return challenge;
} }
@Override this.getTimes().remove(id);
public void garbageCollectCaptchaStore() { if (valid) {
super.garbageCollectCaptchaStore(); addNumberOfCorrectResponse(1);
} else {
addNumberOfUncorrectResponse(1);
} }
return valid;
}
/**
* 请求新的图形验证码
*
* @param ID
* @param locale
* @return
* @throws CaptchaServiceException
*/
public Object getChallengeForID(String ID, Locale locale) throws CaptchaServiceException {
Captcha captcha = this.generateAndStoreCaptcha(locale, ID);
Object challenge = this.getChallengeClone(captcha);
captcha.disposeChallenge();
return challenge;
}
@Override
public void garbageCollectCaptchaStore() {
super.garbageCollectCaptchaStore();
}
} }
...@@ -26,87 +26,87 @@ import java.util.concurrent.TimeUnit; ...@@ -26,87 +26,87 @@ import java.util.concurrent.TimeUnit;
*/ */
public class RedisCaptchaStore implements CaptchaStore { public class RedisCaptchaStore implements CaptchaStore {
private static final Logger LOGGER = LoggerFactory.getLogger(RedisCaptchaStore.class); private static final Logger LOGGER = LoggerFactory.getLogger(RedisCaptchaStore.class);
private static final long DEFAULT_EXPIRED_IN = 120L; private static final long DEFAULT_EXPIRED_IN = 120L;
private static final TimeUnit DEFAULT_EXPIRED_TIMEUNIT = TimeUnit.SECONDS; private static final TimeUnit DEFAULT_EXPIRED_TIMEUNIT = TimeUnit.SECONDS;
protected RedisTemplate<String, String> stringRedisTemplate; protected RedisTemplate<String, String> stringRedisTemplate;
public RedisCaptchaStore(RedisTemplate<String, String> stringRedisTemplate) { public RedisCaptchaStore(RedisTemplate<String, String> stringRedisTemplate) {
super(); super();
this.stringRedisTemplate = stringRedisTemplate; this.stringRedisTemplate = stringRedisTemplate;
} }
@Override @Override
public boolean hasCaptcha(String captchaId) { public boolean hasCaptcha(String captchaId) {
return stringRedisTemplate.hasKey(buildCaptcharKey(captchaId)); return stringRedisTemplate.hasKey(buildCaptcharKey(captchaId));
} }
@Override @Override
public void storeCaptcha(String s, Captcha captcha) throws CaptchaServiceException { public void storeCaptcha(String s, Captcha captcha) throws CaptchaServiceException {
stringRedisTemplate.opsForValue().set(buildCaptcharKey(s), ((SimpleCaptcha) captcha).getResponse(), DEFAULT_EXPIRED_IN, DEFAULT_EXPIRED_TIMEUNIT); stringRedisTemplate.opsForValue().set(buildCaptcharKey(s), ((SimpleCaptcha) captcha).getResponse(), DEFAULT_EXPIRED_IN, DEFAULT_EXPIRED_TIMEUNIT);
} }
@Override @Override
public void storeCaptcha(String s, Captcha captcha, Locale locale) throws CaptchaServiceException { public void storeCaptcha(String s, Captcha captcha, Locale locale) throws CaptchaServiceException {
stringRedisTemplate.opsForValue().set(buildCaptcharKey(s), ((SimpleCaptcha) captcha).getResponse(), DEFAULT_EXPIRED_IN, DEFAULT_EXPIRED_TIMEUNIT); stringRedisTemplate.opsForValue().set(buildCaptcharKey(s), ((SimpleCaptcha) captcha).getResponse(), DEFAULT_EXPIRED_IN, DEFAULT_EXPIRED_TIMEUNIT);
} }
@Override @Override
public boolean removeCaptcha(String captchaId) { public boolean removeCaptcha(String captchaId) {
stringRedisTemplate.delete(buildCaptcharKey(captchaId)); stringRedisTemplate.delete(buildCaptcharKey(captchaId));
return true; return true;
} }
@Override @Override
public Captcha getCaptcha(String captchaId) throws CaptchaServiceException { public Captcha getCaptcha(String captchaId) throws CaptchaServiceException {
return getFromRedisThenDel(captchaId); return getFromRedisThenDel(captchaId);
} }
@Override @Override
public Locale getLocale(String captchaId) throws CaptchaServiceException { public Locale getLocale(String captchaId) throws CaptchaServiceException {
return Locale.CHINA; return Locale.CHINA;
} }
@Override @Override
public int getSize() { public int getSize() {
return getKeys().size(); return getKeys().size();
} }
@Override @Override
public Collection getKeys() { public Collection getKeys() {
return stringRedisTemplate.keys(Constants.REDIS_CAPTCHA_KEY_PATTERN); return stringRedisTemplate.keys(Constants.REDIS_CAPTCHA_KEY_PATTERN);
} }
@Override @Override
public void empty() { public void empty() {
} }
@Override @Override
public void initAndStart() { public void initAndStart() {
} }
@Override @Override
public void cleanAndShutdown() { public void cleanAndShutdown() {
} }
private Captcha getFromRedis(String captchaId) { private Captcha getFromRedis(String captchaId) {
Object value = stringRedisTemplate.opsForValue().get(buildCaptcharKey(captchaId)); Object value = stringRedisTemplate.opsForValue().get(buildCaptcharKey(captchaId));
return value != null ? new SimpleCaptcha(captchaId, String.valueOf(value)) : null; return value != null ? new SimpleCaptcha(captchaId, String.valueOf(value)) : null;
} }
private Captcha getFromRedisThenDel(String captchaId) { private Captcha getFromRedisThenDel(String captchaId) {
String captcharKey = buildCaptcharKey(captchaId); String captcharKey = buildCaptcharKey(captchaId);
Object value = stringRedisTemplate.opsForValue().get(captcharKey); Object value = stringRedisTemplate.opsForValue().get(captcharKey);
stringRedisTemplate.delete(captcharKey); stringRedisTemplate.delete(captcharKey);
return value != null ? new SimpleCaptcha(captchaId, String.valueOf(value)) : null; return value != null ? new SimpleCaptcha(captchaId, String.valueOf(value)) : null;
} }
protected String buildCaptcharKey(String captchaId) { protected String buildCaptcharKey(String captchaId) {
return Constants.REDIS_CAPTCHA_KEY + captchaId; return Constants.REDIS_CAPTCHA_KEY + captchaId;
} }
} }
...@@ -33,66 +33,65 @@ import java.util.Properties; ...@@ -33,66 +33,65 @@ import java.util.Properties;
@EnableTransactionManagement @EnableTransactionManagement
public class JpaConfig { public class JpaConfig {
@SafeValue("xyqb.data.mysql.jdbc-url") @SafeValue("xyqb.data.mysql.jdbc-url")
private String xyqbJdbcUrl; private String xyqbJdbcUrl;
@SafeValue("xyqb.data.mysql.password") @SafeValue("xyqb.data.mysql.password")
private String password; private String password;
@SafeValue("xyqb.data.mysql.user") @SafeValue("xyqb.data.mysql.user")
private String user; private String user;
@Value("${xyqb.data.mysql.max-pool-size}") @Value("${xyqb.data.mysql.max-pool-size}")
private Integer maxPoolSize; private Integer maxPoolSize;
@Bean @Bean
@DependsOn(value = "dataSource") @DependsOn(value = "dataSource")
public EntityManagerFactory entityManagerFactory() { public EntityManagerFactory entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean(); LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean();
entityManager.setDataSource(ApplicationContextHolder.getBean("dataSource")); entityManager.setDataSource(ApplicationContextHolder.getBean("dataSource"));
entityManager.setPackagesToScan("cn.quantgroup.xyqb"); entityManager.setPackagesToScan("cn.quantgroup.xyqb");
entityManager.setPersistenceUnitName("dataSource"); entityManager.setPersistenceUnitName("dataSource");
Properties properties = new Properties(); Properties properties = new Properties();
properties.put("hibernate.jdbc.batch_size", 30); properties.put("hibernate.jdbc.batch_size", 30);
properties.put("hibernate.order_inserts", true); properties.put("hibernate.order_inserts", true);
properties.put("hibernate.order_updates", true); properties.put("hibernate.order_updates", true);
entityManager.setJpaProperties(properties); entityManager.setJpaProperties(properties);
entityManager.setJpaVendorAdapter(jpaVendorAdapter()); entityManager.setJpaVendorAdapter(jpaVendorAdapter());
entityManager.afterPropertiesSet(); entityManager.afterPropertiesSet();
return entityManager.getObject(); return entityManager.getObject();
} }
@Bean @Bean
public DataSource dataSource() { public DataSource dataSource() {
HikariConfig config = new HikariConfig(); HikariConfig config = new HikariConfig();
config.setJdbcUrl(xyqbJdbcUrl); config.setJdbcUrl(xyqbJdbcUrl);
config.setPassword(password); config.setPassword(password);
config.setUsername(user); config.setUsername(user);
config.setMaximumPoolSize(maxPoolSize); config.setMaximumPoolSize(maxPoolSize);
config.setMinimumIdle(20); config.setMinimumIdle(20);
config.addDataSourceProperty("cachePrepStmts", "true"); config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250"); config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
return new HikariDataSource(config); return new HikariDataSource(config);
} }
private JpaVendorAdapter jpaVendorAdapter() { private JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter(); HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
hibernateJpaVendorAdapter.setShowSql(false); hibernateJpaVendorAdapter.setShowSql(false);
hibernateJpaVendorAdapter.setGenerateDdl(false); hibernateJpaVendorAdapter.setGenerateDdl(false);
hibernateJpaVendorAdapter.setDatabase(Database.MYSQL); hibernateJpaVendorAdapter.setDatabase(Database.MYSQL);
return hibernateJpaVendorAdapter; return hibernateJpaVendorAdapter;
} }
@Bean
@Bean public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { JpaTransactionManager transactionManager = new JpaTransactionManager();
JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(entityManagerFactory);
transactionManager.setEntityManagerFactory(entityManagerFactory); return transactionManager;
return transactionManager; }
}
} }
package cn.quantgroup.xyqb.config.http; package cn.quantgroup.xyqb.config.http;
import java.security.KeyManagementException; import com.fasterxml.jackson.annotation.JsonInclude;
import java.security.KeyStoreException; import com.fasterxml.jackson.databind.DeserializationFeature;
import java.security.NoSuchAlgorithmException; import com.fasterxml.jackson.databind.SerializationFeature;
import java.text.SimpleDateFormat;
import javax.net.ssl.SSLContext;
import org.apache.http.client.HttpRequestRetryHandler; import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.CookieSpecs; import org.apache.http.client.config.CookieSpecs;
import org.apache.http.config.Registry; import org.apache.http.config.Registry;
...@@ -37,9 +33,11 @@ import org.springframework.core.convert.converter.ConverterRegistry; ...@@ -37,9 +33,11 @@ import org.springframework.core.convert.converter.ConverterRegistry;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.web.filter.CharacterEncodingFilter; import org.springframework.web.filter.CharacterEncodingFilter;
import com.fasterxml.jackson.annotation.JsonInclude; import javax.net.ssl.SSLContext;
import com.fasterxml.jackson.databind.DeserializationFeature; import java.security.KeyManagementException;
import com.fasterxml.jackson.databind.SerializationFeature; import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
/** /**
* Created by Miraculous on 15/7/12. * Created by Miraculous on 15/7/12.
...@@ -47,94 +45,94 @@ import com.fasterxml.jackson.databind.SerializationFeature; ...@@ -47,94 +45,94 @@ import com.fasterxml.jackson.databind.SerializationFeature;
@Configuration @Configuration
public class HttpConfig { public class HttpConfig {
@Bean @Bean
public FilterRegistrationBean filterRegistrationBean() { public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean(); FilterRegistrationBean registrationBean = new FilterRegistrationBean();
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter(); CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
registrationBean.setFilter(characterEncodingFilter); registrationBean.setFilter(characterEncodingFilter);
characterEncodingFilter.setEncoding("UTF-8"); characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true); characterEncodingFilter.setForceEncoding(true);
registrationBean.setOrder(Integer.MIN_VALUE); registrationBean.setOrder(Integer.MIN_VALUE);
registrationBean.addUrlPatterns("/*"); registrationBean.addUrlPatterns("/*");
return registrationBean; return registrationBean;
} }
/** /**
* 该方法主要对对象json序列化产生影响,其功能如下: * 该方法主要对对象json序列化产生影响,其功能如下:
* 1. 禁用缩进输出 * 1. 禁用缩进输出
* 2. 日期格式排版 * 2. 日期格式排版
* 3. null被过滤掉 * 3. null被过滤掉
* 4. 将enum转为其ordinal * 4. 将enum转为其ordinal
* *
* @return Jackson2ObjectMapperBuilder * @return Jackson2ObjectMapperBuilder
*/ */
@Bean @Bean
public Jackson2ObjectMapperBuilder jacksonBuilder() { public Jackson2ObjectMapperBuilder jacksonBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.indentOutput(false) builder.indentOutput(false)
.dateFormat(new SimpleDateFormat("yyyy-MM-dd")) .dateFormat(new SimpleDateFormat("yyyy-MM-dd"))
.defaultViewInclusion(false) .defaultViewInclusion(false)
.serializationInclusion(JsonInclude.Include.NON_NULL) .serializationInclusion(JsonInclude.Include.NON_NULL)
.featuresToEnable(SerializationFeature.WRITE_ENUMS_USING_INDEX, .featuresToEnable(SerializationFeature.WRITE_ENUMS_USING_INDEX,
DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS); DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS);
return builder; return builder;
} }
// hack spring mvc. // hack spring mvc.
@Bean @Bean
public IntegerToEnumConverterFactory getIntegerToEnumConverterFactory( public IntegerToEnumConverterFactory getIntegerToEnumConverterFactory(
ConverterRegistry defaultConversionService, ConverterRegistry mvcConversionService, ConverterRegistry integrationConversionService) { ConverterRegistry defaultConversionService, ConverterRegistry mvcConversionService, ConverterRegistry integrationConversionService) {
IntegerToEnumConverterFactory factory = new IntegerToEnumConverterFactory(); IntegerToEnumConverterFactory factory = new IntegerToEnumConverterFactory();
defaultConversionService.removeConvertible(String.class, Enum.class); defaultConversionService.removeConvertible(String.class, Enum.class);
mvcConversionService.removeConvertible(String.class, Enum.class); mvcConversionService.removeConvertible(String.class, Enum.class);
integrationConversionService.removeConvertible(String.class, Enum.class); integrationConversionService.removeConvertible(String.class, Enum.class);
defaultConversionService.addConverterFactory(factory); defaultConversionService.addConverterFactory(factory);
mvcConversionService.addConverterFactory(factory); mvcConversionService.addConverterFactory(factory);
integrationConversionService.addConverterFactory(factory); integrationConversionService.addConverterFactory(factory);
return factory; return factory;
} }
@Bean(name = "httpClient") @Bean(name = "httpClient")
public CloseableHttpClient httpClient() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException { public CloseableHttpClient httpClient() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
// socket factory // socket factory
ConnectionSocketFactory plainSocketFactory = new PlainConnectionSocketFactory(); ConnectionSocketFactory plainSocketFactory = new PlainConnectionSocketFactory();
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial( SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(
null, (x509Certificates, authType) -> true).build(); null, (x509Certificates, authType) -> true).build();
LayeredConnectionSocketFactory sslSocketFactory = LayeredConnectionSocketFactory sslSocketFactory =
new SSLConnectionSocketFactory(sslContext, new AllowAllHostnameVerifier()); new SSLConnectionSocketFactory(sslContext, new AllowAllHostnameVerifier());
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create() Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", plainSocketFactory) .register("http", plainSocketFactory)
.register("https", sslSocketFactory).build(); .register("https", sslSocketFactory).build();
// cookie specification // cookie specification
Registry<CookieSpecProvider> cookieSpecProviderRegistry = RegistryBuilder.<CookieSpecProvider>create() Registry<CookieSpecProvider> cookieSpecProviderRegistry = RegistryBuilder.<CookieSpecProvider>create()
.register(CookieSpecs.BEST_MATCH, new BestMatchSpecFactory()) .register(CookieSpecs.BEST_MATCH, new BestMatchSpecFactory())
.register(CookieSpecs.BROWSER_COMPATIBILITY, new BrowserCompatSpecFactory()) .register(CookieSpecs.BROWSER_COMPATIBILITY, new BrowserCompatSpecFactory())
.register("easy", httpContext -> new BrowserCompatSpec() { .register("easy", httpContext -> new BrowserCompatSpec() {
public void validate(Cookie cookie, CookieOrigin origin) throws MalformedCookieException { public void validate(Cookie cookie, CookieOrigin origin) throws MalformedCookieException {
} }
}).build(); }).build();
// connection manager // connection manager
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
connectionManager.setMaxTotal(10000); connectionManager.setMaxTotal(10000);
connectionManager.setDefaultMaxPerRoute(1000); connectionManager.setDefaultMaxPerRoute(1000);
// retry handler // retry handler
HttpRequestRetryHandler retryHandler = new StandardHttpRequestRetryHandler(3, false); HttpRequestRetryHandler retryHandler = new StandardHttpRequestRetryHandler(3, false);
// keep alive strategy // keep alive strategy
ConnectionKeepAliveStrategy keepAliveStrategy = new DefaultConnectionKeepAliveStrategy(); ConnectionKeepAliveStrategy keepAliveStrategy = new DefaultConnectionKeepAliveStrategy();
// httpclient // httpclient
return HttpClients.custom() return HttpClients.custom()
.setConnectionManager(connectionManager) .setConnectionManager(connectionManager)
.setRetryHandler(retryHandler) .setRetryHandler(retryHandler)
.setKeepAliveStrategy(keepAliveStrategy) .setKeepAliveStrategy(keepAliveStrategy)
.setDefaultCookieSpecRegistry(cookieSpecProviderRegistry).build(); .setDefaultCookieSpecRegistry(cookieSpecProviderRegistry).build();
} }
} }
...@@ -7,33 +7,33 @@ import org.springframework.core.convert.converter.ConverterFactory; ...@@ -7,33 +7,33 @@ import org.springframework.core.convert.converter.ConverterFactory;
* Created by Miraculous on 15/7/12. * Created by Miraculous on 15/7/12.
*/ */
final class IntegerToEnumConverterFactory implements ConverterFactory<String, Enum> { final class IntegerToEnumConverterFactory implements ConverterFactory<String, Enum> {
IntegerToEnumConverterFactory() { IntegerToEnumConverterFactory() {
} }
public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) { public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) {
Class<?> enumType = targetType; Class<?> enumType = targetType;
while (enumType != null && !enumType.isEnum()) { while (enumType != null && !enumType.isEnum()) {
enumType = enumType.getSuperclass(); enumType = enumType.getSuperclass();
} }
if (enumType == null) { if (enumType == null) {
throw new IllegalArgumentException("The target type " + targetType.getName() + " does not refer to an enum"); throw new IllegalArgumentException("The target type " + targetType.getName() + " does not refer to an enum");
} else { } else {
return new IntegerToEnumConverterFactory.IntegerToEnum(enumType); return new IntegerToEnumConverterFactory.IntegerToEnum(enumType);
}
} }
}
private class IntegerToEnum<T extends Enum> implements Converter<String, T> { private class IntegerToEnum<T extends Enum> implements Converter<String, T> {
private final Class<T> enumType; private final Class<T> enumType;
public IntegerToEnum(Class<T> enumType) { public IntegerToEnum(Class<T> enumType) {
this.enumType = enumType; this.enumType = enumType;
} }
public T convert(String source) { public T convert(String source) {
T[] ts = enumType.getEnumConstants(); T[] ts = enumType.getEnumConstants();
int ordinal = Integer.parseInt(source); int ordinal = Integer.parseInt(source);
return ordinal < ts.length && ordinal >= 0 ? ts[ordinal] : null; return ordinal < ts.length && ordinal >= 0 ? ts[ordinal] : null;
}
} }
}
} }
\ No newline at end of file
...@@ -11,14 +11,15 @@ import java.sql.Timestamp; ...@@ -11,14 +11,15 @@ import java.sql.Timestamp;
* Created by Miraculous on 2016/12/29. * Created by Miraculous on 2016/12/29.
*/ */
public class Timestamp2LongConverter implements ObjectSerializer { public class Timestamp2LongConverter implements ObjectSerializer {
; ;
@Override
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException { @Override
Timestamp time = (Timestamp)object; public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
if (time == null) { Timestamp time = (Timestamp) object;
serializer.write(String.valueOf(0L)); if (time == null) {
} else { serializer.write(String.valueOf(0L));
serializer.write(String.valueOf(time.getTime())); } else {
} serializer.write(String.valueOf(time.getTime()));
} }
}
} }
package cn.quantgroup.xyqb.config.motan;
import com.weibo.api.motan.config.springsupport.AnnotationBean;
import com.weibo.api.motan.config.springsupport.BasicServiceConfigBean;
import com.weibo.api.motan.config.springsupport.ProtocolConfigBean;
import com.weibo.api.motan.config.springsupport.RegistryConfigBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Created by 11 on 2017/2/27.
*/
@Configuration
public class MotanConfig {
@Bean
public AnnotationBean motanAnnotationBean() {
AnnotationBean motanAnnotationBean = new AnnotationBean();
motanAnnotationBean.setPackage("cn.quantgroup.xyqb.controller.external.motan");
return motanAnnotationBean;
}
@Bean(name = "userMotan")
public ProtocolConfigBean protocolConfig1(
@Value("${protocol.isDefault}") Boolean isDefault, @Value("${protocol.name}") String name,
@Value("${protocol.contentLength}") int contentLength) {
ProtocolConfigBean config = new ProtocolConfigBean();
config.setDefault(isDefault);
config.setName(name);
config.setMaxContentLength(contentLength);
config.setMaxServerConnection(1000);
return config;
}
@Bean(name = "registryConfig")
public RegistryConfigBean registryConfig(@Value("${registry.protocol}") String registryProtocol,
@Value("${registry.address}") String registryAddress
) {
RegistryConfigBean config = new RegistryConfigBean();
config.setRegProtocol(registryProtocol);
config.setAddress(registryAddress);
return config;
}
@Bean
public BasicServiceConfigBean baseServiceConfig(@Value("${motan.port}") int motanPort,
@Value("${motan.user.group}") String userGroup,
@Value("${motan.user.module}") String userModule,
@Value("${motan.application:xyqbUserMotan}") String applicationName) {
BasicServiceConfigBean config = new BasicServiceConfigBean();
config.setExport("userMotan:" + motanPort);
config.setGroup(userGroup);
config.setVersion("1.0");
config.setAccessLog(true);
config.setShareChannel(true);
config.setModule(userModule);
config.setApplication(applicationName);
config.setRegistry("registryConfig");
return config;
}
}
package cn.quantgroup.xyqb.config.web; package cn.quantgroup.xyqb.config.web;
import cn.quantgroup.xyqb.interceptors.ChannelIdInterceptor; import cn.quantgroup.xyqb.interceptors.ChannelIdInterceptor;
import cn.quantgroup.xyqb.interceptors.IPWhiteListInterceptor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
...@@ -11,8 +13,12 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter ...@@ -11,8 +13,12 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
@Configuration @Configuration
public class InterceptorConfig extends WebMvcConfigurerAdapter { public class InterceptorConfig extends WebMvcConfigurerAdapter {
public void addInterceptors(InterceptorRegistry registry) { @Value("${configserver.disable}")
registry.addInterceptor(new ChannelIdInterceptor()).addPathPatterns("/**"); private Integer isDebug;
}
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new IPWhiteListInterceptor(isDebug)).addPathPatterns("/innerapi/**");
registry.addInterceptor(new ChannelIdInterceptor()).addPathPatterns("/**");
}
} }
...@@ -22,42 +22,41 @@ import javax.servlet.http.HttpServletRequest; ...@@ -22,42 +22,41 @@ import javax.servlet.http.HttpServletRequest;
@RestController @RestController
public class ExceptionHandlingController implements IBaseController { public class ExceptionHandlingController implements IBaseController {
private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionHandlingController.class); private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionHandlingController.class);
private static final JsonResult EXCEPTION_RESULT = new JsonResult("internal error", 500L, ""); private static final JsonResult EXCEPTION_RESULT = new JsonResult("internal error", 500L, "");
@ExceptionHandler(NullUserException.class) @ExceptionHandler(NullUserException.class)
@ResponseStatus(HttpStatus.UNAUTHORIZED) @ResponseStatus(HttpStatus.UNAUTHORIZED)
public JsonResult nullUserException(NullUserException nue) { public JsonResult nullUserException(NullUserException nue) {
return new JsonResult(nue.getMessage(), 401L, null); return new JsonResult(nue.getMessage(), 401L, null);
} }
/** /**
* 验证码登陆异常 * 验证码登陆异常
* *
* @param vce * @param vce
* @return * @return
*/ */
@ExceptionHandler(VerificationCodeErrorException.class) @ExceptionHandler(VerificationCodeErrorException.class)
public JsonResult verificationCodeErrorException(VerificationCodeErrorException vce) { public JsonResult verificationCodeErrorException(VerificationCodeErrorException vce) {
return JsonResult.buildErrorStateResult(vce.getMessage(), null, 1L); return JsonResult.buildErrorStateResult(vce.getMessage(), null, 1L);
} }
@ExceptionHandler(UserNotExistException.class) @ExceptionHandler(UserNotExistException.class)
@ResponseStatus(HttpStatus.UNAUTHORIZED) @ResponseStatus(HttpStatus.UNAUTHORIZED)
public JsonResult userNotExistException(UserNotExistException unee) { public JsonResult userNotExistException(UserNotExistException unee) {
return new JsonResult(unee.getMessage(), 401L, null); return new JsonResult(unee.getMessage(), 401L, null);
} }
@ExceptionHandler(Exception.class)
@ExceptionHandler(Exception.class) public JsonResult exceptionOccurs(Exception e) {
public JsonResult exceptionOccurs(Exception e) { HttpServletRequest request = getRequest();
HttpServletRequest request = getRequest(); String uri = request.getRequestURI();
String uri = request.getRequestURI(); String registerFrom = request.getParameter("registerFrom");
String registerFrom = request.getParameter("registerFrom"); LOGGER.error("接口异常 URI:{}, registerFrom:{}", uri, registerFrom, e);
LOGGER.error("接口异常 URI:{}, registerFrom:{}", uri, registerFrom, e); return EXCEPTION_RESULT;
return EXCEPTION_RESULT; }
}
} }
...@@ -7,56 +7,61 @@ import org.springframework.web.context.request.RequestContextHolder; ...@@ -7,56 +7,61 @@ import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import static cn.quantgroup.xyqb.session.XyqbSessionContextHolder.*;
import static cn.quantgroup.xyqb.session.XyqbSessionContextHolder.getXSession;
import static cn.quantgroup.xyqb.session.XyqbSessionContextHolder.getXSessionFromRedis;
/** /**
* Created by Miraculous on 15/7/5. * Created by Miraculous on 15/7/5.
*/ */
public interface IBaseController { public interface IBaseController {
default User getCurrentUser() { default User getCurrentUser() {
SessionStruct session = getXSession(); SessionStruct session = getXSession();
if (session == null) { if (session == null) {
return null; return null;
}
return getXSession().getValues().getUser();
}
default SessionStruct getSessionStruct() {
return getXSession();
} }
return getXSession().getValues().getUser();
}
default SessionStruct getSessionStruct() {
return getXSession();
}
default HttpServletRequest getRequest() { default SessionStruct getCurrentSessionFromRedis(){
ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder return getXSessionFromRedis();
.getRequestAttributes(); }
return attrs.getRequest();
}
default String getIp() {
HttpServletRequest request = getRequest();
String ip = request.getHeader("x-real-ip"); default HttpServletRequest getRequest() {
if (StringUtils.isEmpty(ip)) { ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder
ip = request.getRemoteAddr(); .getRequestAttributes();
} return attrs.getRequest();
}
//过滤反向代理的ip default String getIp() {
String[] stemps = ip.split(","); HttpServletRequest request = getRequest();
if (stemps.length >= 1) {
//得到第一个IP,即客户端真实IP
ip = stemps[0];
}
ip = ip.trim(); String ip = request.getHeader("x-real-ip");
if (ip.length() > 23) { if (StringUtils.isEmpty(ip)) {
ip = ip.substring(0, 23); ip = request.getRemoteAddr();
} }
return ip; //过滤反向代理的ip
String[] stemps = ip.split(",");
if (stemps.length >= 1) {
//得到第一个IP,即客户端真实IP
ip = stemps[0];
} }
default String getProtocol() { ip = ip.trim();
return StringUtils.startsWith(getRequest().getHeader("x-forwarded-proto"), "https") ? "https:" : "http:"; if (ip.length() > 23) {
ip = ip.substring(0, 23);
} }
return ip;
}
default String getProtocol() {
return StringUtils.startsWith(getRequest().getHeader("x-forwarded-proto"), "https") ? "https:" : "http:";
}
} }
...@@ -38,52 +38,54 @@ import java.util.UUID; ...@@ -38,52 +38,54 @@ import java.util.UUID;
@RequestMapping("/api") @RequestMapping("/api")
public class ImageCaptchaController implements IBaseController { public class ImageCaptchaController implements IBaseController {
private static final Logger LOGGER = LoggerFactory.getLogger(ImageCaptchaController.class); private static final Logger LOGGER = LoggerFactory.getLogger(ImageCaptchaController.class);
private static final String IMAGE_FORMAT_PNG = "png"; private static final String IMAGE_FORMAT_PNG = "png";
private static final String IMG_BASE64_PATTREN = "data:image/" + IMAGE_FORMAT_PNG + ";base64,%s"; private static final String IMG_BASE64_PATTREN = "data:image/" + IMAGE_FORMAT_PNG + ";base64,%s";
@Autowired @Autowired
@Qualifier("customCaptchaService") @Qualifier("customCaptchaService")
private AbstractManageableImageCaptchaService imageCaptchaService; private AbstractManageableImageCaptchaService imageCaptchaService;
@ModelAttribute("clientIp") @ModelAttribute("clientIp")
public String initClientIp() { public String initClientIp() {
return getIp(); return getIp();
} }
/** /**
* 获取验证码 * 获取验证码
* 默认匹配 GET /captcha, 提供4位数字和字母混合图片验证码 * 默认匹配 GET /captcha, 提供4位数字和字母混合图片验证码
* *
* @return * @return
*/ */
@RequestMapping(value = "/captcha") @RequestMapping(value = "/captcha")
public JsonResult fetchCaptcha(HttpServletRequest request, @ModelAttribute("clientIp") String clientIp) { public JsonResult fetchCaptcha(HttpServletRequest request, @ModelAttribute("clientIp") String clientIp) {
String imageId = UUID.randomUUID().toString(); String imageId = UUID.randomUUID().toString();
BufferedImage challenge = imageCaptchaService.getImageChallengeForID(Constants.IMAGE_CAPTCHA_KEY + imageId, request.getLocale()); BufferedImage challenge = imageCaptchaService.getImageChallengeForID(Constants.IMAGE_CAPTCHA_KEY + imageId, request.getLocale());
ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream(); ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
try { try {
boolean write = ImageIO.write(challenge, IMAGE_FORMAT_PNG, jpegOutputStream); boolean write = ImageIO.write(challenge, IMAGE_FORMAT_PNG, jpegOutputStream);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
return JsonResult.buildErrorStateResult("", "fail"); return JsonResult.buildErrorStateResult("", "fail");
} }
String imageBase64 = Base64.encodeBase64String(jpegOutputStream.toByteArray()); String imageBase64 = Base64.encodeBase64String(jpegOutputStream.toByteArray());
Map<String, String> data = new HashMap<>(); Map<String, String> data = new HashMap<>();
data.put("imageId", imageId); data.put("imageId", imageId);
data.put("image", String.format(IMG_BASE64_PATTREN, imageBase64)); data.put("image", String.format(IMG_BASE64_PATTREN, imageBase64));
return JsonResult.buildSuccessResult("", data); return JsonResult.buildSuccessResult("", data);
} }
/** 图片验证码验证*/ /**
@CaptchaValidator * 图片验证码验证
@RequestMapping("/verification_image_code") */
public JsonResult verificationImageCode() { @CaptchaValidator
return JsonResult.buildSuccessResult("", null); @RequestMapping("/verification_image_code")
} public JsonResult verificationImageCode() {
return JsonResult.buildSuccessResult("", null);
}
} }
package cn.quantgroup.xyqb.controller.external.motan;
import cn.quantgroup.xyqb.model.JsonResult;
import com.weibo.api.motan.common.MotanConstants;
import com.weibo.api.motan.util.MotanSwitcherUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/motan")
public class MotanController {
@RequestMapping("/enable/{key}")
public JsonResult reload(@PathVariable String key) {
if (StringUtils.equals(key, "b5140fb2-2c85-4b5a-abcf-3e97528014db")) {
MotanSwitcherUtil.setSwitcherValue(MotanConstants.REGISTRY_HEARTBEAT_SWITCHER, true);
return JsonResult.buildSuccessResult("加载成功", null);
}
return JsonResult.buildErrorStateResult("无效", null);
}
@RequestMapping("/disable/{key}")
public JsonResult disable(@PathVariable String key) {
if (StringUtils.equals(key, "b5140fb2-2c85-4b5a-abcf-3e97528014db")) {
MotanSwitcherUtil.setSwitcherValue(MotanConstants.REGISTRY_HEARTBEAT_SWITCHER, false);
return JsonResult.buildSuccessResult("加载成功", null);
}
return JsonResult.buildErrorStateResult("无效", null);
}
}
...@@ -42,7 +42,7 @@ import static cn.quantgroup.xyqb.constant.UserConstant.USER_ERROR_OR_PASSWORD_ER ...@@ -42,7 +42,7 @@ import static cn.quantgroup.xyqb.constant.UserConstant.USER_ERROR_OR_PASSWORD_ER
public class AppController implements IBaseController { public class AppController implements IBaseController {
private static final Logger LOGGER = LoggerFactory.getLogger(AppController.class); private static final Logger LOGGER = LoggerFactory.getLogger(AppController.class);
private final static Random random = new Random();
@Autowired @Autowired
private ISessionService sessionService; private ISessionService sessionService;
@Autowired @Autowired
...@@ -53,7 +53,6 @@ public class AppController implements IBaseController { ...@@ -53,7 +53,6 @@ public class AppController implements IBaseController {
private IUserRepository userRepository; private IUserRepository userRepository;
@Autowired @Autowired
private ISmsService smsService; private ISmsService smsService;
@Autowired @Autowired
private IUserDetailService userDetailService; private IUserDetailService userDetailService;
@Autowired @Autowired
...@@ -61,8 +60,6 @@ public class AppController implements IBaseController { ...@@ -61,8 +60,6 @@ public class AppController implements IBaseController {
@Autowired @Autowired
private IMerchantService merchantService; private IMerchantService merchantService;
private final static Random random = new Random();
/** /**
* 第三方用户登录 * 第三方用户登录
*/ */
...@@ -186,14 +183,16 @@ public class AppController implements IBaseController { ...@@ -186,14 +183,16 @@ public class AppController implements IBaseController {
user.setCreatedAt(currentTime); user.setCreatedAt(currentTime);
userRepository.saveAndFlush(user); userRepository.saveAndFlush(user);
if (registerFrom != 645L) { if (registerFrom != 645L && registerFrom != 900L) {
smsService.sendAfterRegister(phoneNo); smsService.sendAfterRegister(phoneNo);
LOGGER.info("第三方登录用户注册成功, registerFrom:{}, phoneNo:{}, 并且已发送短信通知", registerFrom, phoneNo); LOGGER.info("第三方登录用户注册成功, registerFrom:{}, phoneNo:{}, 并且已发送短信通知", registerFrom, phoneNo);
}else if(registerFrom == 900L){
smsService.sendAfterRegister(phoneNo,"123");
LOGGER.info("第三方(聚美)登录用户注册成功, registerFrom:{}, phoneNo:{},idNo:{},name:{} 并且已发送短信通知", registerFrom, phoneNo, idNo, name);
} }
if (StringUtils.isNotEmpty(idNo) && StringUtils.isNotEmpty(name)) { if (StringUtils.isNotEmpty(idNo) && StringUtils.isNotEmpty(name)) {
LOGGER.info("第三方登录用户,保存 UserDetail"); LOGGER.info("第三方登录用户,保存 UserDetail");
IdCardInfo cardInfo; IdCardInfo cardInfo;
try { try {
cardInfo = idCardService.getIdCardInfoWithExceptions(idNo); cardInfo = idCardService.getIdCardInfoWithExceptions(idNo);
......
package cn.quantgroup.xyqb.controller.external.user; package cn.quantgroup.xyqb.controller.external.user;
import cn.quantgroup.xyqb.controller.IBaseController;
import cn.quantgroup.xyqb.entity.*; import cn.quantgroup.xyqb.entity.*;
import cn.quantgroup.xyqb.entity.enumerate.*; import cn.quantgroup.xyqb.entity.enumerate.*;
import cn.quantgroup.xyqb.model.*; import cn.quantgroup.xyqb.model.*;
...@@ -15,6 +16,7 @@ import org.apache.commons.lang3.StringUtils; ...@@ -15,6 +16,7 @@ import org.apache.commons.lang3.StringUtils;
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.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
...@@ -23,13 +25,14 @@ import java.sql.Timestamp; ...@@ -23,13 +25,14 @@ import java.sql.Timestamp;
import java.text.ParseException; import java.text.ParseException;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* Created by Miraculous on 2016/12/19. * Created by Miraculous on 2016/12/19.
*/ */
@RestController @RestController
@RequestMapping("/innerapi") @RequestMapping("/innerapi")
public class InnerController { public class InnerController implements IBaseController {
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(InnerController.class); private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(InnerController.class);
...@@ -72,6 +75,22 @@ public class InnerController { ...@@ -72,6 +75,22 @@ public class InnerController {
return JsonResult.buildSuccessResult("", userRet); return JsonResult.buildSuccessResult("", userRet);
} }
@RequestMapping("/user/getPhoneByUserIds")
public JsonResult findByIds(@RequestParam(value = "userIds") String userIdsString) {
LOGGER.info("批量查询用户的手机号列表, userIdsString:" + userIdsString);
if (StringUtils.isEmpty(userIdsString)) {
return JsonResult.buildErrorStateResult(null, null);
}
List<Long> userIds = JSONObject.parseObject(userIdsString, new TypeReference<List<Long>>() {
});
if(!CollectionUtils.isEmpty(userIds) && userIds.size()<=500) {
Map<Long, String> userIdAndPhoneMap = userService.findPhoneByIdsInDb(userIds);
return JsonResult.buildSuccessResult("", userIdAndPhoneMap);
}else {
return JsonResult.buildErrorStateResult("批量查询每次最多进行500条用户信息的查询",null);
}
}
@RequestMapping("/user/save") @RequestMapping("/user/save")
public JsonResult saveUser( public JsonResult saveUser(
String phoneNo, Long registeredFrom, Long createdAt, Long updatedAt, String phoneNo, Long registeredFrom, Long createdAt, Long updatedAt,
...@@ -240,6 +259,12 @@ public class InnerController { ...@@ -240,6 +259,12 @@ public class InnerController {
return JsonResult.buildErrorStateResult(null, null); return JsonResult.buildErrorStateResult(null, null);
} }
Timestamp now = new Timestamp(System.currentTimeMillis()); Timestamp now = new Timestamp(System.currentTimeMillis());
convertContactList(userId, contacts, now);
List<Contact> result = contactService.save(contacts);
return JsonResult.buildSuccessResult(null, ContactRet.contacts2ContactRets(result));
}
private void convertContactList(Long userId, List<Contact> contacts, Timestamp now) {
for (Contact c : contacts) { for (Contact c : contacts) {
c.setId(null); c.setId(null);
c.setUserId(userId); c.setUserId(userId);
...@@ -247,8 +272,6 @@ public class InnerController { ...@@ -247,8 +272,6 @@ public class InnerController {
c.setCreatedAt(now); c.setCreatedAt(now);
c.setUpdateAt(now); c.setUpdateAt(now);
} }
List<Contact> result = contactService.save(contacts);
return JsonResult.buildSuccessResult(null, ContactRet.contacts2ContactRets(result));
} }
@RequestMapping("/address/search/user_id") @RequestMapping("/address/search/user_id")
...@@ -300,13 +323,13 @@ public class InnerController { ...@@ -300,13 +323,13 @@ public class InnerController {
return JsonResult.buildErrorStateResult("用户ID不能为空", null); return JsonResult.buildErrorStateResult("用户ID不能为空", null);
} }
UserExtInfo info = userExtInfoService.findByUserId(userId); UserExtInfo info = userExtInfoService.findByUserId(userId);
Timestamp now = new Timestamp(System.currentTimeMillis());
if (info == null) { if (info == null) {
Timestamp now = new Timestamp(System.currentTimeMillis());
info = new UserExtInfo(); info = new UserExtInfo();
info.setUserId(userId); info.setUserId(userId);
info.setCreatedAt(now); info.setCreatedAt(now);
info.setUpdateAt(now);
} }
info.setUpdateAt(now);
if (incomeEnum != null) { if (incomeEnum != null) {
info.setIncomeEnum(incomeEnum); info.setIncomeEnum(incomeEnum);
} }
...@@ -337,6 +360,8 @@ public class InnerController { ...@@ -337,6 +360,8 @@ public class InnerController {
@RequestMapping("/user_detail/search_list") @RequestMapping("/user_detail/search_list")
public JsonResult searchUserDetailList(String name, String phoneNo, String idNo) { public JsonResult searchUserDetailList(String name, String phoneNo, String idNo) {
LOGGER.info("searchUserDetailList ,param.name:{},phone:{},idNo:{},ip:{}",name,phoneNo,idNo,getIp());
if (StringUtils.isBlank(name) && StringUtils.isBlank(phoneNo) && StringUtils.isBlank(idNo)) { if (StringUtils.isBlank(name) && StringUtils.isBlank(phoneNo) && StringUtils.isBlank(idNo)) {
return JsonResult.buildErrorStateResult("至少必须满足一个条件不为空", null); return JsonResult.buildErrorStateResult("至少必须满足一个条件不为空", null);
} }
...@@ -353,7 +378,7 @@ public class InnerController { ...@@ -353,7 +378,7 @@ public class InnerController {
if (userExtInfo == null) { if (userExtInfo == null) {
return JsonResult.buildErrorStateResult(null, null); return JsonResult.buildErrorStateResult(null, null);
} }
return JsonResult.buildSuccessResult("success", UserExtInfoRet.getUserExtInfoRet(userExtInfo)); return JsonResult.buildSuccessResult(null, UserExtInfoRet.getUserExtInfoRet(userExtInfo));
} }
@RequestMapping("/user/query/openId") @RequestMapping("/user/query/openId")
...@@ -439,4 +464,29 @@ public class InnerController { ...@@ -439,4 +464,29 @@ public class InnerController {
return JsonResult.buildSuccessResult(null, UserSpouseRet.getUserSpouseRet(userSpouse)); return JsonResult.buildSuccessResult(null, UserSpouseRet.getUserSpouseRet(userSpouse));
} }
/**
* 重置密码接口,供内部人员使用(例如绝影)
* @param key
* @param phone
* @return
*/
@RequestMapping("/user/password/reset/{key}/{phone}")
public JsonResult resetPassword(@PathVariable("key")String key,@PathVariable("phone")String phone) {
LOGGER.info("密码重置请求,phone:[{}]",phone);
if(StringUtils.isBlank(key)){
return JsonResult.buildErrorStateResult("用户密码重置失败.", null);
}
if(!"ecf75c1f-2ccb-4661-8e4b-2874c0f45a2b".equalsIgnoreCase(key)){
LOGGER.error("密码重置失败,key错误!@!,phone:[{}]", phone);
return JsonResult.buildErrorStateResult("用户密码重置失败.", null);
}
try {
userService.resetPassword(phone, "123456"); //默认重置的密码是123456
return JsonResult.buildSuccessResult("用户密码已重置.", "null");
}catch (Exception e){
LOGGER.error("密码重置失败,phone[{}],err:[{}]",phone, e);
}
return JsonResult.buildErrorStateResult("用户密码重置失败.", null);
}
} }
\ No newline at end of file
...@@ -4,7 +4,6 @@ import cn.quantgroup.xyqb.entity.User; ...@@ -4,7 +4,6 @@ import cn.quantgroup.xyqb.entity.User;
import cn.quantgroup.xyqb.entity.UserDetail; import cn.quantgroup.xyqb.entity.UserDetail;
import cn.quantgroup.xyqb.model.JsonResult; import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.model.UserModel; import cn.quantgroup.xyqb.model.UserModel;
import cn.quantgroup.xyqb.repository.IUserDetailRepository;
import cn.quantgroup.xyqb.service.user.IUserDetailService; import cn.quantgroup.xyqb.service.user.IUserDetailService;
import cn.quantgroup.xyqb.service.user.IUserService; import cn.quantgroup.xyqb.service.user.IUserService;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
...@@ -22,73 +21,73 @@ import org.springframework.web.bind.annotation.RestController; ...@@ -22,73 +21,73 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/api/sync") @RequestMapping("/api/sync")
public class SyncUserController { public class SyncUserController {
@Autowired @Autowired
private IUserService userService; private IUserService userService;
@Autowired @Autowired
private IUserDetailService userDetailService; private IUserDetailService userDetailService;
/*@Autowired /*@Autowired
private IUserDetailRepository userDetailRepository;*/ private IUserDetailRepository userDetailRepository;*/
@Autowired @Autowired
@Qualifier("stringRedisTemplate") @Qualifier("stringRedisTemplate")
private RedisTemplate<String, String> stringRedisTemplate; private RedisTemplate<String, String> stringRedisTemplate;
@RequestMapping("/user") @RequestMapping("/user")
public JsonResult fetchUser(String key, String phoneNo) { public JsonResult fetchUser(String key, String phoneNo) {
if (StringUtils.isEmpty(key) || !"abc1234".equals(key)) { if (StringUtils.isEmpty(key) || !"abc1234".equals(key)) {
return JsonResult.buildErrorStateResult(null, null); return JsonResult.buildErrorStateResult(null, null);
} }
if (StringUtils.isEmpty(phoneNo)) { if (StringUtils.isEmpty(phoneNo)) {
return JsonResult.buildErrorStateResult(null, null); return JsonResult.buildErrorStateResult(null, null);
} }
User user = userService.findByPhoneInDb(phoneNo); User user = userService.findByPhoneInDb(phoneNo);
if (null == user) { if (null == user) {
return JsonResult.buildErrorStateResult(null, null); return JsonResult.buildErrorStateResult(null, null);
} }
UserDetail detail = userDetailService.findByUserId(user.getId()); UserDetail detail = userDetailService.findByUserId(user.getId());
if (null == detail) { if (null == detail) {
// FIXME: 16/4/15 前期不对身份证强制要求.后期对修改 // FIXME: 16/4/15 前期不对身份证强制要求.后期对修改
// return JsonResult.buildErrorStateResult(null, null); // return JsonResult.buildErrorStateResult(null, null);
}
UserModel userModel = new UserModel(user, detail);
return JsonResult.buildSuccessResult(null, userModel);
} }
UserModel userModel = new UserModel(user, detail);
return JsonResult.buildSuccessResult(null, userModel);
}
@RequestMapping("/save_detail") @RequestMapping("/save_detail")
public JsonResult saveUserDetail(String key, UserDetail userDetail) { public JsonResult saveUserDetail(String key, UserDetail userDetail) {
if (StringUtils.isEmpty(key) || !"abc1234".equals(key)) { if (StringUtils.isEmpty(key) || !"abc1234".equals(key)) {
return JsonResult.buildErrorStateResult(null, null); return JsonResult.buildErrorStateResult(null, null);
} }
String phoneNo = userDetail.getPhoneNo(); String phoneNo = userDetail.getPhoneNo();
User user = userService.findByPhoneWithCache(phoneNo); User user = userService.findByPhoneWithCache(phoneNo);
if (null == user) { if (null == user) {
return JsonResult.buildErrorStateResult(null, null); return JsonResult.buildErrorStateResult(null, null);
}
userDetail.setId(null);
userDetail.setUserId(user.getId());
userDetailService.saveUserDetail(userDetail);
return JsonResult.buildSuccessResult(null, null);
} }
userDetail.setId(null);
userDetail.setUserId(user.getId());
userDetailService.saveUserDetail(userDetail);
return JsonResult.buildSuccessResult(null, null);
}
@RequestMapping("/user_uuid") @RequestMapping("/user_uuid")
public JsonResult fetchUserByUuid(String key, String uuid) { public JsonResult fetchUserByUuid(String key, String uuid) {
if (StringUtils.isEmpty(key) || !"abc1234".equals(key)) { if (StringUtils.isEmpty(key) || !"abc1234".equals(key)) {
return JsonResult.buildErrorStateResult(null, null); return JsonResult.buildErrorStateResult(null, null);
} }
if (StringUtils.isEmpty(uuid)) { if (StringUtils.isEmpty(uuid)) {
return JsonResult.buildErrorStateResult(null, null); return JsonResult.buildErrorStateResult(null, null);
} }
User user = userService.findByUuidWithCache(uuid); User user = userService.findByUuidWithCache(uuid);
if (null == user) { if (null == user) {
return JsonResult.buildErrorStateResult(null, null); return JsonResult.buildErrorStateResult(null, null);
} }
UserDetail detail = userDetailService.findByUserId(user.getId()); UserDetail detail = userDetailService.findByUserId(user.getId());
if (null == detail) { if (null == detail) {
// FIXME: 16/4/15 前期不对身份证强制要求.后期对修改 // FIXME: 16/4/15 前期不对身份证强制要求.后期对修改
// return JsonResult.buildErrorStateResult(null, null); // return JsonResult.buildErrorStateResult(null, null);
}
UserModel userModel = new UserModel(user, detail);
return JsonResult.buildSuccessResult(null, userModel);
} }
UserModel userModel = new UserModel(user, detail);
return JsonResult.buildSuccessResult(null, userModel);
}
} }
...@@ -18,45 +18,45 @@ import org.springframework.web.bind.annotation.RestController; ...@@ -18,45 +18,45 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/api") @RequestMapping("/api")
public class UserApiController { public class UserApiController {
private static final Logger LOGGER = LoggerFactory.getLogger(UserApiController.class); private static final Logger LOGGER = LoggerFactory.getLogger(UserApiController.class);
@Autowired @Autowired
private IUserApiService userApiService; private IUserApiService userApiService;
@Autowired @Autowired
private IUserService userService; private IUserService userService;
@RequestMapping("/user/check") @RequestMapping("/user/check")
public JsonResult userImportCheck(String phoneNo, String registerFrom) { public JsonResult userImportCheck(String phoneNo, String registerFrom) {
if ("244".equals(registerFrom)) { if ("244".equals(registerFrom)) {
LOGGER.info("[user_import_check]用户导入检查拒绝。phoneNo=[{}], registerFrom=[{}]", phoneNo, registerFrom); LOGGER.info("[user_import_check]用户导入检查拒绝。phoneNo=[{}], registerFrom=[{}]", phoneNo, registerFrom);
return JsonResult.buildErrorStateResult("用户导入检查拒绝", false); return JsonResult.buildErrorStateResult("用户导入检查拒绝", false);
}
if (StringUtils.isEmpty(phoneNo) || StringUtils.isEmpty(registerFrom)) {
LOGGER.error("[user_import_check]检查传入的参数,参数不全。phoneNo=[{}], registerFrom=[{}]", phoneNo, registerFrom);
return JsonResult.buildErrorStateResult("检查传入的参数,参数不全。", null);
}
boolean checkPassed = userApiService.userImportCheck(phoneNo);
if (checkPassed) {
LOGGER.info("[user_import_check]用户可以导入。phoneNo=[{}], registerFrom=[{}]", phoneNo, registerFrom);
return JsonResult.buildSuccessResult("用户可以导入", checkPassed);
}
LOGGER.info("[user_import_check]用户导入检查拒绝。phoneNo=[{}], registerFrom=[{}]", phoneNo, registerFrom);
return JsonResult.buildErrorStateResult("用户导入检查拒绝", checkPassed);
} }
if (StringUtils.isEmpty(phoneNo) || StringUtils.isEmpty(registerFrom)) {
LOGGER.error("[user_import_check]检查传入的参数,参数不全。phoneNo=[{}], registerFrom=[{}]", phoneNo, registerFrom);
return JsonResult.buildErrorStateResult("检查传入的参数,参数不全。", null);
}
boolean checkPassed = userApiService.userImportCheck(phoneNo);
if (checkPassed) {
LOGGER.info("[user_import_check]用户可以导入。phoneNo=[{}], registerFrom=[{}]", phoneNo, registerFrom);
return JsonResult.buildSuccessResult("用户可以导入", checkPassed);
}
LOGGER.info("[user_import_check]用户导入检查拒绝。phoneNo=[{}], registerFrom=[{}]", phoneNo, registerFrom);
return JsonResult.buildErrorStateResult("用户导入检查拒绝", checkPassed);
}
@RequestMapping("/user/is_passwd_set") @RequestMapping("/user/is_passwd_set")
public JsonResult isPasswordSet(String key, String phoneNo) { public JsonResult isPasswordSet(String key, String phoneNo) {
if (!"abc1234".equals(key) || StringUtils.isEmpty(phoneNo)) { if (!"abc1234".equals(key) || StringUtils.isEmpty(phoneNo)) {
return JsonResult.buildErrorStateResult(null, null); return JsonResult.buildErrorStateResult(null, null);
} }
User user = userService.findByPhoneWithCache(phoneNo); User user = userService.findByPhoneWithCache(phoneNo);
if (null == user) { if (null == user) {
return JsonResult.buildErrorStateResult(null, null); return JsonResult.buildErrorStateResult(null, null);
} }
if (StringUtils.length(user.getPassword()) == 32) { if (StringUtils.length(user.getPassword()) == 32) {
return JsonResult.buildSuccessResult(null, null); return JsonResult.buildSuccessResult(null, null);
}
return JsonResult.buildErrorStateResult(null, null, 2L);
} }
return JsonResult.buildErrorStateResult(null, null, 2L);
}
} }
...@@ -13,11 +13,11 @@ import java.io.PrintWriter; ...@@ -13,11 +13,11 @@ import java.io.PrintWriter;
@RequestMapping("/") @RequestMapping("/")
public class WechatVerifyController { public class WechatVerifyController {
@RequestMapping("/MP_verify_AWiagUn4kZiwmTt0.txt") @RequestMapping("/MP_verify_AWiagUn4kZiwmTt0.txt")
public void verifyWechat(HttpServletResponse response) throws Exception { public void verifyWechat(HttpServletResponse response) throws Exception {
response.setContentType("plain/text"); response.setContentType("plain/text");
PrintWriter writer = response.getWriter(); PrintWriter writer = response.getWriter();
writer.print("AWiagUn4kZiwmTt0"); writer.print("AWiagUn4kZiwmTt0");
writer.close(); writer.close();
} }
} }
package cn.quantgroup.xyqb.controller.internal.login; package cn.quantgroup.xyqb.controller.internal.login;
import cn.quantgroup.xyqb.controller.IBaseController; import cn.quantgroup.xyqb.controller.IBaseController;
import cn.quantgroup.xyqb.entity.User;
import cn.quantgroup.xyqb.model.JsonResult; import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.model.UserRet; import cn.quantgroup.xyqb.model.UserRet;
import cn.quantgroup.xyqb.model.session.LoginInfo; import cn.quantgroup.xyqb.model.session.LoginInfo;
import cn.quantgroup.xyqb.model.session.SessionStruct; import cn.quantgroup.xyqb.model.session.SessionStruct;
import cn.quantgroup.xyqb.service.http.IHttpService;
import cn.quantgroup.xyqb.service.user.IUserService;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.ImmutableMap;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; 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.util.Map;
/** /**
* Created by Miraculous on 2016/12/30. * Created by Miraculous on 2016/12/30.
*/ */
@RestController @RestController
@RequestMapping("/auth") @RequestMapping("/auth")
@Slf4j
public class AuthInfoController implements IBaseController { public class AuthInfoController implements IBaseController {
@RequestMapping("/info/login")
public JsonResult loginInfo() { @Value("${xyqb.auth.url}")
SessionStruct sessionStruct = getSessionStruct(); private String xyqbAuthUrl;
LoginInfo loginInfo = new LoginInfo();
loginInfo.setUser(UserRet.getUserRet(sessionStruct.getValues().getUser())); @Autowired
loginInfo.setToken(sessionStruct.getSid()); private IHttpService httpService;
LoginInfo.LoginContext context = new LoginInfo.LoginContext();
context.setChannelId(sessionStruct.getValues().getLoginProperties().getChannelId()); @Autowired
context.setCreatedFrom(sessionStruct.getValues().getLoginProperties().getCreatedFrom()); private IUserService userService;
context.setAppChannel(sessionStruct.getValues().getLoginProperties().getAppChannel());
loginInfo.setLoginContext(context);
return JsonResult.buildSuccessResult("", loginInfo); @RequestMapping("/info/login")
public JsonResult loginInfo() {
SessionStruct sessionStruct = getCurrentSessionFromRedis();
if(null != sessionStruct) {
log.info("从用户中心获取到了用户登录信息:phone:[{}]",sessionStruct.getValues().getUser().getPhoneNo());
LoginInfo loginInfo = new LoginInfo();
loginInfo.setUser(UserRet.getUserRet(sessionStruct.getValues().getUser()));
loginInfo.setToken(sessionStruct.getSid());
LoginInfo.LoginContext context = new LoginInfo.LoginContext();
context.setChannelId(sessionStruct.getValues().getLoginProperties().getChannelId());
context.setCreatedFrom(sessionStruct.getValues().getLoginProperties().getCreatedFrom());
context.setAppChannel(sessionStruct.getValues().getLoginProperties().getAppChannel());
loginInfo.setLoginContext(context);
return JsonResult.buildSuccessResult("", loginInfo); //有ThreadLocal不释放的问题,不可再使用原来方式了
}else {
// 函谷关去查token 返回值高仿
log.info("去向函谷关查询用户信息");
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String token = request.getHeader("x-auth-token");
if(StringUtils.isBlank(token) ||token.length() != 36){
return JsonResult.buildErrorStateResult("用户未登录",null);
}
String checkUrl = xyqbAuthUrl+"/innerapi/is_login";
ImmutableMap<String, String> headMap = ImmutableMap.of("x-auth-token", token);
String response = httpService.get(checkUrl, headMap, null);
log.info("去向函谷关查询用户信息,response:[{}]",response);
JsonResult result = JSONObject.parseObject(response, JsonResult.class);
if (result == null || !"0000".equals(result.getCode()) || !"0000".equals(result.getBusinessCode())) {
return JsonResult.buildErrorStateResult("用户未登录",null);
}
String phoneNo = ((Map<String, String>) result.getData()).get("phoneNo");
User user = userService.findByPhoneWithCache(phoneNo);
LoginInfo loginInfo = new LoginInfo();
loginInfo.setUser(UserRet.getUserRet(user));
loginInfo.setToken(token);
LoginInfo.LoginContext context = new LoginInfo.LoginContext();
context.setChannelId(null);
context.setCreatedFrom(user.getRegisteredFrom());
context.setAppChannel("");
loginInfo.setLoginContext(context);
return JsonResult.buildSuccessResult("", loginInfo);
} }
}
} }
...@@ -13,32 +13,32 @@ import java.sql.Timestamp; ...@@ -13,32 +13,32 @@ import java.sql.Timestamp;
@Data @Data
@Entity @Entity
@Table(name = "address", uniqueConstraints = @UniqueConstraint(columnNames = "user_id")) @Table(name = "address", uniqueConstraints = @UniqueConstraint(columnNames = "user_id"))
public class Address implements Serializable{ public class Address implements Serializable {
private static final long serialVersionUID = -1L; private static final long serialVersionUID = -1L;
@Id @Id
@Column(name = "id") @Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; private Long id;
@Column(name = "user_id") @Column(name = "user_id")
private Long userId; private Long userId;
@Column(name = "province_code") @Column(name = "province_code")
private Long provinceCode; private Long provinceCode;
@Column(name = "province") @Column(name = "province")
private String province; private String province;
@Column(name = "city_code") @Column(name = "city_code")
private Long cityCode; private Long cityCode;
@Column(name = "city") @Column(name = "city")
private String city; private String city;
@Column(name = "districtCode") @Column(name = "districtCode")
private Long districtCode; private Long districtCode;
@Column(name = "district") @Column(name = "district")
private String district; private String district;
@Column(name = "address") @Column(name = "address")
private String address; private String address;
@Column(name = "created_at") @Column(name = "created_at")
private Timestamp createdAt; private Timestamp createdAt;
@Column(name = "updated_at") @Column(name = "updated_at")
private Timestamp updateAt; private Timestamp updateAt;
} }
This diff is collapsed.
This diff is collapsed.
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