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
becc469f
Commit
becc469f
authored
Nov 08, 2017
by
技术部-任文超
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
给getHeaderParam方法添加失败返回
parent
f1bc1f94
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
179 additions
and
10 deletions
+179
-10
Constants.java
src/main/java/cn/quantgroup/xyqb/Constants.java
+3
-1
CaptchaFineteValidator.java
...uantgroup/xyqb/aspect/captcha/CaptchaFineteValidator.java
+15
-0
CaptchaFiniteValidateAdvisor.java
...oup/xyqb/aspect/captcha/CaptchaFiniteValidateAdvisor.java
+139
-0
CaptchaValidateAdvisor.java
...uantgroup/xyqb/aspect/captcha/CaptchaValidateAdvisor.java
+0
-4
UserController.java
...ntgroup/xyqb/controller/internal/user/UserController.java
+22
-5
No files found.
src/main/java/cn/quantgroup/xyqb/Constants.java
View file @
becc469f
...
...
@@ -37,7 +37,9 @@ public interface Constants {
String
REDIS_VOICE_DEVICE_COUNT
=
"Voice_Device_verification_code_count:"
;
String
REDIS_VERIFICATION_COUNT
=
"verification_code_count:"
;
final
Long
Image_Need_Count
=
3L
;
final
Long
Image_Need_Count
=
3L
;
final
Long
IMAGE_FINITE_COUNT
=
3L
;
/**
* redis中token的key值前缀
*/
...
...
src/main/java/cn/quantgroup/xyqb/aspect/captcha/CaptchaFineteValidator.java
0 → 100644
View file @
becc469f
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
0 → 100644
View file @
becc469f
package
cn
.
quantgroup
.
xyqb
.
aspect
.
captcha
;
import
cn.quantgroup.xyqb.Constants
;
import
cn.quantgroup.xyqb.model.JsonResult
;
import
cn.quantgroup.xyqb.thirdparty.jcaptcha.AbstractManageableImageCaptchaService
;
import
com.octo.captcha.service.CaptchaServiceException
;
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.beans.factory.annotation.Value
;
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.nio.charset.Charset
;
import
java.util.Optional
;
import
java.util.UUID
;
import
java.util.concurrent.TimeUnit
;
/**
* 限次图形验证码校验标记
* @author 任文超
* @version 1.0.0
* @since 2017-11-07
*/
@Aspect
@Component
public
class
CaptchaFiniteValidateAdvisor
{
private
static
final
Logger
LOGGER
=
LoggerFactory
.
getLogger
(
CaptchaFiniteValidateAdvisor
.
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
=
"__SUPERQG__"
;
private
static
final
String
IMAGE_CAPTCHA_ID_COUNT
=
"image:captcha_id:count:"
;
/**
* 图形验证码错误计数器生命周期,与图形验证码生命周期保持一致
* 参照点:cn.quantgroup.xyqb.config.captcha.RedisCaptchaStore{
* DEFAULT_EXPIRED_IN = 120L;
* DEFAULT_EXPIRED_TIMEUNIT = TimeUnit.SECONDS;
* }
*/
private
static
final
Long
SECONDS
=
2
*
60L
;
@Autowired
@Qualifier
(
"stringRedisTemplate"
)
private
RedisTemplate
<
String
,
String
>
redisTemplate
;
@Autowired
@Qualifier
(
"customCaptchaService"
)
private
AbstractManageableImageCaptchaService
imageCaptchaService
;
/**
* 自动化测试忽略验证码
*/
@Value
(
"${xyqb.auth.captcha.autotest.enable:false}"
)
private
boolean
autoTestCaptchaEnabled
;
/**
* 限次图形验证码切面
*/
@Pointcut
(
"@annotation(cn.quantgroup.xyqb.aspect.captcha.CaptchaFineteValidator)"
)
private
void
needCaptchaFiniteValidate
()
{
}
/**
* 在受保护的接口方法执行前, 执行限次图形验证码校验
*
* @param pjp
* @return
* @throws Throwable
*/
@Around
(
"needCaptchaFiniteValidate()"
)
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
();
}
if
(
captchaValue
!=
null
)
{
String
captcha
=
String
.
valueOf
(
captchaValue
);
// 忽略用户输入的大小写
captcha
=
StringUtils
.
lowerCase
(
captcha
);
// 验证码校验
Boolean
validCaptcha
=
false
;
Long
captchaCount
=
countCaptchaId
(
captchaId
);
if
(
captchaCount
==
null
||
captchaCount
>=
Constants
.
IMAGE_FINITE_COUNT
){
return
JsonResult
.
buildSuccessResult
(
"验证码失效,请重新获取"
,
""
,
2L
);
}
try
{
validCaptcha
=
imageCaptchaService
.
validateResponseForID
(
Constants
.
IMAGE_CAPTCHA_KEY
+
captchaId
,
captcha
);
}
catch
(
CaptchaServiceException
ex
)
{
LOGGER
.
error
(
"验证码校验异常, {}, {}"
,
ex
.
getMessage
(),
ex
);
}
if
(
validCaptcha
)
{
return
pjp
.
proceed
();
}
}
return
JsonResult
.
buildSuccessResult
(
"图形验证码不正确"
,
""
,
2L
);
}
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
));
}
private
Long
countCaptchaId
(
String
captchaId
)
{
String
captchaKey
=
getKey
(
captchaId
);
if
(
StringUtils
.
isBlank
(
captchaKey
)){
return
null
;
}
if
(!
redisTemplate
.
hasKey
(
captchaKey
))
{
redisTemplate
.
opsForValue
().
set
(
captchaKey
,
String
.
valueOf
(
0
),
SECONDS
,
TimeUnit
.
SECONDS
);
}
return
redisTemplate
.
opsForValue
().
increment
(
captchaKey
,
1L
);
}
private
final
static
String
getKey
(
String
captchaId
){
if
(
StringUtils
.
isBlank
(
captchaId
)){
return
null
;
}
return
IMAGE_CAPTCHA_ID_COUNT
+
captchaId
;
}
}
src/main/java/cn/quantgroup/xyqb/aspect/captcha/CaptchaValidateAdvisor.java
View file @
becc469f
...
...
@@ -103,19 +103,15 @@ public class CaptchaValidateAdvisor {
return
pjp
.
proceed
();
}
}
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
));
}
}
src/main/java/cn/quantgroup/xyqb/controller/internal/user/UserController.java
View file @
becc469f
package
cn
.
quantgroup
.
xyqb
.
controller
.
internal
.
user
;
import
cn.quantgroup.xyqb.Constants
;
import
cn.quantgroup.xyqb.aspect.captcha.CaptchaFineteValidator
;
import
cn.quantgroup.xyqb.aspect.captcha.CaptchaValidator
;
import
cn.quantgroup.xyqb.aspect.token.OneTimeTokenValidator
;
import
cn.quantgroup.xyqb.controller.IBaseController
;
...
...
@@ -41,7 +42,7 @@ import java.util.Map;
import
java.util.Random
;
/**
*
Created by FrankChow on 15/7/5.
*
Http服务接口:用户注册、登录、重置密码
*/
@RestController
@RequestMapping
(
"/user"
)
...
...
@@ -78,7 +79,10 @@ public class UserController implements IBaseController {
/**
* 登录(账号 + 密码),H5专用入口
* 登录(账号 + 密码)
* 密码错误达到限定次数时执行图形验证码校验
* 图形验证码累计错误达到限定次数时须重新获取
*
* @param channelId
* @param appChannel
* @param createdFrom
...
...
@@ -91,7 +95,7 @@ public class UserController implements IBaseController {
*/
@CaptchaValidator
@RequestMapping
(
"/loginForH5"
)
public
JsonResult
login
ForH5
(
public
JsonResult
login
WithFineteCaptcha
(
@RequestParam
(
required
=
false
,
defaultValue
=
"1"
)
Long
channelId
,
String
appChannel
,
@RequestParam
(
required
=
false
,
defaultValue
=
"1"
)
Long
createdFrom
,
@RequestParam
(
required
=
false
,
defaultValue
=
""
)
String
userId
,
...
...
@@ -103,6 +107,9 @@ public class UserController implements IBaseController {
/**
* 快速登录(手机号 + 短信验证码),H5专用入口
* 短信验证码错误达到限定次数时执行图形验证码校验
* 图形验证码累计错误达到限定次数时须重新获取
*
* @param channelId
* @param appChannel
* @param createdFrom
...
...
@@ -114,7 +121,7 @@ public class UserController implements IBaseController {
*/
@OneTimeTokenValidator
@RequestMapping
(
"/login/fastForH5"
)
public
JsonResult
loginFast
ForH5
(
public
JsonResult
loginFast
WithFineteCaptcha
(
@RequestParam
(
required
=
false
,
defaultValue
=
"1"
)
Long
channelId
,
String
appChannel
,
@RequestParam
(
required
=
false
,
defaultValue
=
"1"
)
Long
createdFrom
,
@RequestParam
(
required
=
false
,
defaultValue
=
"xyqb"
)
String
key
,
...
...
@@ -244,31 +251,41 @@ public class UserController implements IBaseController {
String
credential
=
request
.
getHeader
(
"authorization"
);
if
(
StringUtils
.
isBlank
(
credential
))
{
result
.
put
(
"fail"
,
JsonResult
.
buildErrorStateResult
(
"登录失败"
,
null
));
return
result
;
}
if
(!
credential
.
startsWith
(
verificationHeader
))
{
result
.
put
(
"fail"
,
JsonResult
.
buildErrorStateResult
(
"登录失败"
,
null
));
return
result
;
}
credential
=
credential
.
substring
(
verificationHeader
.
length
(),
credential
.
length
());
byte
[]
buf
=
Base64
.
decodeBase64
(
credential
);
boolean
validCharset
=
true
;
try
{
credential
=
new
String
(
buf
,
"UTF-8"
);
}
catch
(
UnsupportedEncodingException
e
)
{
LOGGER
.
error
(
"不支持的编码."
);
result
.
put
(
"fail"
,
JsonResult
.
buildErrorStateResult
(
"登录失败"
,
null
));
}
if
(!
validCharset
)
{
result
.
put
(
"fail"
,
JsonResult
.
buildErrorStateResult
(
"登录失败"
,
null
));
return
result
;
}
String
[]
credentialArr
=
credential
.
split
(
":"
);
if
(
credentialArr
.
length
!=
2
)
{
result
.
put
(
"fail"
,
JsonResult
.
buildErrorStateResult
(
"登录失败"
,
null
));
return
result
;
}
String
phoneNo
=
credentialArr
[
0
];
String
verificationCode
=
credentialArr
[
1
];
LOGGER
.
info
(
"用户快速登录,phoneNo:{} , verificationCode:{}"
,
phoneNo
,
verificationCode
);
if
(!
ValidationUtil
.
validatePhoneNo
(
phoneNo
))
{
result
.
put
(
"fail"
,
JsonResult
.
buildErrorStateResult
(
"登录失败"
,
null
));
return
result
;
}
if
(!
smsService
.
validateFastLoginVerificationCode
(
phoneNo
,
verificationCode
))
{
LOGGER
.
info
(
"用户快速登录,验证码校验失败,phoneNo:{} , verificationCode:{}"
,
phoneNo
,
verificationCode
);
result
.
put
(
"fail"
,
JsonResult
.
buildErrorStateResult
(
"验证码不正确"
,
null
));
return
result
;
}
result
.
put
(
"success"
,
JsonResult
.
buildSuccessResult
(
verificationCode
,
phoneNo
));
return
result
;
...
...
@@ -415,7 +432,7 @@ public class UserController implements IBaseController {
return
JsonResult
.
buildErrorStateResult
(
"密码应为6-12位"
,
null
);
}
smsValidForRegister
(
phoneNo
,
verificationCode
);
if
(
userService
.
exist
(
phoneNo
))
{
if
(
!
userService
.
exist
(
phoneNo
))
{
LOGGER
.
info
(
"修改密码失败,该手机号尚未注册, registerFrom:{}, phoneNo:{}"
,
registerFrom
,
phoneNo
);
return
JsonResult
.
buildErrorStateResult
(
"该手机号尚未注册"
,
null
);
}
...
...
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