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
7f6a40eb
Commit
7f6a40eb
authored
Nov 03, 2017
by
技术部-任文超
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
更新One-Time Token获取策略,
优化UserController代码, 重新梳理用户安全问题解决方案的应对方法, 恢复旧接口的行为到分支初始状态
parent
072528aa
Changes
9
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
282 additions
and
360 deletions
+282
-360
Constants.java
src/main/java/cn/quantgroup/xyqb/Constants.java
+1
-1
OneTimeTokenValidateAdvisor.java
...tgroup/xyqb/aspect/token/OneTimeTokenValidateAdvisor.java
+85
-0
OneTimeTokenValidator.java
...n/quantgroup/xyqb/aspect/token/OneTimeTokenValidator.java
+2
-2
TokenOnceValidateAdvisor.java
...uantgroup/xyqb/aspect/token/TokenOnceValidateAdvisor.java
+0
-144
OneTimeTokenController.java
...yqb/controller/internal/token/OneTimeTokenController.java
+44
-0
UserController.java
...ntgroup/xyqb/controller/internal/user/UserController.java
+111
-111
RequestFilter.java
src/main/java/cn/quantgroup/xyqb/filter/RequestFilter.java
+1
-1
LoginForH5Tests.java
src/test/java/login/LoginForH5Tests.java
+17
-65
OneTimeTokenTests.java
src/test/java/token/OneTimeTokenTests.java
+21
-36
No files found.
src/main/java/cn/quantgroup/xyqb/Constants.java
View file @
7f6a40eb
...
@@ -12,7 +12,7 @@ public interface Constants {
...
@@ -12,7 +12,7 @@ public interface Constants {
String
PASSWORD_SALT
=
"_lkb"
;
String
PASSWORD_SALT
=
"_lkb"
;
String
IMAGE_CAPTCHA_KEY
=
"img_captcha:"
;
String
IMAGE_CAPTCHA_KEY
=
"img_captcha:"
;
String
TOKEN_ONCE_KEY_FOR_PHONE
=
"token_once:for_phone:
"
;
String
ONE_TIME_TOKEN
=
"One-Time-Token
"
;
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
+
"*"
;
...
...
src/main/java/cn/quantgroup/xyqb/aspect/token/OneTimeTokenValidateAdvisor.java
0 → 100644
View file @
7f6a40eb
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
(
"Token过期,请重新请求"
,
""
,
2L
);
}
/**
* 校验一次性令牌
* @return True or False
*/
private
boolean
oneTimeTokenValid
()
{
HttpServletRequest
request
=
((
ServletRequestAttributes
)
RequestContextHolder
.
getRequestAttributes
()).
getRequest
();
// 当前请求的OneTimeToken
String
oneTimeToken
=
request
.
getHeader
(
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
(
"Token过期,请重新请求, One-Time-Token={}, clientIp={}"
,
oneTimeToken
,
request
.
getRemoteAddr
());
}
return
valid
;
}
}
src/main/java/cn/quantgroup/xyqb/aspect/token/
TokenOnce
Validator.java
→
src/main/java/cn/quantgroup/xyqb/aspect/token/
OneTimeToken
Validator.java
View file @
7f6a40eb
...
@@ -3,7 +3,7 @@ package cn.quantgroup.xyqb.aspect.token;
...
@@ -3,7 +3,7 @@ package cn.quantgroup.xyqb.aspect.token;
import
java.lang.annotation.*
;
import
java.lang.annotation.*
;
/**
/**
*
需要单次
令牌校验标记
*
一次性
令牌校验标记
* @author 任文超
* @author 任文超
* @version 1.0.0
* @version 1.0.0
* @since 2017-10-31
* @since 2017-10-31
...
@@ -11,5 +11,5 @@ import java.lang.annotation.*;
...
@@ -11,5 +11,5 @@ import java.lang.annotation.*;
@Documented
@Documented
@Target
(
ElementType
.
METHOD
)
@Target
(
ElementType
.
METHOD
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
TokenOnce
Validator
{
public
@interface
OneTimeToken
Validator
{
}
}
src/main/java/cn/quantgroup/xyqb/aspect/token/TokenOnceValidateAdvisor.java
deleted
100644 → 0
View file @
072528aa
package
cn
.
quantgroup
.
xyqb
.
aspect
.
token
;
import
cn.quantgroup.xyqb.Constants
;
import
cn.quantgroup.xyqb.exception.VerificationCodeErrorException
;
import
cn.quantgroup.xyqb.model.JsonResult
;
import
cn.quantgroup.xyqb.util.ValidationUtil
;
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.io.UnsupportedEncodingException
;
import
java.nio.charset.Charset
;
import
java.util.Base64
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.Objects
;
/**
* 单次令牌校验切面
*
* @author 任文超
* @version 1.0.0
* @since 2017-10-31
*/
@Aspect
@Component
public
class
TokenOnceValidateAdvisor
{
private
static
final
Logger
LOGGER
=
LoggerFactory
.
getLogger
(
TokenOnceValidateAdvisor
.
class
);
@Autowired
@Qualifier
(
"stringRedisTemplate"
)
private
RedisTemplate
<
String
,
String
>
redisTemplate
;
/**
* 单次令牌校验切面
*/
@Pointcut
(
"@annotation(cn.quantgroup.xyqb.aspect.token.TokenOnceValidator)"
)
private
void
needTokenOnceValidate
()
{
}
/**
* 在受单次令牌保护的接口方法执行前, 执行单次令牌校验
*
* @throws Throwable
*/
@Around
(
"needTokenOnceValidate()"
)
private
Object
doTokenOnceValidate
(
ProceedingJoinPoint
pjp
)
throws
Throwable
{
boolean
checkTokenForPhone
=
checkTokenForPhone
();
if
(!
checkTokenForPhone
)
{
return
JsonResult
.
buildSuccessResult
(
"Token过期,请重新请求"
,
""
,
2L
);
}
return
pjp
.
proceed
();
}
/**
* 校验按手机号分发的单次令牌
* @return True or False
*/
private
boolean
checkTokenForPhone
()
{
HttpServletRequest
request
=
((
ServletRequestAttributes
)
RequestContextHolder
.
getRequestAttributes
()).
getRequest
();
Map
<
String
,
String
>
phoneTokenMap
=
getHeaderParam
(
request
);
if
(
phoneTokenMap
==
null
||
phoneTokenMap
.
isEmpty
()){
return
false
;
}
// 当前用户手机号
String
phoneNo
=
phoneTokenMap
.
get
(
"phoneNo"
);
// 当前请求的TokenOnce
String
requestToken
=
phoneTokenMap
.
get
(
"requestToken"
);
if
(
StringUtils
.
isBlank
(
phoneNo
)
||
StringUtils
.
isBlank
(
requestToken
)){
return
false
;
}
final
String
key
=
Constants
.
TOKEN_ONCE_KEY_FOR_PHONE
+
phoneNo
;
String
tokenOnce
=
redisTemplate
.
opsForValue
().
get
(
key
);
// TokenOnce不应为空值(空白、空格、null)
if
(
StringUtils
.
isBlank
(
tokenOnce
))
{
redisTemplate
.
delete
(
key
);
return
false
;
}
boolean
valid
=
Objects
.
equals
(
tokenOnce
,
requestToken
);
// TokenOnce校验正确时删除key
if
(
valid
)
{
redisTemplate
.
delete
(
key
);
}
else
{
LOGGER
.
info
(
"Token过期,请重新请求, token_once:for_phone:={}, requestToken={}, clientIp={}"
,
phoneNo
,
requestToken
,
request
.
getRemoteAddr
());
}
return
valid
;
}
/**
* 单次令牌参数解析
*
* @param request 当前请求,其首部行必须包含形如【TokenOnce MTM0NjEwNjc2NjI6NmFjMDY2NWItZTE5Yy00MzkyLWEyNDQtN2I2MTY5MDgzM2Y1】的UTF-8编码的Base64加密参数
* @return 令牌参数Map 或 null
*/
private
Map
<
String
,
String
>
getHeaderParam
(
HttpServletRequest
request
)
{
String
headerName
=
"TokenOnce"
;
String
credential
=
request
.
getHeader
(
headerName
);
if
(
StringUtils
.
isBlank
(
credential
))
{
LOGGER
.
info
(
"令牌参数无效, credential:{}"
,
credential
);
return
null
;
}
boolean
headerParamValid
=
true
;
byte
[]
buf
=
Base64
.
getDecoder
().
decode
(
credential
.
getBytes
());
credential
=
new
String
(
buf
,
Charset
.
forName
(
"UTF-8"
));
if
(!
headerParamValid
){
LOGGER
.
info
(
"令牌参数无效, credential:{}"
,
credential
);
return
null
;
}
String
[]
credentialArr
=
credential
.
split
(
":"
);
headerParamValid
=
headerParamValid
&&
credentialArr
.
length
==
2
;
if
(!
headerParamValid
)
{
LOGGER
.
info
(
"令牌参数无效, credential:{}"
,
credential
);
return
null
;
}
// 当前用户手机号
String
phoneNo
=
credentialArr
[
0
];
// 当前请求的TokenOnce
String
requestToken
=
credentialArr
[
1
];
headerParamValid
=
headerParamValid
&&
ValidationUtil
.
validatePhoneNo
(
phoneNo
);
if
(!
headerParamValid
)
{
LOGGER
.
info
(
"令牌参数无效, credential:{}"
,
credential
);
return
null
;
}
LOGGER
.
info
(
"获取单次令牌, phoneNo:{}, requestToken:{}"
,
phoneNo
,
requestToken
);
Map
<
String
,
String
>
phoneTokenMap
=
new
HashMap
<
String
,
String
>(
2
);
phoneTokenMap
.
put
(
"phoneNo"
,
phoneNo
);
phoneTokenMap
.
put
(
"requestToken"
,
requestToken
);
return
phoneTokenMap
;
}
}
src/main/java/cn/quantgroup/xyqb/controller/internal/token/
TokenOnce
Controller.java
→
src/main/java/cn/quantgroup/xyqb/controller/internal/token/
OneTimeToken
Controller.java
View file @
7f6a40eb
package
cn
.
quantgroup
.
xyqb
.
controller
.
internal
.
token
;
package
cn
.
quantgroup
.
xyqb
.
controller
.
internal
.
token
;
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
org.apache.commons.codec.binary.Base64
;
import
org.apache.commons.lang3.StringUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Qualifier
;
import
org.springframework.beans.factory.annotation.Qualifier
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.web.bind.annotation.ModelAttribute
;
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
javax.servlet.http.HttpServletRequest
;
import
java.nio.charset.Charset
;
import
java.util.UUID
;
import
java.util.UUID
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.TimeUnit
;
/**
/**
* 发放
单次
令牌
* 发放
一次性
令牌
*
*
* @author 任文超
* @author 任文超
* @version 1.0.0
* @version 1.0.0
...
@@ -28,32 +20,25 @@ import java.util.concurrent.TimeUnit;
...
@@ -28,32 +20,25 @@ import java.util.concurrent.TimeUnit;
*/
*/
@RestController
@RestController
@RequestMapping
(
"/token"
)
@RequestMapping
(
"/token"
)
public
class
TokenOnce
Controller
implements
IBaseController
{
public
class
OneTimeToken
Controller
implements
IBaseController
{
private
static
final
Logger
LOGGER
=
LoggerFactory
.
getLogger
(
TokenOnceController
.
class
);
private
static
final
Long
SECONDS
=
1
*
60L
;
private
static
final
Long
ONE_HOUR
=
10
*
60L
;
@Autowired
@Autowired
@Qualifier
(
"stringRedisTemplate"
)
@Qualifier
(
"stringRedisTemplate"
)
private
RedisTemplate
<
String
,
String
>
redisTemplate
;
private
RedisTemplate
<
String
,
String
>
redisTemplate
;
/**
/**
* 向指定用户账号(手机号)发放一枚TokenOnce
* 发放一枚一次性令牌
* TokenOnce用法:其首部行必须包含形如【TokenOnce MTM0NjEwNjc2NjI6NmFjMDY2NWItZTE5Yy00MzkyLWEyNDQtN2I2MTY5MDgzM2Y1】的UTF-8编码的Base64加密参数
* One-Time Token用法:http请求首部行添加参数{One-Time-Token 6ac0665b-e19c-4392-a244-7b61690833f5}
* 例如:Base64.getEncoder().encodeToString("13461067662:6ac0665b-e19c-4392-a244-7b61690833f5".getBytes(Charset.forName("UTF-8")));
*
*
* @param phoneNo 用户账号(手机号)
* @return 一次性令牌
* @return 单次令牌
*/
*/
@RequestMapping
(
value
=
"/once"
)
@RequestMapping
(
value
=
"/oneTime"
)
public
JsonResult
newTokenOnce
(
HttpServletRequest
request
,
@ModelAttribute
(
"phoneNo"
)
String
phoneNo
)
{
public
JsonResult
oneTimeToken
()
{
if
(
StringUtils
.
isBlank
(
phoneNo
)){
String
token
=
UUID
.
randomUUID
().
toString
();
return
JsonResult
.
buildErrorStateResult
(
"获取TokenOnce失败"
,
""
);
redisTemplate
.
opsForValue
().
set
(
token
,
Boolean
.
TRUE
.
toString
(),
SECONDS
,
TimeUnit
.
SECONDS
);
}
return
JsonResult
.
buildSuccessResult
(
""
,
token
);
String
tokenOnce
=
UUID
.
randomUUID
().
toString
();
final
String
key
=
Constants
.
TOKEN_ONCE_KEY_FOR_PHONE
+
phoneNo
;
redisTemplate
.
opsForValue
().
set
(
key
,
tokenOnce
,
ONE_HOUR
,
TimeUnit
.
SECONDS
);
return
JsonResult
.
buildSuccessResult
(
""
,
tokenOnce
);
}
}
}
}
src/main/java/cn/quantgroup/xyqb/controller/internal/user/UserController.java
View file @
7f6a40eb
This diff is collapsed.
Click to expand it.
src/main/java/cn/quantgroup/xyqb/filter/RequestFilter.java
View file @
7f6a40eb
...
@@ -27,7 +27,7 @@ public class RequestFilter implements Filter {
...
@@ -27,7 +27,7 @@ public class RequestFilter implements Filter {
private
static
final
String
[]
ALLOWED_PATTERNS
=
{
private
static
final
String
[]
ALLOWED_PATTERNS
=
{
"/user_detail/**"
,
"/hello/**"
,
"/innerapi/**"
,
"/user/exist"
,
"/motan/**"
,
"/user/register"
,
"/user/login"
,
"/user/register/fast"
,
"/user_detail/**"
,
"/hello/**"
,
"/innerapi/**"
,
"/user/exist"
,
"/motan/**"
,
"/user/register"
,
"/user/login"
,
"/user/register/fast"
,
"/token/on
c
e"
,
"/user/loginForH5"
,
"/user/register/fastForH5"
,
"/token/on
eTim
e"
,
"/user/loginForH5"
,
"/user/register/fastForH5"
,
"/auth/info/login"
,
"/user/login/fast"
,
"/user/reset_password"
,
"/user/exist_check"
,
"/user/center/**"
,
"/auth/info/login"
,
"/user/login/fast"
,
"/user/reset_password"
,
"/user/exist_check"
,
"/user/center/**"
,
"/jr58/**"
,
"/app/login"
,
"/app/login_super"
,
"/app/login2"
,
"/user/login2"
,
"/wechat/**"
,
"/config/**"
,
"/api/**"
,
"/user/exists_token"
,
"/query/**"
,
"/jr58/**"
,
"/app/login"
,
"/app/login_super"
,
"/app/login2"
,
"/user/login2"
,
"/wechat/**"
,
"/config/**"
,
"/api/**"
,
"/user/exists_token"
,
"/query/**"
,
"/platform/api/page/return_url"
,
"/MP_"
+
"/platform/api/page/return_url"
,
"/MP_"
+
...
...
src/test/java/login/Login
WithTokenOnce
Tests.java
→
src/test/java/login/Login
ForH5
Tests.java
View file @
7f6a40eb
package
login
;
package
login
;
import
cn.quantgroup.xyqb.Bootstrap
;
import
cn.quantgroup.xyqb.Bootstrap
;
import
cn.quantgroup.xyqb.Constants
;
import
com.alibaba.fastjson.JSON
;
import
com.alibaba.fastjson.JSON
;
import
com.alibaba.fastjson.JSONObject
;
import
com.alibaba.fastjson.JSONObject
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
com.octo.captcha.service.CaptchaServiceException
;
import
org.apache.commons.lang3.StringUtils
;
import
org.junit.Assert
;
import
org.junit.Assert
;
import
org.junit.Before
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.Test
;
...
@@ -21,13 +24,14 @@ import org.springframework.web.context.WebApplicationContext;
...
@@ -21,13 +24,14 @@ import org.springframework.web.context.WebApplicationContext;
import
java.nio.charset.Charset
;
import
java.nio.charset.Charset
;
import
java.util.Base64
;
import
java.util.Base64
;
import
java.util.Optional
;
import
static
org
.
springframework
.
test
.
web
.
servlet
.
result
.
MockMvcResultMatchers
.
status
;
import
static
org
.
springframework
.
test
.
web
.
servlet
.
result
.
MockMvcResultMatchers
.
status
;
@RunWith
(
SpringJUnit4ClassRunner
.
class
)
@RunWith
(
SpringJUnit4ClassRunner
.
class
)
@SpringApplicationConfiguration
(
classes
=
Bootstrap
.
class
)
@SpringApplicationConfiguration
(
classes
=
Bootstrap
.
class
)
@WebAppConfiguration
@WebAppConfiguration
public
class
Login
WithTokenOnce
Tests
{
public
class
Login
ForH5
Tests
{
final
String
phoneNo
=
"13461067662"
;
final
String
phoneNo
=
"13461067662"
;
final
String
userName
=
"root"
;
final
String
userName
=
"root"
;
final
String
password
=
"!QAZ2wsx"
;
final
String
password
=
"!QAZ2wsx"
;
...
@@ -54,71 +58,19 @@ public class LoginWithTokenOnceTests {
...
@@ -54,71 +58,19 @@ public class LoginWithTokenOnceTests {
.
andExpect
(
status
().
isOk
());
.
andExpect
(
status
().
isOk
());
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
"/user/login/fastForH5"
).
accept
(
MediaType
.
APPLICATION_JSON
))
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
"/user/login/fastForH5"
).
accept
(
MediaType
.
APPLICATION_JSON
))
.
andExpect
(
status
().
isOk
());
.
andExpect
(
status
().
isOk
());
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
"/api/captcha"
).
accept
(
MediaType
.
APPLICATION_JSON
))
.
andExpect
(
status
().
isOk
());
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
"/api/sms/send_login_code"
).
accept
(
MediaType
.
APPLICATION_JSON
))
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
"/api/sms/send_login_code"
).
accept
(
MediaType
.
APPLICATION_JSON
))
.
andExpect
(
status
().
isOk
());
.
andExpect
(
status
().
isOk
());
}
}
/**
/**
* 测试
TokenOnce发放服务
* 测试
图形验证码账密登录
* @throws Exception
* @throws Exception
*/
*/
@Test
@Test
public
void
testLoginFoH5
()
throws
Exception
{
public
void
testLoginFoH5
()
throws
Exception
{
// 获取TokenOnce
Assert
.
assertTrue
(
false
);
String
tokenOnceUri
=
"/token/once"
;
MvcResult
mvcResult
=
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
tokenOnceUri
).
accept
(
MediaType
.
APPLICATION_JSON
)
.
param
(
"phoneNo"
,
phoneNo
))
.
andExpect
(
status
().
isOk
())
.
andReturn
();
String
content
=
mvcResult
.
getResponse
().
getContentAsString
();
JSONObject
jsonResult
=
JSON
.
parseObject
(
new
String
(
content
));
Object
code
=
jsonResult
.
get
(
"code"
);
Assert
.
assertEquals
(
"0000"
,
code
);
Object
data
=
jsonResult
.
get
(
"data"
);
Assert
.
assertNotNull
(
data
);
StringBuilder
tokenBuilder
=
new
StringBuilder
(
phoneNo
);
String
tokenOnce
=
new
String
(
Base64
.
getEncoder
().
encodeToString
(
tokenBuilder
.
append
(
":"
).
append
(
data
).
toString
().
getBytes
(
Charset
.
forName
(
"UTF-8"
))));
StringBuilder
basicBuilder
=
new
StringBuilder
();
String
authorization
=
"Basic "
+
new
String
(
Base64
.
getEncoder
().
encodeToString
(
basicBuilder
.
append
(
userName
).
append
(
":"
).
append
(
password
).
toString
().
getBytes
(
Charset
.
forName
(
"UTF-8"
))));
// 第一次使用TokenOnce
String
aspectUri
=
"/user/loginForH5"
;
mvcResult
=
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
aspectUri
).
accept
(
MediaType
.
APPLICATION_JSON
)
.
header
(
"TokenOnce"
,
tokenOnce
)
.
header
(
"authorization"
,
authorization
)
.
param
(
"openId"
,
"none"
))
.
andExpect
(
status
().
isOk
())
.
andReturn
();
content
=
mvcResult
.
getResponse
().
getContentAsString
();
jsonResult
=
JSON
.
parseObject
(
new
String
(
content
));
code
=
jsonResult
.
get
(
"code"
);
Object
businessCode
=
jsonResult
.
get
(
"businessCode"
);
Assert
.
assertEquals
(
"0000"
,
code
);
Assert
.
assertNotEquals
(
"0002"
,
businessCode
);
// 使用过期的TokenOnce
mvcResult
=
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
aspectUri
).
accept
(
MediaType
.
APPLICATION_JSON
)
.
header
(
"TokenOnce"
,
tokenOnce
)
.
header
(
"authorization"
,
authorization
)
.
param
(
"openId"
,
"none"
))
.
andExpect
(
status
().
isOk
())
.
andReturn
();
content
=
mvcResult
.
getResponse
().
getContentAsString
();
jsonResult
=
JSON
.
parseObject
(
new
String
(
content
));
code
=
jsonResult
.
get
(
"code"
);
Assert
.
assertEquals
(
"0000"
,
code
);
businessCode
=
jsonResult
.
get
(
"businessCode"
);
Assert
.
assertEquals
(
"0002"
,
businessCode
);
// 不使用TokenOnce
mvcResult
=
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
aspectUri
).
accept
(
MediaType
.
APPLICATION_JSON
)
.
header
(
"authorization"
,
authorization
)
.
param
(
"openId"
,
"none"
))
.
andExpect
(
status
().
isOk
())
.
andReturn
();
content
=
mvcResult
.
getResponse
().
getContentAsString
();
jsonResult
=
JSON
.
parseObject
(
new
String
(
content
));
code
=
jsonResult
.
get
(
"code"
);
Assert
.
assertEquals
(
"0000"
,
code
);
businessCode
=
jsonResult
.
get
(
"businessCode"
);
Assert
.
assertEquals
(
"0002"
,
businessCode
);
}
}
/**
/**
...
@@ -128,8 +80,8 @@ public class LoginWithTokenOnceTests {
...
@@ -128,8 +80,8 @@ public class LoginWithTokenOnceTests {
@Test
@Test
public
void
testLoginFastFoH5
()
throws
Exception
{
public
void
testLoginFastFoH5
()
throws
Exception
{
// 获取TokenOnce
// 获取TokenOnce
String
tokenOnceUri
=
"/token/onc
e"
;
String
oneTimeTokenUri
=
"/token/oneTim
e"
;
MvcResult
mvcResult
=
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
tokenOnce
Uri
).
accept
(
MediaType
.
APPLICATION_JSON
)
MvcResult
mvcResult
=
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
oneTimeToken
Uri
).
accept
(
MediaType
.
APPLICATION_JSON
)
.
param
(
"phoneNo"
,
phoneNo
))
.
param
(
"phoneNo"
,
phoneNo
))
.
andExpect
(
status
().
isOk
())
.
andExpect
(
status
().
isOk
())
.
andReturn
();
.
andReturn
();
...
@@ -139,11 +91,11 @@ public class LoginWithTokenOnceTests {
...
@@ -139,11 +91,11 @@ public class LoginWithTokenOnceTests {
Assert
.
assertEquals
(
"0000"
,
code
);
Assert
.
assertEquals
(
"0000"
,
code
);
Object
data
=
jsonResult
.
get
(
"data"
);
Object
data
=
jsonResult
.
get
(
"data"
);
Assert
.
assertNotNull
(
data
);
Assert
.
assertNotNull
(
data
);
String
Builder
tokenBuilder
=
new
StringBuilder
(
phoneNo
);
String
oneTimeToken
=
String
.
valueOf
(
data
);
String
tokenOnce
=
new
String
(
Base64
.
getEncoder
().
encodeToString
(
tokenBuilder
.
append
(
":"
).
append
(
data
).
toString
().
getBytes
(
Charset
.
forName
(
"UTF-8"
)))
);
Assert
.
assertNotEquals
(
""
,
oneTimeToken
);
String
smsUri
=
"/api/sms/send_login_code"
;
String
smsUri
=
"/api/sms/send_login_code"
;
mvcResult
=
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
tokenOnce
Uri
).
accept
(
MediaType
.
APPLICATION_JSON
)
mvcResult
=
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
oneTimeToken
Uri
).
accept
(
MediaType
.
APPLICATION_JSON
)
.
param
(
"phoneNo"
,
phoneNo
))
.
param
(
"phoneNo"
,
phoneNo
))
.
andExpect
(
status
().
isOk
())
.
andExpect
(
status
().
isOk
())
.
andReturn
();
.
andReturn
();
...
@@ -159,7 +111,7 @@ public class LoginWithTokenOnceTests {
...
@@ -159,7 +111,7 @@ public class LoginWithTokenOnceTests {
// 第一次使用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
(
"TokenOnce"
,
tokenOnce
)
.
header
(
Constants
.
ONE_TIME_TOKEN
,
oneTimeToken
)
.
header
(
"authorization"
,
authorization
))
.
header
(
"authorization"
,
authorization
))
.
andExpect
(
status
().
isOk
())
.
andExpect
(
status
().
isOk
())
.
andReturn
();
.
andReturn
();
...
@@ -168,10 +120,10 @@ public class LoginWithTokenOnceTests {
...
@@ -168,10 +120,10 @@ public class LoginWithTokenOnceTests {
code
=
jsonResult
.
get
(
"code"
);
code
=
jsonResult
.
get
(
"code"
);
Object
businessCode
=
jsonResult
.
get
(
"businessCode"
);
Object
businessCode
=
jsonResult
.
get
(
"businessCode"
);
Assert
.
assertEquals
(
"0000"
,
code
);
Assert
.
assertEquals
(
"0000"
,
code
);
Assert
.
assertNotEquals
(
"000
1
"
,
businessCode
);
Assert
.
assertNotEquals
(
"000
2
"
,
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
(
"TokenOnce"
,
tokenOnce
)
.
header
(
Constants
.
ONE_TIME_TOKEN
,
oneTimeToken
)
.
header
(
"authorization"
,
authorization
))
.
header
(
"authorization"
,
authorization
))
.
andExpect
(
status
().
isOk
())
.
andExpect
(
status
().
isOk
())
.
andReturn
();
.
andReturn
();
...
...
src/test/java/token/
TokenOnce
Tests.java
→
src/test/java/token/
OneTimeToken
Tests.java
View file @
7f6a40eb
package
token
;
package
token
;
import
cn.quantgroup.xyqb.Bootstrap
;
import
cn.quantgroup.xyqb.Bootstrap
;
import
cn.quantgroup.xyqb.Constants
;
import
com.alibaba.fastjson.JSON
;
import
com.alibaba.fastjson.JSON
;
import
com.alibaba.fastjson.JSONObject
;
import
com.alibaba.fastjson.JSONObject
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
...
@@ -27,7 +28,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
...
@@ -27,7 +28,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
@RunWith
(
SpringJUnit4ClassRunner
.
class
)
@RunWith
(
SpringJUnit4ClassRunner
.
class
)
@SpringApplicationConfiguration
(
classes
=
Bootstrap
.
class
)
@SpringApplicationConfiguration
(
classes
=
Bootstrap
.
class
)
@WebAppConfiguration
@WebAppConfiguration
public
class
TokenOnce
Tests
{
public
class
OneTimeToken
Tests
{
final
String
phoneNo
=
"13461067662"
;
final
String
phoneNo
=
"13461067662"
;
private
MockMvc
mvc
;
private
MockMvc
mvc
;
...
@@ -48,70 +49,54 @@ public class TokenOnceTests {
...
@@ -48,70 +49,54 @@ public class TokenOnceTests {
public
void
testServer
()
throws
Exception
{
public
void
testServer
()
throws
Exception
{
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
"/"
).
accept
(
MediaType
.
APPLICATION_JSON
))
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
"/"
).
accept
(
MediaType
.
APPLICATION_JSON
))
.
andExpect
(
status
().
isOk
());
.
andExpect
(
status
().
isOk
());
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
"/token/on
c
e"
).
accept
(
MediaType
.
APPLICATION_JSON
))
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
"/token/on
eTim
e"
).
accept
(
MediaType
.
APPLICATION_JSON
))
.
andExpect
(
status
().
isOk
());
.
andExpect
(
status
().
isOk
());
}
}
/**
/**
* 测试
TokenOnce
发放服务
* 测试
OneTime-Token
发放服务
* @throws Exception
* @throws Exception
*/
*/
@Test
@Test
public
void
testTokenOnce
()
throws
Exception
{
public
void
testTokenOnce
()
throws
Exception
{
String
tokenOnceUri
=
"/token/once"
;
String
tokenOnceUri
=
"/token/oneTime"
;
MvcResult
mvcResult
=
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
tokenOnceUri
).
accept
(
MediaType
.
APPLICATION_JSON
)
MvcResult
mvcResult
=
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
tokenOnceUri
).
accept
(
MediaType
.
APPLICATION_JSON
))
.
header
(
"Session-Id"
,
"82107d0326772b8b5c72ec11801b8ab3"
))
.
andExpect
(
status
().
isOk
())
.
andExpect
(
status
().
isOk
())
.
andReturn
();
.
andReturn
();
String
content
=
mvcResult
.
getResponse
().
getContentAsString
();
String
content
=
mvcResult
.
getResponse
().
getContentAsString
();
JSONObject
jsonResult
=
JSON
.
parseObject
(
new
String
(
content
));
JSONObject
jsonResult
=
JSON
.
parseObject
(
new
String
(
content
));
Object
code
=
jsonResult
.
get
(
"code"
);
Object
code
=
jsonResult
.
get
(
"code"
);
Assert
.
assertEquals
(
"0000"
,
code
);
Assert
.
assertEquals
(
"0000"
,
code
);
Object
data
=
jsonResult
.
get
(
"data"
);
Object
data
=
jsonResult
.
getString
(
"data"
);
Assert
.
assertEquals
(
data
,
""
);
Object
msg
=
jsonResult
.
get
(
"msg"
);
Assert
.
assertEquals
(
"获取TokenOnce失败"
,
jsonResult
.
get
(
"msg"
));
jsonResult
=
JSON
.
parseObject
(
new
String
(
content
));
mvcResult
=
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
tokenOnceUri
).
accept
(
MediaType
.
APPLICATION_JSON
)
.
param
(
"phoneNo"
,
phoneNo
))
.
andExpect
(
status
().
isOk
())
.
andReturn
();
content
=
mvcResult
.
getResponse
().
getContentAsString
();
jsonResult
=
JSON
.
parseObject
(
new
String
(
content
));
code
=
jsonResult
.
get
(
"code"
);
Assert
.
assertEquals
(
"0000"
,
code
);
data
=
jsonResult
.
get
(
"data"
);
Assert
.
assertNotNull
(
data
);
Assert
.
assertNotNull
(
data
);
msg
=
jsonResult
.
get
(
"msg"
);
String
oneTimeToken
=
String
.
valueOf
(
data
);
Assert
.
assert
Equals
(
msg
,
""
);
Assert
.
assert
NotEquals
(
""
,
oneTimeToken
);
}
}
/**
/**
* 测试
TokenOnce
切面
* 测试
OneTime-Token
切面
* @throws Exception
* @throws Exception
*/
*/
// TODO 用户注册先不加
TokenOnce
校验,进一步确认后再添加或删除本用例
// TODO 用户注册先不加
OneTime-Token
校验,进一步确认后再添加或删除本用例
//@Test
//@Test
public
void
testAspect
()
throws
Exception
{
public
void
testAspect
()
throws
Exception
{
// 获取TokenOnce
// 获取OneTime-Token
String
tokenOnceUri
=
"/token/once"
;
String
oneTimeTokenUri
=
"/token/oneTime"
;
MvcResult
mvcResult
=
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
tokenOnceUri
).
accept
(
MediaType
.
APPLICATION_JSON
)
MvcResult
mvcResult
=
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
oneTimeTokenUri
).
accept
(
MediaType
.
APPLICATION_JSON
))
.
param
(
"phoneNo"
,
phoneNo
))
.
andExpect
(
status
().
isOk
())
.
andExpect
(
status
().
isOk
())
.
andReturn
();
.
andReturn
();
String
content
=
mvcResult
.
getResponse
().
getContentAsString
();
String
content
=
mvcResult
.
getResponse
().
getContentAsString
();
JSONObject
jsonResult
=
JSON
.
parseObject
(
new
String
(
content
));
JSONObject
jsonResult
=
JSON
.
parseObject
(
new
String
(
content
));
Object
code
=
jsonResult
.
get
(
"code"
);
Object
code
=
jsonResult
.
get
(
"code"
);
Assert
.
assertEquals
(
"0000"
,
code
);
Assert
.
assertEquals
(
"0000"
,
code
);
Object
data
=
jsonResult
.
get
(
"data"
);
Object
data
=
jsonResult
.
get
String
(
"data"
);
Assert
.
assertNotNull
(
data
);
Assert
.
assertNotNull
(
data
);
String
Builder
tokenBuilder
=
new
StringBuilder
(
phoneNo
);
String
oneTimeToken
=
String
.
valueOf
(
data
);
String
tokenOnce
=
new
String
(
Base64
.
getEncoder
().
encodeToString
(
tokenBuilder
.
append
(
":"
).
append
(
data
).
toString
().
getBytes
(
Charset
.
forName
(
"UTF-8"
)))
);
Assert
.
assertNotEquals
(
""
,
oneTimeToken
);
// 第一次使用
TokenOnce
// 第一次使用
OneTime-Token
String
aspectUri
=
"/user/
register
"
;
String
aspectUri
=
"/user/
loginForH5
"
;
mvcResult
=
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
aspectUri
).
accept
(
MediaType
.
APPLICATION_JSON
)
mvcResult
=
mvc
.
perform
(
MockMvcRequestBuilders
.
get
(
aspectUri
).
accept
(
MediaType
.
APPLICATION_JSON
)
.
header
(
"TokenOnce"
,
tokenOnce
)
.
header
(
Constants
.
ONE_TIME_TOKEN
,
oneTimeToken
)
.
param
(
"phoneNo"
,
phoneNo
)
.
param
(
"phoneNo"
,
phoneNo
)
.
param
(
"password"
,
"Qg123456"
)
.
param
(
"password"
,
"Qg123456"
)
.
param
(
"verificationCode"
,
"1234"
))
.
param
(
"verificationCode"
,
"1234"
))
...
@@ -125,7 +110,7 @@ public class TokenOnceTests {
...
@@ -125,7 +110,7 @@ public class TokenOnceTests {
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
)
.
header
(
"TokenOnce"
,
tokenOnce
)
.
header
(
"TokenOnce"
,
oneTimeToken
)
.
param
(
"phoneNo"
,
phoneNo
)
.
param
(
"phoneNo"
,
phoneNo
)
.
param
(
"password"
,
"Qg123456"
)
.
param
(
"password"
,
"Qg123456"
)
.
param
(
"verificationCode"
,
"1234"
))
.
param
(
"verificationCode"
,
"1234"
))
...
...
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