Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
X
xyqb-user2
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
head_group
xyqb-user2
Commits
cdb2fe25
Commit
cdb2fe25
authored
Dec 01, 2017
by
技术部-任文超
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
解决SECBUGS:
http://jira.quantgroup.cn/browse/SECBUGS-9,http://jira.quantgroup.cn/browse/SECBUGS-14
parent
d457a892
Changes
21
Show whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
108 additions
and
472 deletions
+108
-472
Constants.java
src/main/java/cn/quantgroup/xyqb/Constants.java
+0
-1
IpValidator.java
...ava/cn/quantgroup/xyqb/aspect/accessable/IpValidator.java
+1
-1
IpValidatorAdvisor.java
...quantgroup/xyqb/aspect/accessable/IpValidatorAdvisor.java
+0
-59
CaptchaFineteValidator.java
...uantgroup/xyqb/aspect/captcha/CaptchaFineteValidator.java
+0
-15
CaptchaFiniteValidateAdvisor.java
...oup/xyqb/aspect/captcha/CaptchaFiniteValidateAdvisor.java
+4
-3
CaptchaNewValidateAdvisor.java
...tgroup/xyqb/aspect/captcha/CaptchaNewValidateAdvisor.java
+4
-21
CaptchaValidateAdvisor.java
...uantgroup/xyqb/aspect/captcha/CaptchaValidateAdvisor.java
+2
-1
PasswordFreeAccessValidatorValidateAdvisor.java
...ect/limit/PasswordFreeAccessValidatorValidateAdvisor.java
+0
-130
PasswordErrorFiniteValidateAdvisor.java
.../xyqb/aspect/lock/PasswordErrorFiniteValidateAdvisor.java
+12
-31
PasswordFineteValidator.java
.../quantgroup/xyqb/aspect/lock/PasswordFineteValidator.java
+0
-15
OneTimeTokenValidateAdvisor.java
...tgroup/xyqb/aspect/token/OneTimeTokenValidateAdvisor.java
+0
-85
OneTimeTokenValidator.java
...n/quantgroup/xyqb/aspect/token/OneTimeTokenValidator.java
+0
-15
IBaseController.java
...n/java/cn/quantgroup/xyqb/controller/IBaseController.java
+2
-19
InnerController.java
...tgroup/xyqb/controller/external/user/InnerController.java
+5
-5
SmsController.java
...uantgroup/xyqb/controller/internal/sms/SmsController.java
+8
-8
OneTimeTokenController.java
...yqb/controller/internal/token/OneTimeTokenController.java
+0
-44
UserController.java
...ntgroup/xyqb/controller/internal/user/UserController.java
+6
-7
IPWhiteListInterceptor.java
.../quantgroup/xyqb/interceptors/IPWhiteListInterceptor.java
+3
-1
IPUtil.java
src/main/java/cn/quantgroup/xyqb/util/IPUtil.java
+61
-7
LoginForH5Tests.java
src/test/java/login/LoginForH5Tests.java
+0
-2
OneTimeTokenTests.java
src/test/java/token/OneTimeTokenTests.java
+0
-2
No files found.
src/main/java/cn/quantgroup/xyqb/Constants.java
View file @
cdb2fe25
...
@@ -39,7 +39,6 @@ public interface Constants {
...
@@ -39,7 +39,6 @@ public interface Constants {
Long
VERIFICATION_CODE_FINITE_COUNT
=
3L
;
Long
VERIFICATION_CODE_FINITE_COUNT
=
3L
;
String
X_AUTH_TOKEN
=
"x-auth-token"
;
String
X_AUTH_TOKEN
=
"x-auth-token"
;
String
ONE_TIME_TOKEN
=
"oneTimeToken"
;
// -- Start -- IPV4安全策略常量组
// -- Start -- IPV4安全策略常量组
String
REDIS_PASSWORD_ERROR_COUNT
=
"password_error_count:"
;
String
REDIS_PASSWORD_ERROR_COUNT
=
"password_error_count:"
;
...
...
src/main/java/cn/quantgroup/xyqb/aspect/accessable/IpValidator.java
View file @
cdb2fe25
...
@@ -3,7 +3,7 @@ package cn.quantgroup.xyqb.aspect.accessable;
...
@@ -3,7 +3,7 @@ package cn.quantgroup.xyqb.aspect.accessable;
import
java.lang.annotation.*
;
import
java.lang.annotation.*
;
/**
/**
*
Created by 11 on 2017/3/23.
*
Ip白名单检验标记
*/
*/
@Documented
@Documented
@Target
(
ElementType
.
METHOD
)
@Target
(
ElementType
.
METHOD
)
...
...
src/main/java/cn/quantgroup/xyqb/aspect/accessable/IpValidatorAdvisor.java
deleted
100644 → 0
View file @
d457a892
package
cn
.
quantgroup
.
xyqb
.
aspect
.
accessable
;
import
cn.quantgroup.xyqb.model.JsonResult
;
import
cn.quantgroup.xyqb.util.IPUtil
;
import
org.aspectj.lang.ProceedingJoinPoint
;
import
org.aspectj.lang.annotation.Around
;
import
org.aspectj.lang.annotation.Aspect
;
import
org.aspectj.lang.annotation.Pointcut
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.stereotype.Component
;
import
org.springframework.web.context.request.RequestContextHolder
;
import
org.springframework.web.context.request.ServletRequestAttributes
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.xml.crypto.dsig.keyinfo.PGPData
;
/**
* Created by 11 on 2017/3/23.
*/
@Aspect
@Component
public
class
IpValidatorAdvisor
{
private
static
final
Logger
LOGGER
=
LoggerFactory
.
getLogger
(
IpValidatorAdvisor
.
class
);
/*@Value("${config.accessable}")
private boolean accessable;*/
@Pointcut
(
"@annotation(cn.quantgroup.xyqb.aspect.accessable.IpValidator)"
)
private
void
needIpValidate
()
{
}
@Around
(
"needIpValidate()"
)
private
Object
doCapchaValidate
(
ProceedingJoinPoint
pjp
)
throws
Throwable
{
HttpServletRequest
request
=
((
ServletRequestAttributes
)
RequestContextHolder
.
getRequestAttributes
()).
getRequest
();
String
ip
=
IPUtil
.
getRemoteIP
(
request
);
LOGGER
.
info
(
"获取ip地址:"
+
ip
);
if
(
ip
.
startsWith
(
"172"
)||
ip
.
startsWith
(
"192"
)){
return
pjp
.
proceed
();
}
else
{
LOGGER
.
error
(
"非法ip:{}"
,
ip
);
return
JsonResult
.
buildErrorStateResult
(
"非法ip"
,
null
);
}
/*HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String ip = IPUtil.getRemoteIP(request);
if(accessable) {
return pjp.proceed();
} else {
if(ip.startsWith("172")){
return pjp.proceed();
} else {
LOGGER.error("非法ip:{}", ip);
return JsonResult.buildErrorStateResult("非法ip", null);
}
}*/
//return pjp.proceed();
}
}
src/main/java/cn/quantgroup/xyqb/aspect/captcha/CaptchaFineteValidator.java
deleted
100644 → 0
View file @
d457a892
package
cn
.
quantgroup
.
xyqb
.
aspect
.
captcha
;
import
java.lang.annotation.*
;
/**
* 限次的图形验证码校验标记
* @author 任文超
* @version 1.0.0
* @since 2017-11-07
*/
@Documented
@Target
(
ElementType
.
METHOD
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
CaptchaFineteValidator
{
}
src/main/java/cn/quantgroup/xyqb/aspect/captcha/CaptchaFiniteValidateAdvisor.java
View file @
cdb2fe25
...
@@ -4,6 +4,7 @@ package cn.quantgroup.xyqb.aspect.captcha;
...
@@ -4,6 +4,7 @@ package cn.quantgroup.xyqb.aspect.captcha;
import
cn.quantgroup.xyqb.Constants
;
import
cn.quantgroup.xyqb.Constants
;
import
cn.quantgroup.xyqb.model.JsonResult
;
import
cn.quantgroup.xyqb.model.JsonResult
;
import
cn.quantgroup.xyqb.thirdparty.jcaptcha.AbstractManageableImageCaptchaService
;
import
cn.quantgroup.xyqb.thirdparty.jcaptcha.AbstractManageableImageCaptchaService
;
import
cn.quantgroup.xyqb.util.IPUtil
;
import
cn.quantgroup.xyqb.util.ValidationUtil
;
import
cn.quantgroup.xyqb.util.ValidationUtil
;
import
com.octo.captcha.service.CaptchaServiceException
;
import
com.octo.captcha.service.CaptchaServiceException
;
import
org.apache.commons.codec.binary.Base64
;
import
org.apache.commons.codec.binary.Base64
;
...
@@ -67,7 +68,7 @@ public class CaptchaFiniteValidateAdvisor {
...
@@ -67,7 +68,7 @@ public class CaptchaFiniteValidateAdvisor {
/**
/**
* 限次图形验证码切面
* 限次图形验证码切面
*/
*/
@Pointcut
(
"@annotation(cn.quantgroup.xyqb.aspect.captcha.CaptchaFin
e
teValidator)"
)
@Pointcut
(
"@annotation(cn.quantgroup.xyqb.aspect.captcha.CaptchaFin
i
teValidator)"
)
private
void
needCaptchaFiniteValidate
()
{
private
void
needCaptchaFiniteValidate
()
{
}
}
...
@@ -89,7 +90,7 @@ public class CaptchaFiniteValidateAdvisor {
...
@@ -89,7 +90,7 @@ public class CaptchaFiniteValidateAdvisor {
String
phoneNo
=
phonePasswordMap
.
get
(
"phoneNo"
);
String
phoneNo
=
phonePasswordMap
.
get
(
"phoneNo"
);
Long
countErrorByPhone
=
getCount
(
phoneNo
);
Long
countErrorByPhone
=
getCount
(
phoneNo
);
if
(
countErrorByPhone
==
null
){
if
(
countErrorByPhone
==
null
){
LOGGER
.
info
(
"用户名或密码不正确, phoneNo={}, countErrorByPhone={}, clientIp={}"
,
phoneNo
,
countErrorByPhone
,
request
.
getRemoteAddr
(
));
LOGGER
.
info
(
"用户名或密码不正确, phoneNo={}, countErrorByPhone={}, clientIp={}"
,
phoneNo
,
countErrorByPhone
,
IPUtil
.
getRemoteIP
(
request
));
return
JsonResult
.
buildErrorStateResult
(
"用户名或密码不正确"
,
null
);
return
JsonResult
.
buildErrorStateResult
(
"用户名或密码不正确"
,
null
);
}
}
if
(
countErrorByPhone
>
Constants
.
Image_Need_Count
)
{
if
(
countErrorByPhone
>
Constants
.
Image_Need_Count
)
{
...
@@ -97,7 +98,7 @@ public class CaptchaFiniteValidateAdvisor {
...
@@ -97,7 +98,7 @@ public class CaptchaFiniteValidateAdvisor {
String
captchaId
=
Optional
.
ofNullable
(
request
.
getParameter
(
"captchaId"
)).
orElse
(
""
);
String
captchaId
=
Optional
.
ofNullable
(
request
.
getParameter
(
"captchaId"
)).
orElse
(
""
);
String
captchaValue
=
request
.
getParameter
(
"captchaValue"
);
String
captchaValue
=
request
.
getParameter
(
"captchaValue"
);
if
(
shouldSkipCaptchaValidate
(
registerFrom
,
captchaId
,
captchaValue
))
{
if
(
shouldSkipCaptchaValidate
(
registerFrom
,
captchaId
,
captchaValue
))
{
LOGGER
.
info
(
"使用超级图形验证码校验, registerFrom={}, clientIp={}"
,
registerFrom
,
request
.
getRemoteAddr
(
));
LOGGER
.
info
(
"使用超级图形验证码校验, registerFrom={}, clientIp={}"
,
registerFrom
,
IPUtil
.
getRemoteIP
(
request
));
return
pjp
.
proceed
();
return
pjp
.
proceed
();
}
}
if
(
StringUtils
.
isNotBlank
(
captchaValue
))
{
if
(
StringUtils
.
isNotBlank
(
captchaValue
))
{
...
...
src/main/java/cn/quantgroup/xyqb/aspect/captcha/CaptchaNewValidateAdvisor.java
View file @
cdb2fe25
...
@@ -4,6 +4,7 @@ import cn.quantgroup.xyqb.Constants;
...
@@ -4,6 +4,7 @@ import cn.quantgroup.xyqb.Constants;
import
cn.quantgroup.xyqb.controller.IBaseController
;
import
cn.quantgroup.xyqb.controller.IBaseController
;
import
cn.quantgroup.xyqb.model.JsonResult
;
import
cn.quantgroup.xyqb.model.JsonResult
;
import
cn.quantgroup.xyqb.thirdparty.jcaptcha.AbstractManageableImageCaptchaService
;
import
cn.quantgroup.xyqb.thirdparty.jcaptcha.AbstractManageableImageCaptchaService
;
import
cn.quantgroup.xyqb.util.IPUtil
;
import
com.octo.captcha.service.CaptchaServiceException
;
import
com.octo.captcha.service.CaptchaServiceException
;
import
java.io.PipedReader
;
import
java.io.PipedReader
;
...
@@ -86,15 +87,16 @@ public class CaptchaNewValidateAdvisor {
...
@@ -86,15 +87,16 @@ public class CaptchaNewValidateAdvisor {
String
captchaValue
=
request
.
getParameter
(
"captchaValue"
);
String
captchaValue
=
request
.
getParameter
(
"captchaValue"
);
String
phoneNo
=
request
.
getParameter
(
"phoneNo"
);
String
phoneNo
=
request
.
getParameter
(
"phoneNo"
);
String
deviceId
=
Optional
.
ofNullable
(
request
.
getParameter
(
"deviceId"
)).
orElse
(
""
);
String
deviceId
=
Optional
.
ofNullable
(
request
.
getParameter
(
"deviceId"
)).
orElse
(
""
);
String
clientIp
=
getIp
(
);
String
clientIp
=
IPUtil
.
getRemoteIP
(
request
);
Long
countIP
=
countIP
(
clientIp
);
Long
countIP
=
countIP
(
clientIp
);
Long
countPhone
=
countPhone
(
phoneNo
);
Long
countPhone
=
countPhone
(
phoneNo
);
Long
countDeviceId
=
countDeviceId
(
deviceId
);
Long
countDeviceId
=
countDeviceId
(
deviceId
);
IPUtil
.
logIp
(
LOGGER
,
request
);
LOGGER
.
info
(
"使用图形验证码, registerFrom={}, clientIp={},手机号次数:{},设备次数:{},ip次数:{},phone:{}"
,
registerFrom
,
clientIp
,
countPhone
,
countDeviceId
,
countIP
,
phoneNo
);
LOGGER
.
info
(
"使用图形验证码, registerFrom={}, clientIp={},手机号次数:{},设备次数:{},ip次数:{},phone:{}"
,
registerFrom
,
clientIp
,
countPhone
,
countDeviceId
,
countIP
,
phoneNo
);
if
(
countIP
>
Constants
.
Image_Need_Count
||
countPhone
>
Constants
.
Image_Need_Count
||
countDeviceId
>
Constants
.
Image_Need_Count
)
{
if
(
countIP
>
Constants
.
Image_Need_Count
||
countPhone
>
Constants
.
Image_Need_Count
||
countDeviceId
>
Constants
.
Image_Need_Count
)
{
if
(
shouldSkipCaptchaValidate
(
registerFrom
,
captchaId
,
captchaValue
))
{
if
(
shouldSkipCaptchaValidate
(
registerFrom
,
captchaId
,
captchaValue
))
{
LOGGER
.
info
(
"使用超级图形验证码校验, registerFrom={}, clientIp={}"
,
registerFrom
,
request
.
getRemoteAddr
()
);
LOGGER
.
info
(
"使用超级图形验证码校验, registerFrom={}, clientIp={}"
,
registerFrom
,
clientIp
);
return
pjp
.
proceed
();
return
pjp
.
proceed
();
}
}
...
@@ -183,25 +185,6 @@ public class CaptchaNewValidateAdvisor {
...
@@ -183,25 +185,6 @@ public class CaptchaNewValidateAdvisor {
}
}
}
}
private
String
getIp
()
{
HttpServletRequest
request
=
getRequest
();
String
ip
=
request
.
getHeader
(
"x-real-ip"
);
if
(
StringUtils
.
isEmpty
(
ip
))
{
ip
=
request
.
getRemoteAddr
();
}
//过滤反向代理的ip
String
[]
stemps
=
ip
.
split
(
","
);
if
(
stemps
.
length
>=
1
)
{
//得到第一个IP,即客户端真实IP
ip
=
stemps
[
0
];
}
ip
=
ip
.
trim
();
if
(
ip
.
length
()
>
23
)
{
ip
=
ip
.
substring
(
0
,
23
);
}
return
ip
;
}
private
HttpServletRequest
getRequest
()
{
private
HttpServletRequest
getRequest
()
{
ServletRequestAttributes
attrs
=
(
ServletRequestAttributes
)
RequestContextHolder
.
getRequestAttributes
();
ServletRequestAttributes
attrs
=
(
ServletRequestAttributes
)
RequestContextHolder
.
getRequestAttributes
();
return
attrs
.
getRequest
();
return
attrs
.
getRequest
();
...
...
src/main/java/cn/quantgroup/xyqb/aspect/captcha/CaptchaValidateAdvisor.java
View file @
cdb2fe25
...
@@ -4,6 +4,7 @@ package cn.quantgroup.xyqb.aspect.captcha;
...
@@ -4,6 +4,7 @@ package cn.quantgroup.xyqb.aspect.captcha;
import
cn.quantgroup.xyqb.Constants
;
import
cn.quantgroup.xyqb.Constants
;
import
cn.quantgroup.xyqb.model.JsonResult
;
import
cn.quantgroup.xyqb.model.JsonResult
;
import
cn.quantgroup.xyqb.thirdparty.jcaptcha.AbstractManageableImageCaptchaService
;
import
cn.quantgroup.xyqb.thirdparty.jcaptcha.AbstractManageableImageCaptchaService
;
import
cn.quantgroup.xyqb.util.IPUtil
;
import
com.octo.captcha.service.CaptchaServiceException
;
import
com.octo.captcha.service.CaptchaServiceException
;
import
org.apache.commons.lang3.StringUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.aspectj.lang.ProceedingJoinPoint
;
import
org.aspectj.lang.ProceedingJoinPoint
;
...
@@ -81,7 +82,7 @@ public class CaptchaValidateAdvisor {
...
@@ -81,7 +82,7 @@ public class CaptchaValidateAdvisor {
Object
captchaValue
=
request
.
getParameter
(
"captchaValue"
);
Object
captchaValue
=
request
.
getParameter
(
"captchaValue"
);
if
(
shouldSkipCaptchaValidate
(
registerFrom
,
captchaId
,
captchaValue
))
{
if
(
shouldSkipCaptchaValidate
(
registerFrom
,
captchaId
,
captchaValue
))
{
LOGGER
.
info
(
"使用超级图形验证码校验, registerFrom={}, clientIp={}"
,
registerFrom
,
request
.
getRemoteAddr
(
));
LOGGER
.
info
(
"使用超级图形验证码校验, registerFrom={}, clientIp={}"
,
registerFrom
,
IPUtil
.
getRemoteIP
(
request
));
return
pjp
.
proceed
();
return
pjp
.
proceed
();
}
}
...
...
src/main/java/cn/quantgroup/xyqb/aspect/limit/PasswordFreeAccessValidatorValidateAdvisor.java
deleted
100644 → 0
View file @
d457a892
package
cn
.
quantgroup
.
xyqb
.
aspect
.
limit
;
import
cn.quantgroup.xyqb.Constants
;
import
cn.quantgroup.xyqb.entity.User
;
import
cn.quantgroup.xyqb.model.JsonResult
;
import
cn.quantgroup.xyqb.model.session.SessionStruct
;
import
cn.quantgroup.xyqb.session.XyqbSessionContextHolder
;
import
com.alibaba.fastjson.JSONObject
;
import
org.apache.commons.lang3.StringUtils
;
import
org.aspectj.lang.ProceedingJoinPoint
;
import
org.aspectj.lang.annotation.Around
;
import
org.aspectj.lang.annotation.Aspect
;
import
org.aspectj.lang.annotation.Pointcut
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Qualifier
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.stereotype.Component
;
import
org.springframework.web.context.request.RequestContextHolder
;
import
org.springframework.web.context.request.ServletRequestAttributes
;
import
javax.servlet.http.HttpServletRequest
;
import
java.util.*
;
/**
* 免密访问校验切面
*
* @author 任文超
* @version 1.0.0
* @since 2017-11-21
*/
@Aspect
@Component
public
class
PasswordFreeAccessValidatorValidateAdvisor
{
private
static
final
Logger
LOGGER
=
LoggerFactory
.
getLogger
(
PasswordFreeAccessValidatorValidateAdvisor
.
class
);
private
static
final
String
PHONE_NO
=
"phoneNo"
;
private
static
final
String
USER_ID
=
"userId"
;
@Autowired
@Qualifier
(
"stringRedisTemplate"
)
private
RedisTemplate
<
String
,
String
>
redisTemplate
;
/**
* 免密访问校验切面
*/
@Pointcut
(
"@annotation(cn.quantgroup.xyqb.aspect.limit.PasswordFreeAccessValidator)"
)
private
void
passwordFreeAccess
()
{}
/**
* 执行免密访问校验
*
* @throws Throwable
*/
@Around
(
"passwordFreeAccess()"
)
private
Object
checkToken
(
ProceedingJoinPoint
pjp
)
throws
Throwable
{
HttpServletRequest
request
=
((
ServletRequestAttributes
)
RequestContextHolder
.
getRequestAttributes
()).
getRequest
();
boolean
valid
=
tokenValid
(
request
)
||
ipValid
(
request
);
if
(
valid
)
{
return
pjp
.
proceed
();
}
return
JsonResult
.
buildErrorStateResult
(
"拒绝访问"
,
""
);
}
/**
* 校验免密访问
* 规则:token 与 身份标记(phoneNo、userId匹配)
* @return True or False
*/
private
boolean
tokenValid
(
HttpServletRequest
request
)
{
Objects
.
requireNonNull
(
request
,
"无效请求"
);
Set
<
String
>
paramKeys
=
request
.
getParameterMap
().
keySet
();
if
(!
paramKeys
.
contains
(
PHONE_NO
)
&&
!
paramKeys
.
contains
(
USER_ID
)){
LOGGER
.
info
(
"非法请求 - 缺少参数, paramKeys={}, clientIp={}"
,
paramKeys
,
request
.
getRemoteAddr
());
return
false
;
}
// 当前请求的phoneNo/userId
String
phoneNo
=
request
.
getParameter
(
PHONE_NO
);
String
userId
=
request
.
getParameter
(
USER_ID
);
if
(
StringUtils
.
isBlank
(
phoneNo
)
&&
StringUtils
.
isBlank
(
userId
)){
LOGGER
.
info
(
"非法请求 - 缺少参数, phoneNo={}, userId={}, clientIp={}"
,
phoneNo
,
userId
,
request
.
getRemoteAddr
());
return
false
;
}
// 当前请求的Token
String
token
=
request
.
getHeader
(
Constants
.
X_AUTH_TOKEN
);
if
(
Objects
.
isNull
(
token
)
||
token
.
length
()
!=
36
)
{
LOGGER
.
info
(
"非法请求 - 无效token, token={}, phoneNo={}, userId={}, clientIp={}"
,
token
,
phoneNo
,
userId
,
request
.
getRemoteAddr
());
return
false
;
}
// 当前session
SessionStruct
session
=
XyqbSessionContextHolder
.
getXSessionFromRedis
(
token
);
if
(
Objects
.
isNull
(
session
)
||
Objects
.
isNull
(
session
.
getValues
())
||
Objects
.
isNull
(
session
.
getValues
().
getUser
())){
LOGGER
.
info
(
"非法请求 - 未登录, token={}, phoneNo={}, userId={}, clientIp={}"
,
token
,
phoneNo
,
userId
,
request
.
getRemoteAddr
());
return
false
;
}
// 当前用户
User
user
=
session
.
getValues
().
getUser
();
if
(
Objects
.
isNull
(
user
.
getId
())
&&
StringUtils
.
isBlank
(
user
.
getPhoneNo
())){
LOGGER
.
info
(
"非法请求 - 未登录, token={}, phoneNo={}, userId={}, clientIp={}"
,
token
,
phoneNo
,
userId
,
request
.
getRemoteAddr
());
return
false
;
}
// 校对用户信息是否匹配
boolean
valid
=
(
Objects
.
nonNull
(
user
.
getId
())
&&
Objects
.
equals
(
userId
,
user
.
getId
().
toString
()));
valid
=
valid
||
(
StringUtils
.
isNotBlank
(
phoneNo
)
&&
Objects
.
equals
(
phoneNo
,
user
.
getPhoneNo
()));
if
(!
valid
)
{
LOGGER
.
info
(
"非法请求 - 身份不匹配, token={}, phoneNo=({},{}), userId=({},{}), clientIp={}"
,
token
,
phoneNo
,
user
.
getPhoneNo
(),
userId
,
user
.
getId
(),
request
.
getRemoteAddr
());
}
return
valid
;
}
/**
* 校验免密访问
* 规则:来访IP与白名单匹配
* @return True or False
*/
private
boolean
ipValid
(
HttpServletRequest
request
)
{
Objects
.
requireNonNull
(
request
,
"无效请求"
);
String
remoteAddr
=
request
.
getRemoteAddr
();
Set
<
String
>
whiteAddr
=
Collections
.
emptySet
();
// Todo 配置白名单
// 校对来访IP是否与白名单匹配
boolean
valid
=
StringUtils
.
isNotBlank
(
remoteAddr
)
&&
whiteAddr
.
contains
(
remoteAddr
);
if
(!
valid
)
{
LOGGER
.
info
(
"非法请求 - 未授权访问, clientIp={}"
,
request
.
getRemoteAddr
());
}
return
valid
;
}
}
src/main/java/cn/quantgroup/xyqb/aspect/lock/PasswordErrorFiniteValidateAdvisor.java
View file @
cdb2fe25
...
@@ -3,6 +3,7 @@ package cn.quantgroup.xyqb.aspect.lock;
...
@@ -3,6 +3,7 @@ package cn.quantgroup.xyqb.aspect.lock;
import
cn.quantgroup.xyqb.Constants
;
import
cn.quantgroup.xyqb.Constants
;
import
cn.quantgroup.xyqb.model.JsonResult
;
import
cn.quantgroup.xyqb.model.JsonResult
;
import
cn.quantgroup.xyqb.util.IPUtil
;
import
org.apache.commons.lang3.StringUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.aspectj.lang.ProceedingJoinPoint
;
import
org.aspectj.lang.ProceedingJoinPoint
;
import
org.aspectj.lang.annotation.Around
;
import
org.aspectj.lang.annotation.Around
;
...
@@ -39,7 +40,7 @@ public class PasswordErrorFiniteValidateAdvisor {
...
@@ -39,7 +40,7 @@ public class PasswordErrorFiniteValidateAdvisor {
/**
/**
* 密码错误限次切面
* 密码错误限次切面
*/
*/
@Pointcut
(
"@annotation(cn.quantgroup.xyqb.aspect.lock.Password
Fine
teValidator)"
)
@Pointcut
(
"@annotation(cn.quantgroup.xyqb.aspect.lock.Password
ErrorFini
teValidator)"
)
private
void
passwordErrorFiniteValidate
()
{
private
void
passwordErrorFiniteValidate
()
{
}
}
...
@@ -58,23 +59,29 @@ public class PasswordErrorFiniteValidateAdvisor {
...
@@ -58,23 +59,29 @@ public class PasswordErrorFiniteValidateAdvisor {
}*/
}*/
HttpServletRequest
request
=
((
ServletRequestAttributes
)
RequestContextHolder
.
getRequestAttributes
()).
getRequest
();
HttpServletRequest
request
=
((
ServletRequestAttributes
)
RequestContextHolder
.
getRequestAttributes
()).
getRequest
();
// 客户端IP
// 客户端IP
String
clientIp
=
getIp
(
request
);
String
clientIp
=
IPUtil
.
getRemoteIP
(
request
);
//
入口服务器IP
//
白名单
if
(
StringUtils
.
startsWith
(
clientIp
,
"139.198."
)){
if
(
IPUtil
.
whiteOf
(
clientIp
)){
return
pjp
.
proceed
();
return
pjp
.
proceed
();
}
}
// 白名单
//
补充
白名单
if
(
redisTemplate
.
opsForSet
().
isMember
(
Constants
.
IPV4_LOCK_WHITE
,
clientIp
)){
if
(
redisTemplate
.
opsForSet
().
isMember
(
Constants
.
IPV4_LOCK_WHITE
,
clientIp
)){
return
pjp
.
proceed
();
return
pjp
.
proceed
();
}
}
// 入口服务器IP
if
(
StringUtils
.
startsWith
(
clientIp
,
"139.198."
)){
return
pjp
.
proceed
();
}
// 黑名单
// 黑名单
if
(
redisTemplate
.
opsForSet
().
isMember
(
Constants
.
IPV4_LOCK_BLACK
,
clientIp
)){
if
(
redisTemplate
.
opsForSet
().
isMember
(
Constants
.
IPV4_LOCK_BLACK
,
clientIp
)){
IPUtil
.
logIp
(
LOGGER
,
request
);
LOGGER
.
info
(
"Lock_ipv4: locked ip access:{}"
,
clientIp
);
LOGGER
.
info
(
"Lock_ipv4: locked ip access:{}"
,
clientIp
);
return
JsonResult
.
buildErrorStateResult
(
"登录失败"
,
null
);
return
JsonResult
.
buildErrorStateResult
(
"登录失败"
,
null
);
}
}
String
lockIpv4Key
=
getLockIpv4Key
(
clientIp
);
String
lockIpv4Key
=
getLockIpv4Key
(
clientIp
);
String
lock
=
redisTemplate
.
opsForValue
().
get
(
lockIpv4Key
);
String
lock
=
redisTemplate
.
opsForValue
().
get
(
lockIpv4Key
);
if
(
Objects
.
equals
(
Boolean
.
TRUE
.
toString
(),
lock
)){
if
(
Objects
.
equals
(
Boolean
.
TRUE
.
toString
(),
lock
)){
IPUtil
.
logIp
(
LOGGER
,
request
);
LOGGER
.
info
(
"Lock_ipv4: locked ip access:{}"
,
clientIp
);
LOGGER
.
info
(
"Lock_ipv4: locked ip access:{}"
,
clientIp
);
return
JsonResult
.
buildErrorStateResult
(
"登录失败"
,
null
);
return
JsonResult
.
buildErrorStateResult
(
"登录失败"
,
null
);
}
}
...
@@ -85,30 +92,4 @@ public class PasswordErrorFiniteValidateAdvisor {
...
@@ -85,30 +92,4 @@ public class PasswordErrorFiniteValidateAdvisor {
return
Constants
.
IPV4_LOCK
+
ipv4
;
return
Constants
.
IPV4_LOCK
+
ipv4
;
}
}
/**
* 客户端IP解析
*
* @param request 当前请求,其首部行必须包含形如【SingleToken 13461067662:0123456789abcdef】的UTF-8编码的Base64加密参数
* @return 客户端IP 或 null
*/
private
String
getIp
(
HttpServletRequest
request
)
{
Objects
.
requireNonNull
(
request
,
"无效请求"
);
String
ip
=
request
.
getHeader
(
"x-real-ip"
);
if
(
StringUtils
.
isBlank
(
ip
))
{
ip
=
request
.
getRemoteAddr
();
}
//过滤反向代理的ip
String
[]
stemps
=
ip
.
split
(
","
);
if
(
stemps
.
length
>=
1
)
{
//得到第一个IP,即客户端真实IP
ip
=
stemps
[
0
];
}
ip
=
ip
.
trim
();
if
(
ip
.
length
()
>
23
)
{
ip
=
ip
.
substring
(
0
,
23
);
}
return
ip
;
}
}
}
src/main/java/cn/quantgroup/xyqb/aspect/lock/PasswordFineteValidator.java
deleted
100644 → 0
View file @
d457a892
package
cn
.
quantgroup
.
xyqb
.
aspect
.
lock
;
import
java.lang.annotation.*
;
/**
* 密码错误限次的校验标记
* @author 任文超
* @version 1.0.0
* @since 2017-11-23
*/
@Documented
@Target
(
ElementType
.
METHOD
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
PasswordFineteValidator
{
}
src/main/java/cn/quantgroup/xyqb/aspect/token/OneTimeTokenValidateAdvisor.java
deleted
100644 → 0
View file @
d457a892
package
cn
.
quantgroup
.
xyqb
.
aspect
.
token
;
import
cn.quantgroup.xyqb.Constants
;
import
cn.quantgroup.xyqb.model.JsonResult
;
import
org.apache.commons.lang3.StringUtils
;
import
org.aspectj.lang.ProceedingJoinPoint
;
import
org.aspectj.lang.annotation.Around
;
import
org.aspectj.lang.annotation.Aspect
;
import
org.aspectj.lang.annotation.Pointcut
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Qualifier
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.stereotype.Component
;
import
org.springframework.web.context.request.RequestContextHolder
;
import
org.springframework.web.context.request.ServletRequestAttributes
;
import
javax.servlet.http.HttpServletRequest
;
import
java.util.Objects
;
/**
* 一次性令牌校验切面
*
* @author 任文超
* @version 1.0.0
* @since 2017-10-31
*/
@Aspect
@Component
public
class
OneTimeTokenValidateAdvisor
{
private
static
final
Logger
LOGGER
=
LoggerFactory
.
getLogger
(
OneTimeTokenValidateAdvisor
.
class
);
@Autowired
@Qualifier
(
"stringRedisTemplate"
)
private
RedisTemplate
<
String
,
String
>
redisTemplate
;
/**
* 一次性令牌校验切面
*/
@Pointcut
(
"@annotation(cn.quantgroup.xyqb.aspect.token.OneTimeTokenValidator)"
)
private
void
needOneTimeToken
()
{}
/**
* 在受一次性令牌保护的接口方法执行前, 执行一次性令牌校验
*
* @throws Throwable
*/
@Around
(
"needOneTimeToken()"
)
private
Object
checkOneTimeToken
(
ProceedingJoinPoint
pjp
)
throws
Throwable
{
boolean
valid
=
oneTimeTokenValid
();
if
(
valid
)
{
return
pjp
.
proceed
();
}
return
JsonResult
.
buildSuccessResult
(
"操作失败,请重新提交"
,
""
,
2L
);
}
/**
* 校验一次性令牌
* @return True or False
*/
private
boolean
oneTimeTokenValid
()
{
HttpServletRequest
request
=
((
ServletRequestAttributes
)
RequestContextHolder
.
getRequestAttributes
()).
getRequest
();
// 当前请求的OneTimeToken
String
oneTimeToken
=
request
.
getParameter
(
Constants
.
ONE_TIME_TOKEN
);
if
(
StringUtils
.
isBlank
(
oneTimeToken
)){
return
false
;
}
String
oneTimeToken_value
=
redisTemplate
.
opsForValue
().
get
(
oneTimeToken
);
// OneTimeToken再Redis中值不应为空值(空白、空格、null)
if
(
StringUtils
.
isBlank
(
oneTimeToken_value
))
{
return
false
;
}
boolean
valid
=
Objects
.
equals
(
Boolean
.
TRUE
.
toString
(),
oneTimeToken_value
);
// OneTimeToken校验正确时删除key
if
(
valid
)
{
redisTemplate
.
delete
(
oneTimeToken
);
}
else
{
LOGGER
.
info
(
"令牌已失效,请重新请求, oneTimeToken={}, clientIp={}"
,
oneTimeToken
,
request
.
getRemoteAddr
());
}
return
valid
;
}
}
src/main/java/cn/quantgroup/xyqb/aspect/token/OneTimeTokenValidator.java
deleted
100644 → 0
View file @
d457a892
package
cn
.
quantgroup
.
xyqb
.
aspect
.
token
;
import
java.lang.annotation.*
;
/**
* 一次性令牌校验标记
* @author 任文超
* @version 1.0.0
* @since 2017-10-31
*/
@Documented
@Target
(
ElementType
.
METHOD
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
OneTimeTokenValidator
{
}
src/main/java/cn/quantgroup/xyqb/controller/IBaseController.java
View file @
cdb2fe25
...
@@ -2,6 +2,7 @@ package cn.quantgroup.xyqb.controller;
...
@@ -2,6 +2,7 @@ package cn.quantgroup.xyqb.controller;
import
cn.quantgroup.xyqb.entity.User
;
import
cn.quantgroup.xyqb.entity.User
;
import
cn.quantgroup.xyqb.model.session.SessionStruct
;
import
cn.quantgroup.xyqb.model.session.SessionStruct
;
import
cn.quantgroup.xyqb.util.IPUtil
;
import
org.apache.commons.lang3.StringUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.web.context.request.RequestContextHolder
;
import
org.springframework.web.context.request.RequestContextHolder
;
import
org.springframework.web.context.request.ServletRequestAttributes
;
import
org.springframework.web.context.request.ServletRequestAttributes
;
...
@@ -50,25 +51,7 @@ public interface IBaseController {
...
@@ -50,25 +51,7 @@ public interface IBaseController {
default
String
getIp
()
{
default
String
getIp
()
{
HttpServletRequest
request
=
getRequest
();
HttpServletRequest
request
=
getRequest
();
return
IPUtil
.
getRemoteIP
(
request
);
String
ip
=
request
.
getHeader
(
"x-real-ip"
);
if
(
StringUtils
.
isEmpty
(
ip
))
{
ip
=
request
.
getRemoteAddr
();
}
//过滤反向代理的ip
String
[]
stemps
=
ip
.
split
(
","
);
if
(
stemps
.
length
>=
1
)
{
//得到第一个IP,即客户端真实IP
ip
=
stemps
[
0
];
}
ip
=
ip
.
trim
();
if
(
ip
.
length
()
>
23
)
{
ip
=
ip
.
substring
(
0
,
23
);
}
return
ip
;
}
}
default
String
getProtocol
()
{
default
String
getProtocol
()
{
...
...
src/main/java/cn/quantgroup/xyqb/controller/external/user/InnerController.java
View file @
cdb2fe25
package
cn
.
quantgroup
.
xyqb
.
controller
.
external
.
user
;
package
cn
.
quantgroup
.
xyqb
.
controller
.
external
.
user
;
import
cn.quantgroup.user.enums.Relation
;
import
cn.quantgroup.user.enums.Relation
;
import
cn.quantgroup.xyqb.aspect.
limit.PasswordFreeAccess
Validator
;
import
cn.quantgroup.xyqb.aspect.
accessable.Ip
Validator
;
import
cn.quantgroup.xyqb.aspect.logcaller.LogHttpCaller
;
import
cn.quantgroup.xyqb.aspect.logcaller.LogHttpCaller
;
import
cn.quantgroup.xyqb.controller.IBaseController
;
import
cn.quantgroup.xyqb.controller.IBaseController
;
import
cn.quantgroup.xyqb.entity.*
;
import
cn.quantgroup.xyqb.entity.*
;
...
@@ -520,9 +520,9 @@ public class InnerController implements IBaseController {
...
@@ -520,9 +520,9 @@ public class InnerController implements IBaseController {
return
JsonResult
.
buildSuccessResult
(
null
,
UserExtInfoRet
.
getUserExtInfoRet
(
info
));
return
JsonResult
.
buildSuccessResult
(
null
,
UserExtInfoRet
.
getUserExtInfoRet
(
info
));
}
}
// Todo @PasswordFreeAccessValidator
@IpValidator
@RequestMapping
(
"/user_detail/search_list"
)
@LogHttpCaller
@LogHttpCaller
@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
());
LOGGER
.
info
(
"searchUserDetailList ,param.name:{},phone:{},idNo:{},ip:{}"
,
name
,
phoneNo
,
idNo
,
getIp
());
...
@@ -574,9 +574,9 @@ public class InnerController implements IBaseController {
...
@@ -574,9 +574,9 @@ public class InnerController implements IBaseController {
return
JsonResult
.
buildSuccessResult
(
"success"
,
wechatUserInfo
.
getOpenId
());
return
JsonResult
.
buildSuccessResult
(
"success"
,
wechatUserInfo
.
getOpenId
());
}
}
// Todo @PasswordFreeAccessValidator
@IpValidator
@RequestMapping
(
"/user-association/search/phone"
)
@LogHttpCaller
@LogHttpCaller
@RequestMapping
(
"/user-association/search/phone"
)
public
JsonResult
findUserAssociationByPhone
(
String
phoneNo
)
{
public
JsonResult
findUserAssociationByPhone
(
String
phoneNo
)
{
UserDetail
userDetail
=
userDetailService
.
findByPhoneNo
(
phoneNo
);
UserDetail
userDetail
=
userDetailService
.
findByPhoneNo
(
phoneNo
);
UserAssociation
bean
=
new
UserAssociation
();
UserAssociation
bean
=
new
UserAssociation
();
...
...
src/main/java/cn/quantgroup/xyqb/controller/internal/sms/SmsController.java
View file @
cdb2fe25
...
@@ -240,12 +240,12 @@ public class SmsController implements IBaseController {
...
@@ -240,12 +240,12 @@ public class SmsController implements IBaseController {
LOGGER
.
info
(
"您手机号已经达到获取今天短信验证码上限:phoneNo:{},deviceId:{},ip:{}"
,
phoneNo
,
deviceId
,
getIp
());
LOGGER
.
info
(
"您手机号已经达到获取今天短信验证码上限:phoneNo:{},deviceId:{},ip:{}"
,
phoneNo
,
deviceId
,
getIp
());
return
JsonResult
.
buildErrorStateResult
(
"今天已获取20次短信验证码,请使用语音验证码或明天再试"
,
null
);
return
JsonResult
.
buildErrorStateResult
(
"今天已获取20次短信验证码,请使用语音验证码或明天再试"
,
null
);
}
}
String
verificationIPCountKey
=
getIp
();
String
clientIp
=
getIp
();
// Todo - 运维解决真实IP获取问题后,打开这段代码,实现按IP限制短信验证码获取量
// Todo - 运维解决真实IP获取问题后,打开这段代码,实现按IP限制短信验证码获取量
// Todo - 另:当前的计数器计数方式为乐观累加,而且还是提前计数,会导致边界值问题,即临界次数会提前一次记满,并且在后续请求到达时计数器会继续计数
// Todo - 另:当前的计数器计数方式为乐观累加,而且还是提前计数,会导致边界值问题,即临界次数会提前一次记满,并且在后续请求到达时计数器会继续计数
/*
/*
if (!StringUtils.isEmpty(
verificationIPCountKey
)) {
if (!StringUtils.isEmpty(
clientIp
)) {
verificationIPCountKey=Constants.REDIS_SMS_IP_COUNT+verificationIPCountKey
;
String verificationIPCountKey = Constants.REDIS_SMS_IP_COUNT+clientIp
;
Long getIPVerificationCount = redisTemplate.opsForHash().increment(verificationIPCountKey, Constants.REDIS_SMS_IP_COUNT, 1);
Long getIPVerificationCount = redisTemplate.opsForHash().increment(verificationIPCountKey, Constants.REDIS_SMS_IP_COUNT, 1);
if (getIPVerificationCount > IP_MAX_PER_DAY) {
if (getIPVerificationCount > IP_MAX_PER_DAY) {
return JsonResult.buildErrorStateResult("您当前ip已经达到获取今天验证码上限", null);
return JsonResult.buildErrorStateResult("您当前ip已经达到获取今天验证码上限", null);
...
@@ -277,7 +277,7 @@ public class SmsController implements IBaseController {
...
@@ -277,7 +277,7 @@ public class SmsController implements IBaseController {
smsService
.
getSmsSender
().
sendMsg
(
message
);
smsService
.
getSmsSender
().
sendMsg
(
message
);
redisTemplate
.
opsForValue
().
set
(
key
,
uniqueId
+
":"
+
randomCode
,
EXPIRE_MINUTES
,
TimeUnit
.
MINUTES
);
redisTemplate
.
opsForValue
().
set
(
key
,
uniqueId
+
":"
+
randomCode
,
EXPIRE_MINUTES
,
TimeUnit
.
MINUTES
);
deleteRetSendCode
(
phoneNo
);
//删除用户重置密码,多次错误逻辑
deleteRetSendCode
(
phoneNo
);
//删除用户重置密码,多次错误逻辑
if
(
isApp
&&
needImageVlidate
(
verificationIPCountKey
,
deviceId
,
phoneNo
)){
if
(
isApp
&&
needImageVlidate
(
clientIp
,
deviceId
,
phoneNo
)){
return
JsonResult
.
buildSuccessResult
(
"发送成功"
,
uniqueId
,
0003
L
);
return
JsonResult
.
buildSuccessResult
(
"发送成功"
,
uniqueId
,
0003
L
);
}
}
LOGGER
.
info
(
"sendVerificationCode2New获取短信成功:phone:{},deviceId:{},ip:{}"
,
phoneNo
,
deviceId
,
getIp
());
LOGGER
.
info
(
"sendVerificationCode2New获取短信成功:phone:{},deviceId:{},ip:{}"
,
phoneNo
,
deviceId
,
getIp
());
...
@@ -299,9 +299,9 @@ public class SmsController implements IBaseController {
...
@@ -299,9 +299,9 @@ public class SmsController implements IBaseController {
if
(
getVerificationCount
>
PHONE_VOICE_MAX_PER_DAY
)
{
if
(
getVerificationCount
>
PHONE_VOICE_MAX_PER_DAY
)
{
return
JsonResult
.
buildErrorStateResult
(
"今天已获取5次语音验证码,请使用短信验证码或明天再试"
,
null
);
return
JsonResult
.
buildErrorStateResult
(
"今天已获取5次语音验证码,请使用短信验证码或明天再试"
,
null
);
}
}
String
verificationIPCountKey
=
getIp
();
String
clientIp
=
getIp
();
/* if (!StringUtils.isEmpty(
verificationIPCountKey
)) {
/* if (!StringUtils.isEmpty(
clientIp
)) {
verificationIPCountKey=Constants.REDIS_VOICE_IP_COUNT+verificationIPCountKey
;
String verificationIPCountKey = Constants.REDIS_VOICE_IP_COUNT+clientIp
;
Long getIPVerificationCount = redisTemplate.opsForHash().increment(verificationIPCountKey, Constants.REDIS_VOICE_IP_COUNT, 1);
Long getIPVerificationCount = redisTemplate.opsForHash().increment(verificationIPCountKey, Constants.REDIS_VOICE_IP_COUNT, 1);
if (getIPVerificationCount > IP_MAX_PER_DAY) {
if (getIPVerificationCount > IP_MAX_PER_DAY) {
return JsonResult.buildErrorStateResult("您当前ip已经达到获取今天语音验证码上限", null);
return JsonResult.buildErrorStateResult("您当前ip已经达到获取今天语音验证码上限", null);
...
@@ -333,7 +333,7 @@ public class SmsController implements IBaseController {
...
@@ -333,7 +333,7 @@ public class SmsController implements IBaseController {
smsService
.
getSmsSender
().
sendMsg
(
message
);
smsService
.
getSmsSender
().
sendMsg
(
message
);
redisTemplate
.
opsForValue
().
set
(
key
,
uniqueId
+
":"
+
randomCode
,
EXPIRE_MINUTES
,
TimeUnit
.
MINUTES
);
redisTemplate
.
opsForValue
().
set
(
key
,
uniqueId
+
":"
+
randomCode
,
EXPIRE_MINUTES
,
TimeUnit
.
MINUTES
);
deleteRetSendCode
(
phoneNo
);
//删除用户重置密码,多次错误逻辑
deleteRetSendCode
(
phoneNo
);
//删除用户重置密码,多次错误逻辑
if
(
needImageVlidate
(
verificationIPCountKey
,
deviceId
,
phoneNo
)){
if
(
needImageVlidate
(
clientIp
,
deviceId
,
phoneNo
)){
return
JsonResult
.
buildSuccessResult
(
"发送成功"
,
uniqueId
,
0003
L
);
return
JsonResult
.
buildSuccessResult
(
"发送成功"
,
uniqueId
,
0003
L
);
}
}
...
...
src/main/java/cn/quantgroup/xyqb/controller/internal/token/OneTimeTokenController.java
deleted
100644 → 0
View file @
d457a892
package
cn
.
quantgroup
.
xyqb
.
controller
.
internal
.
token
;
import
cn.quantgroup.xyqb.controller.IBaseController
;
import
cn.quantgroup.xyqb.model.JsonResult
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Qualifier
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
java.util.UUID
;
import
java.util.concurrent.TimeUnit
;
/**
* 发放一次性令牌
*
* @author 任文超
* @version 1.0.0
* @since 2017-10-31
*/
@RestController
@RequestMapping
(
"/token"
)
public
class
OneTimeTokenController
implements
IBaseController
{
private
static
final
Long
SECONDS
=
5
*
60L
;
@Autowired
@Qualifier
(
"stringRedisTemplate"
)
private
RedisTemplate
<
String
,
String
>
redisTemplate
;
/**
* 发放一枚一次性令牌
* One-Time Token用法:http请求首部行添加参数{One-Time-Token 6ac0665b-e19c-4392-a244-7b61690833f5}
*
* @return 一次性令牌
*/
@RequestMapping
(
value
=
"/oneTime"
)
public
JsonResult
oneTimeToken
()
{
String
token
=
UUID
.
randomUUID
().
toString
();
redisTemplate
.
opsForValue
().
set
(
token
,
Boolean
.
TRUE
.
toString
(),
SECONDS
,
TimeUnit
.
SECONDS
);
return
JsonResult
.
buildSuccessResult
(
""
,
token
);
}
}
src/main/java/cn/quantgroup/xyqb/controller/internal/user/UserController.java
View file @
cdb2fe25
package
cn
.
quantgroup
.
xyqb
.
controller
.
internal
.
user
;
package
cn
.
quantgroup
.
xyqb
.
controller
.
internal
.
user
;
import
cn.quantgroup.xyqb.Constants
;
import
cn.quantgroup.xyqb.Constants
;
import
cn.quantgroup.xyqb.aspect.captcha.CaptchaFin
e
teValidator
;
import
cn.quantgroup.xyqb.aspect.captcha.CaptchaFin
i
teValidator
;
import
cn.quantgroup.xyqb.aspect.lock.Password
Fine
teValidator
;
import
cn.quantgroup.xyqb.aspect.lock.Password
ErrorFini
teValidator
;
import
cn.quantgroup.xyqb.aspect.logcaller.LogHttpCaller
;
import
cn.quantgroup.xyqb.aspect.logcaller.LogHttpCaller
;
import
cn.quantgroup.xyqb.controller.IBaseController
;
import
cn.quantgroup.xyqb.controller.IBaseController
;
import
cn.quantgroup.xyqb.entity.Merchant
;
import
cn.quantgroup.xyqb.entity.Merchant
;
...
@@ -83,7 +83,7 @@ public class UserController implements IBaseController {
...
@@ -83,7 +83,7 @@ public class UserController implements IBaseController {
public
JsonResult
test
()
{
public
JsonResult
test
()
{
HttpServletRequest
request
=
getRequest
();
HttpServletRequest
request
=
getRequest
();
String
remoteAddr
=
request
.
getRemoteAddr
();
String
remoteAddr
=
request
.
getRemoteAddr
();
String
xRealIp
=
request
.
getHeader
(
"x-real-ip"
);
String
xRealIp
=
IPUtil
.
getRemoteIP
(
request
);
String
xOriginalClientIp
=
request
.
getHeader
(
"x-original-client-ip"
);
String
xOriginalClientIp
=
request
.
getHeader
(
"x-original-client-ip"
);
LOGGER
.
info
(
"Test ips:[client={}, old={}, new={}]"
,
remoteAddr
,
xRealIp
,
xOriginalClientIp
);
LOGGER
.
info
(
"Test ips:[client={}, old={}, new={}]"
,
remoteAddr
,
xRealIp
,
xOriginalClientIp
);
return
JsonResult
.
buildSuccessResult
(
""
,
getCurrentUserFromRedis
());
return
JsonResult
.
buildSuccessResult
(
""
,
getCurrentUserFromRedis
());
...
@@ -148,7 +148,7 @@ public class UserController implements IBaseController {
...
@@ -148,7 +148,7 @@ public class UserController implements IBaseController {
* @param dimension
* @param dimension
* @return
* @return
*/
*/
@CaptchaFin
e
teValidator
@CaptchaFin
i
teValidator
@RequestMapping
(
"/loginV1"
)
@RequestMapping
(
"/loginV1"
)
public
JsonResult
loginV1
(
public
JsonResult
loginV1
(
@RequestParam
(
required
=
false
,
defaultValue
=
"1"
)
Long
channelId
,
String
appChannel
,
@RequestParam
(
required
=
false
,
defaultValue
=
"1"
)
Long
channelId
,
String
appChannel
,
...
@@ -175,7 +175,6 @@ public class UserController implements IBaseController {
...
@@ -175,7 +175,6 @@ public class UserController implements IBaseController {
* @param request
* @param request
* @return
* @return
*/
*/
// Todo @OneTimeTokenValidator
@RequestMapping
(
"/login/fastV1"
)
@RequestMapping
(
"/login/fastV1"
)
public
JsonResult
loginFastV1
(
public
JsonResult
loginFastV1
(
@RequestParam
(
required
=
false
,
defaultValue
=
"1"
)
Long
channelId
,
String
appChannel
,
@RequestParam
(
required
=
false
,
defaultValue
=
"1"
)
Long
channelId
,
String
appChannel
,
...
@@ -188,7 +187,7 @@ public class UserController implements IBaseController {
...
@@ -188,7 +187,7 @@ public class UserController implements IBaseController {
}
}
@LogHttpCaller
@LogHttpCaller
@Password
Fine
teValidator
@Password
ErrorFini
teValidator
@RequestMapping
(
"/login"
)
@RequestMapping
(
"/login"
)
public
JsonResult
login
(
public
JsonResult
login
(
@RequestParam
(
required
=
false
,
defaultValue
=
"1"
)
Long
channelId
,
String
appChannel
,
@RequestParam
(
required
=
false
,
defaultValue
=
"1"
)
Long
channelId
,
String
appChannel
,
...
@@ -532,7 +531,7 @@ public class UserController implements IBaseController {
...
@@ -532,7 +531,7 @@ public class UserController implements IBaseController {
//增加登陆统计发送
//增加登陆统计发送
UserStatistics
statistics
=
new
UserStatistics
(
user
,
dimension
,
1
,
channelId
);
UserStatistics
statistics
=
new
UserStatistics
(
user
,
dimension
,
1
,
channelId
);
MqUtils
.
sendLoanVest
(
statistics
);
MqUtils
.
sendLoanVest
(
statistics
);
LOGGER
.
info
(
"用户登陆成功phonNo:{},当前ip:{},用户登陆信息:{}"
,
user
.
getPhoneNo
(),
IPUtil
.
getRemoteIP
(
request
),
statistics
);
LOGGER
.
info
(
"用户登陆成功phonNo:{},当前ip:{},用户登陆信息:{}"
,
user
.
getPhoneNo
(),
IPUtil
.
getRemoteIP
(
request
),
statistics
);
return
new
JsonResult
(
sessionService
.
createSession
(
channelId
,
createdFrom
,
appChannel
,
user
,
merchant
));
return
new
JsonResult
(
sessionService
.
createSession
(
channelId
,
createdFrom
,
appChannel
,
user
,
merchant
));
}
}
...
...
src/main/java/cn/quantgroup/xyqb/interceptors/IPWhiteListInterceptor.java
View file @
cdb2fe25
...
@@ -34,7 +34,9 @@ public class IPWhiteListInterceptor implements HandlerInterceptor {
...
@@ -34,7 +34,9 @@ public class IPWhiteListInterceptor implements HandlerInterceptor {
@Override
@Override
public
boolean
preHandle
(
HttpServletRequest
request
,
HttpServletResponse
response
,
Object
handler
)
throws
Exception
{
public
boolean
preHandle
(
HttpServletRequest
request
,
HttpServletResponse
response
,
Object
handler
)
throws
Exception
{
if
(
isDebug
!=
0
)
return
true
;
if
(
isDebug
!=
0
){
return
true
;
}
String
remoteIP
=
IPUtil
.
getRemoteIP
(
request
);
String
remoteIP
=
IPUtil
.
getRemoteIP
(
request
);
if
(
StringUtils
.
isNoneBlank
(
remoteIP
)){
if
(
StringUtils
.
isNoneBlank
(
remoteIP
)){
remoteIP
=
remoteIP
.
trim
();
remoteIP
=
remoteIP
.
trim
();
...
...
src/main/java/cn/quantgroup/xyqb/util/IPUtil.java
View file @
cdb2fe25
package
cn
.
quantgroup
.
xyqb
.
util
;
package
cn
.
quantgroup
.
xyqb
.
util
;
import
com.google.common.collect.Sets
;
import
org.apache.commons.lang3.StringUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.slf4j.Logger
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletRequest
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.Objects
;
import
java.util.Set
;
/**
/**
* IP地址工具类
* IP地址工具类
*
*
* @author
mengfan.feng
* @author
renwc
* @
time 2015-10-27 11:4
1
* @
date 2017-12-0
1
*/
*/
public
class
IPUtil
{
public
class
IPUtil
{
/**
* IP白名单
*
* 192.168.3.0/24 - 公有云测试业务
* 192.168.4.0/24 - 公有云测试业务
* 172.16.0.0/16 - 公有云正式业务
* 172.20.0.0/16 - 3B私有云
* 172.30.0.0/16 - 3C私有云
*/
private
static
final
Set
<
String
>
whiteAddr
=
Sets
.
newHashSet
();
static
{
String
[]
ips
=
{
"192.168.3."
,
"192.168.4."
,
"172.16."
,
"172.20."
,
"172.30."
};
whiteAddr
.
addAll
(
Arrays
.
asList
(
ips
));
}
/**
* 判断是否为白名单IP
* @param ipv4
* @return
*/
public
static
final
boolean
whiteOf
(
String
ipv4
){
if
(
ValidationUtil
.
validateIpv4
(
ipv4
)){
for
(
String
ipField
:
whiteAddr
){
if
(
ipv4
.
startsWith
(
ipField
)){
return
true
;
}
}
}
return
false
;
}
/**
/**
* 通过指定请求获得对应的远程ip地址
* 打印IP
* @param logger - 日志记录器
* @param request - 真实HttpServletRequest请求
*/
public
static
final
void
logIp
(
Logger
logger
,
HttpServletRequest
request
)
{
if
(
Objects
.
isNull
(
request
)){
return
;
}
String
remoteAddr
=
request
.
getRemoteAddr
();
String
xRealIp
=
IPUtil
.
getRemoteIP
(
request
);
String
xOriginalClientIp
=
request
.
getHeader
(
"x-original-client-ip"
);
logger
.
info
(
"Test ips:[client={}, old={}, new={}]"
,
remoteAddr
,
xRealIp
,
xOriginalClientIp
);
}
/**
* 获取请求客户端的真实ip地址
*
*
* @param request
* @param request
* @return
* @return
*/
*/
public
static
String
getRemoteIP
(
HttpServletRequest
request
)
{
public
static
String
getRemoteIP
(
HttpServletRequest
request
)
{
String
ip
=
request
.
getHeader
(
"x-real-ip"
);
String
ip
=
request
.
getHeader
(
"x-original-client-ip"
);
if
(
ValidationUtil
.
validateIpv4
(
ip
))
{
return
ip
;
}
// Todo - 以下为老代码,保留容错
ip
=
request
.
getHeader
(
"x-real-ip"
);
if
(
StringUtils
.
isEmpty
(
ip
))
{
if
(
StringUtils
.
isEmpty
(
ip
))
{
ip
=
request
.
getRemoteAddr
();
ip
=
request
.
getRemoteAddr
();
}
}
//过滤反向代理的ip
//过滤反向代理的ip
String
[]
stemps
=
ip
.
split
(
","
);
String
[]
stemps
=
ip
.
split
(
","
);
if
(
stemps
!=
null
&&
stemps
.
length
>=
1
)
{
if
(
stemps
!=
null
&&
stemps
.
length
>=
1
)
{
//得到第一个IP,即客户端真实IP
//得到第一个IP,即客户端真实IP
ip
=
stemps
[
0
];
ip
=
stemps
[
0
];
}
}
ip
=
ip
.
trim
();
ip
=
ip
.
trim
();
if
(
ip
.
length
()
>
23
)
{
if
(
ip
.
length
()
>
23
)
{
ip
=
ip
.
substring
(
0
,
23
);
ip
=
ip
.
substring
(
0
,
23
);
}
}
return
ip
;
return
ip
;
}
}
}
}
src/test/java/login/LoginForH5Tests.java
View file @
cdb2fe25
...
@@ -111,7 +111,6 @@ public class LoginForH5Tests {
...
@@ -111,7 +111,6 @@ public class LoginForH5Tests {
// 第一次使用TokenOnce
// 第一次使用TokenOnce
String
aspectUri
=
"/user/login/fastForH5"
;
String
aspectUri
=
"/user/login/fastForH5"
;
mvcResult
=
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
aspectUri
).
accept
(
MediaType
.
APPLICATION_JSON
)
mvcResult
=
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
aspectUri
).
accept
(
MediaType
.
APPLICATION_JSON
)
.
header
(
Constants
.
ONE_TIME_TOKEN
,
oneTimeToken
)
.
header
(
"authorization"
,
authorization
))
.
header
(
"authorization"
,
authorization
))
.
andExpect
(
status
().
isOk
())
.
andExpect
(
status
().
isOk
())
.
andReturn
();
.
andReturn
();
...
@@ -123,7 +122,6 @@ public class LoginForH5Tests {
...
@@ -123,7 +122,6 @@ public class LoginForH5Tests {
Assert
.
assertNotEquals
(
"0002"
,
businessCode
);
Assert
.
assertNotEquals
(
"0002"
,
businessCode
);
// 使用过期的TokenOnce与verificationCode
// 使用过期的TokenOnce与verificationCode
mvcResult
=
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
aspectUri
).
accept
(
MediaType
.
APPLICATION_JSON
)
mvcResult
=
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
aspectUri
).
accept
(
MediaType
.
APPLICATION_JSON
)
.
header
(
Constants
.
ONE_TIME_TOKEN
,
oneTimeToken
)
.
header
(
"authorization"
,
authorization
))
.
header
(
"authorization"
,
authorization
))
.
andExpect
(
status
().
isOk
())
.
andExpect
(
status
().
isOk
())
.
andReturn
();
.
andReturn
();
...
...
src/test/java/token/OneTimeTokenTests.java
View file @
cdb2fe25
...
@@ -98,7 +98,6 @@ public class OneTimeTokenTests {
...
@@ -98,7 +98,6 @@ public class OneTimeTokenTests {
// 第一次使用OneTime-Token
// 第一次使用OneTime-Token
String
aspectUri
=
"/user/loginForH5"
;
String
aspectUri
=
"/user/loginForH5"
;
mvcResult
=
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
aspectUri
).
accept
(
MediaType
.
APPLICATION_JSON
)
mvcResult
=
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
aspectUri
).
accept
(
MediaType
.
APPLICATION_JSON
)
.
param
(
Constants
.
ONE_TIME_TOKEN
,
oneTimeToken
)
.
param
(
"phoneNo"
,
userName
)
.
param
(
"phoneNo"
,
userName
)
.
param
(
"password"
,
password
))
.
param
(
"password"
,
password
))
.
andExpect
(
status
().
isOk
())
.
andExpect
(
status
().
isOk
())
...
@@ -111,7 +110,6 @@ public class OneTimeTokenTests {
...
@@ -111,7 +110,6 @@ public class OneTimeTokenTests {
Assert
.
assertNotEquals
(
"0002"
,
businessCode
);
Assert
.
assertNotEquals
(
"0002"
,
businessCode
);
// 使用过期的TokenOnce
// 使用过期的TokenOnce
mvcResult
=
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
aspectUri
).
accept
(
MediaType
.
APPLICATION_JSON
)
mvcResult
=
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
aspectUri
).
accept
(
MediaType
.
APPLICATION_JSON
)
.
param
(
Constants
.
ONE_TIME_TOKEN
,
oneTimeToken
)
.
param
(
"phoneNo"
,
userName
)
.
param
(
"phoneNo"
,
userName
)
.
param
(
"password"
,
password
))
.
param
(
"password"
,
password
))
.
andExpect
(
status
().
isOk
())
.
andExpect
(
status
().
isOk
())
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment