Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
szpt
Project overview
Project overview
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
以墨为白
szpt
Commits
9425013f
Commit
9425013f
authored
Dec 28, 2024
by
以墨为白
🎧
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
签名优化
parent
86e5d1b2
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
148 additions
and
20 deletions
+148
-20
pom.xml
pom.xml
+6
-0
src/main/java/com/zksy/szpt/aspect/AuthAspect.java
src/main/java/com/zksy/szpt/aspect/AuthAspect.java
+1
-1
src/main/java/com/zksy/szpt/aspect/SignatureAspect.java
src/main/java/com/zksy/szpt/aspect/SignatureAspect.java
+1
-1
src/main/java/com/zksy/szpt/config/RedisConfig.java
src/main/java/com/zksy/szpt/config/RedisConfig.java
+108
-0
src/main/java/com/zksy/szpt/domain/HttpResultState.java
src/main/java/com/zksy/szpt/domain/HttpResultState.java
+1
-0
src/main/java/com/zksy/szpt/filter/SignatureVerificationFilter.java
...ava/com/zksy/szpt/filter/SignatureVerificationFilter.java
+22
-17
src/main/resources/application-dev.yml
src/main/resources/application-dev.yml
+6
-0
src/test/java/com/zksy/szpt/MainTest.java
src/test/java/com/zksy/szpt/MainTest.java
+3
-1
No files found.
pom.xml
View file @
9425013f
...
...
@@ -98,6 +98,12 @@
<artifactId>
spring-boot-starter-webflux
</artifactId>
</dependency>
<!--redis依赖配置-->
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-data-redis
</artifactId>
</dependency>
<dependency>
<groupId>
org.apache.commons
</groupId>
<artifactId>
commons-lang3
</artifactId>
...
...
src/main/java/com/zksy/szpt/aspect/AuthAspect.java
View file @
9425013f
...
...
@@ -76,7 +76,7 @@ public class AuthAspect {
return
joinPoint
.
proceed
();
}
else
{
//传递的签名没有通过
logger
.
info
(
"appKey:{}没有通过验证"
,
param
.
get
(
"appKey"
));
return
new
HttpResult
<
String
>(
HttpResultState
.
INVALID_
TOKEN
);
return
new
HttpResult
<
String
>(
HttpResultState
.
INVALID_
SIGNATURE
);
}
}
...
...
src/main/java/com/zksy/szpt/aspect/SignatureAspect.java
View file @
9425013f
...
...
@@ -57,7 +57,7 @@ public class SignatureAspect {
String
generatedSignature
=
DigestUtil
.
md5Hex
(
appId
+
nonce
+
timestamp
+
objectMapper
.
writeValueAsString
(
paramValues
[
0
])
+
appSecret
);
if
(!
generatedSignature
.
equals
(
signature
))
{
logger
.
error
(
"签名验证失败,请求参数:{}"
,
paramValues
[
0
]);
HttpResultState
httpResultState
=
HttpResultState
.
INVALID_
TOKEN
;
HttpResultState
httpResultState
=
HttpResultState
.
INVALID_
SIGNATURE
;
httpResultState
.
setMessage
(
"签名验证失败"
);
return
new
HttpResult
<
String
>(
httpResultState
);
}
else
{
...
...
src/main/java/com/zksy/szpt/config/RedisConfig.java
0 → 100644
View file @
9425013f
package
com
.
zksy
.
szpt
.
config
;
import
com.fasterxml.jackson.annotation.JsonAutoDetect
;
import
com.fasterxml.jackson.annotation.PropertyAccessor
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
org.springframework.cache.CacheManager
;
import
org.springframework.cache.annotation.CachingConfigurerSupport
;
import
org.springframework.cache.annotation.EnableCaching
;
import
org.springframework.cache.interceptor.KeyGenerator
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.data.redis.cache.RedisCacheConfiguration
;
import
org.springframework.data.redis.cache.RedisCacheManager
;
import
org.springframework.data.redis.connection.RedisConnectionFactory
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.data.redis.core.StringRedisTemplate
;
import
org.springframework.data.redis.listener.RedisMessageListenerContainer
;
import
org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer
;
import
org.springframework.data.redis.serializer.StringRedisSerializer
;
import
java.lang.reflect.Method
;
import
java.time.Duration
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.Map
;
import
java.util.Set
;
@Configuration
@EnableCaching
//开启注解式缓存
public
class
RedisConfig
extends
CachingConfigurerSupport
{
@Bean
public
RedisTemplate
<
String
,
Object
>
redisTemplate
(
RedisConnectionFactory
factory
)
{
RedisTemplate
<
String
,
Object
>
template
=
new
RedisTemplate
<
String
,
Object
>();
template
.
setConnectionFactory
(
factory
);
Jackson2JsonRedisSerializer
jackson2JsonRedisSerializer
=
new
Jackson2JsonRedisSerializer
(
Object
.
class
);
ObjectMapper
om
=
new
ObjectMapper
();
om
.
setVisibility
(
PropertyAccessor
.
ALL
,
JsonAutoDetect
.
Visibility
.
ANY
);
om
.
enableDefaultTyping
(
ObjectMapper
.
DefaultTyping
.
NON_FINAL
);
jackson2JsonRedisSerializer
.
setObjectMapper
(
om
);
StringRedisSerializer
stringRedisSerializer
=
new
StringRedisSerializer
();
// key采用String的序列化方式
template
.
setKeySerializer
(
stringRedisSerializer
);
// hash的key也采用String的序列化方式
template
.
setHashKeySerializer
(
stringRedisSerializer
);
// value序列化方式采用jackson
template
.
setValueSerializer
(
jackson2JsonRedisSerializer
);
// hash的value序列化方式采用jackson
template
.
setHashValueSerializer
(
jackson2JsonRedisSerializer
);
template
.
afterPropertiesSet
();
return
template
;
}
@Bean
@Override
public
KeyGenerator
keyGenerator
()
{
return
new
KeyGenerator
()
{
@Override
public
Object
generate
(
Object
target
,
Method
method
,
Object
...
params
)
{
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
target
.
getClass
().
getName
());
sb
.
append
(
method
.
getName
());
for
(
Object
obj
:
params
)
{
sb
.
append
(
obj
.
toString
());
}
return
sb
.
toString
();
}
};
}
@Bean
public
CacheManager
cacheManager
(
RedisConnectionFactory
redisConnectionFactory
)
{
//通过Spring提供的RedisCacheConfiguration类,构造一个自己的redis配置类,从该配置类中可以设置一些初始化的缓存命名空间
// 及对应的默认过期时间等属性,再利用RedisCacheManager中的builder.build()的方式生成cacheManager:
RedisCacheConfiguration
config
=
RedisCacheConfiguration
.
defaultCacheConfig
();
// 生成一个默认配置,通过config对象即可对缓存进行自定义配置
config
=
config
.
entryTtl
(
Duration
.
ofMinutes
(
1
))
// 设置缓存的默认过期时间,也是使用Duration设置
.
disableCachingNullValues
();
// 不缓存空值
// 设置一个初始化的缓存空间set集合
Set
<
String
>
cacheNames
=
new
HashSet
<>();
cacheNames
.
add
(
"my-redis-cache1"
);
cacheNames
.
add
(
"my-redis-cache2"
);
// 对每个缓存空间应用不同的配置
Map
<
String
,
RedisCacheConfiguration
>
configMap
=
new
HashMap
<>();
configMap
.
put
(
"my-redis-cache1"
,
config
);
configMap
.
put
(
"my-redis-cache2"
,
config
.
entryTtl
(
Duration
.
ofSeconds
(
120
)));
RedisCacheManager
cacheManager
=
RedisCacheManager
.
builder
(
redisConnectionFactory
)
// 使用自定义的缓存配置初始化一个cacheManager
.
initialCacheNames
(
cacheNames
)
// 注意这两句的调用顺序,一定要先调用该方法设置初始化的缓存名,再初始化相关的配置
.
withInitialCacheConfigurations
(
configMap
)
.
build
();
return
cacheManager
;
}
@Bean
public
StringRedisTemplate
stringRedisTemplate
(
RedisConnectionFactory
factory
)
{
StringRedisTemplate
stringRedisTemplate
=
new
StringRedisTemplate
();
stringRedisTemplate
.
setConnectionFactory
(
factory
);
return
stringRedisTemplate
;
}
//创建Redis消息监听者容器
@Bean
public
RedisMessageListenerContainer
redisMessageListenerContainer
(
RedisConnectionFactory
factory
)
{
RedisMessageListenerContainer
container
=
new
RedisMessageListenerContainer
();
container
.
setConnectionFactory
(
factory
);
return
container
;
}
}
\ No newline at end of file
src/main/java/com/zksy/szpt/domain/HttpResultState.java
View file @
9425013f
...
...
@@ -10,6 +10,7 @@ public enum HttpResultState {
MULTI_DEVICE_LOGIN
(
9040
,
"登录已失效,账户已在别处登录,请重新登录"
),
EXPIRE
(
9041
,
"登录已经过期,请重新登录"
),
INVALID_TOKEN
(
9042
,
"身份验证失败"
),
INVALID_SIGNATURE
(
9043
,
"签名验证失败"
),
GATEWAY
(
9050
,
"请求的服务不存在,请联系管理员"
),
...
...
src/main/java/com/zksy/szpt/filter/SignatureVerificationFilter.java
View file @
9425013f
...
...
@@ -12,6 +12,7 @@ import com.zksy.szpt.util.EncryptUtil;
import
com.zksy.szpt.util.SignatureUtil
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.http.MediaType
;
import
org.springframework.stereotype.Component
;
import
org.springframework.util.StreamUtils
;
...
...
@@ -26,6 +27,7 @@ import javax.servlet.http.HttpServletResponse;
import
java.io.IOException
;
import
java.nio.charset.StandardCharsets
;
import
java.util.Map
;
import
java.util.concurrent.TimeUnit
;
@Component
public
class
SignatureVerificationFilter
extends
OncePerRequestFilter
{
...
...
@@ -35,6 +37,9 @@ public class SignatureVerificationFilter extends OncePerRequestFilter {
@Resource
ObjectMapper
objectMapper
;
@Resource
private
RedisTemplate
<
String
,
Object
>
redisTemplate
;
private
final
AppStoreService
appStoreService
;
public
SignatureVerificationFilter
(
AppStoreService
appStoreService
)
{
...
...
@@ -75,28 +80,28 @@ public class SignatureVerificationFilter extends OncePerRequestFilter {
return
false
;
}
// timestamp 10分钟内有效
long
timestamp
=
Long
.
parseLong
(
timestampStr
);
long
currentTimestamp
=
System
.
currentTimeMillis
()
/
1000
;
if
(
Math
.
abs
(
currentTimestamp
-
timestamp
)
>
600
)
{
this
.
write
(
response
,
"请求已过期"
);
return
false
;
}
// 防止请求重放,nonce只能用一次,放在redis中,有效期 20分钟
String
nonceKey
=
"api_signature:nonce:"
+
nonce
;
if
(
Boolean
.
FALSE
.
equals
(
this
.
redisTemplate
.
opsForValue
().
setIfAbsent
(
nonceKey
,
"1"
,
20
,
TimeUnit
.
MINUTES
)))
{
this
.
write
(
response
,
"nonce无效"
);
return
false
;
}
// 校验appId
String
secretKey
=
this
.
appStoreService
.
getAppSecretByAppKey
(
appId
);
if
(!
StringUtils
.
hasText
(
secretKey
))
{
this
.
write
(
response
,
"appId无效"
);
return
false
;
}
// timestamp 10分钟内有效
// long timestamp = Long.parseLong(timestampStr);
// long currentTimestamp = System.currentTimeMillis() / 1000;
// if (Math.abs(currentTimestamp - timestamp) > 600) {
// this.write(response, "请求已过期");
// return false;
// }
// 防止请求重放,nonce只能用一次,放在redis中,有效期 20分钟
// String nonceKey = "SignatureVerificationFilter:nonce:" + nonce;
// if (!this.redisTemplate.opsForValue().setIfAbsent(nonceKey, "1", 20, TimeUnit.MINUTES)) {
// this.write(response, "nonce无效");
// return false;
// }
// 请求体
String
body
=
StreamUtils
.
copyToString
(
request
.
getInputStream
(),
StandardCharsets
.
UTF_8
);
body
=
objectMapper
.
writeValueAsString
(
objectMapper
.
readValue
(
body
,
Map
.
class
));
...
...
@@ -119,7 +124,7 @@ public class SignatureVerificationFilter extends OncePerRequestFilter {
* @throws IOException 如果写入失败
*/
private
void
write
(
HttpServletResponse
response
,
String
msg
)
throws
IOException
{
HttpResultState
httpResultState
=
HttpResultState
.
INVALID_
TOKEN
;
HttpResultState
httpResultState
=
HttpResultState
.
INVALID_
SIGNATURE
;
httpResultState
.
setMessage
(
msg
);
HttpResult
<
String
>
httpResult
=
new
HttpResult
<>(
httpResultState
);
response
.
setContentType
(
MediaType
.
APPLICATION_JSON_VALUE
);
...
...
src/main/resources/application-dev.yml
View file @
9425013f
...
...
@@ -5,3 +5,9 @@ spring:
password
:
123456
driver-class-name
:
com.mysql.cj.jdbc.Driver
type
:
com.alibaba.druid.pool.DruidDataSource
redis
:
database
:
0
port
:
6379
password
:
1qaz2wsx
timeout
:
1000
host
:
192.168.168.110
\ No newline at end of file
src/test/java/com/zksy/szpt/MainTest.java
View file @
9425013f
...
...
@@ -22,7 +22,7 @@ import javax.annotation.Resource;
@SpringBootTest
()
public
class
MainTest
{
String
nonce
=
"
nonce1
"
;
String
nonce
=
"
2
"
;
String
timestampStr
=
"21"
;
String
appId
=
"1"
;
...
...
@@ -39,6 +39,8 @@ public class MainTest {
@Test
@DisplayName
(
"任务完成情况"
)
public
void
xxRwwcqkTest
()
{
timestampStr
=
String
.
valueOf
(
System
.
currentTimeMillis
()
/
1000
);
String
secretKey
=
this
.
appStoreService
.
getAppSecretByAppKey
(
appId
);
Assertions
.
assertNotNull
(
secretKey
,
"appId不存在"
);
//断言appId存在,为空直接抛出异常不进行下一步测试,提高测试效率
// Assertions.fail(secretKey);
...
...
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