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
cbaf93de
Commit
cbaf93de
authored
Dec 26, 2024
by
以墨为白
🎧
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
1
parents
Changes
24
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
1587 additions
and
0 deletions
+1587
-0
.gitignore
.gitignore
+21
-0
pom.xml
pom.xml
+142
-0
src/main/java/com/zksy/szpt/Main.java
src/main/java/com/zksy/szpt/Main.java
+21
-0
src/main/java/com/zksy/szpt/aspect/AuthAspect.java
src/main/java/com/zksy/szpt/aspect/AuthAspect.java
+98
-0
src/main/java/com/zksy/szpt/aspect/GlobalExceptionHandler.java
...ain/java/com/zksy/szpt/aspect/GlobalExceptionHandler.java
+145
-0
src/main/java/com/zksy/szpt/aspect/ResponseBodyAnalysis.java
src/main/java/com/zksy/szpt/aspect/ResponseBodyAnalysis.java
+59
-0
src/main/java/com/zksy/szpt/aspect/SignatureAspect.java
src/main/java/com/zksy/szpt/aspect/SignatureAspect.java
+67
-0
src/main/java/com/zksy/szpt/config/MybatisConfig.java
src/main/java/com/zksy/szpt/config/MybatisConfig.java
+76
-0
src/main/java/com/zksy/szpt/config/WebConfig.java
src/main/java/com/zksy/szpt/config/WebConfig.java
+31
-0
src/main/java/com/zksy/szpt/controller/InfSettingController.java
...n/java/com/zksy/szpt/controller/InfSettingController.java
+21
-0
src/main/java/com/zksy/szpt/domain/HttpResult.java
src/main/java/com/zksy/szpt/domain/HttpResult.java
+70
-0
src/main/java/com/zksy/szpt/domain/HttpResultState.java
src/main/java/com/zksy/szpt/domain/HttpResultState.java
+49
-0
src/main/java/com/zksy/szpt/domain/dto/AppStoreDTO.java
src/main/java/com/zksy/szpt/domain/dto/AppStoreDTO.java
+42
-0
src/main/java/com/zksy/szpt/domain/po/AppStore.java
src/main/java/com/zksy/szpt/domain/po/AppStore.java
+45
-0
src/main/java/com/zksy/szpt/filter/ReusableBodyRequestWrapper.java
...java/com/zksy/szpt/filter/ReusableBodyRequestWrapper.java
+96
-0
src/main/java/com/zksy/szpt/filter/SignatureVerificationFilter.java
...ava/com/zksy/szpt/filter/SignatureVerificationFilter.java
+123
-0
src/main/java/com/zksy/szpt/mapper/AppStoreMapper.java
src/main/java/com/zksy/szpt/mapper/AppStoreMapper.java
+8
-0
src/main/java/com/zksy/szpt/service/AppStoreService.java
src/main/java/com/zksy/szpt/service/AppStoreService.java
+27
-0
src/main/java/com/zksy/szpt/util/EncryptUtil.java
src/main/java/com/zksy/szpt/util/EncryptUtil.java
+224
-0
src/main/java/com/zksy/szpt/util/SignatureUtil.java
src/main/java/com/zksy/szpt/util/SignatureUtil.java
+53
-0
src/main/resources/application-dev.yml
src/main/resources/application-dev.yml
+7
-0
src/main/resources/application.yml
src/main/resources/application.yml
+20
-0
src/main/resources/logback-spring.xml
src/main/resources/logback-spring.xml
+122
-0
src/test/java/com/zksy/szpt/MainTest.java
src/test/java/com/zksy/szpt/MainTest.java
+20
-0
No files found.
.gitignore
0 → 100644
View file @
cbaf93de
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
.mvn/wrapper/maven-wrapper.jar
# Eclipse m2e generated files
# Eclipse Core
.project
# JDT-specific (Eclipse Java Development Tools)
.classpath
# Intellij
*.iml
.idea/
logs/
pom.xml
0 → 100644
View file @
cbaf93de
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<modelVersion>
4.0.0
</modelVersion>
<groupId>
org.example
</groupId>
<artifactId>
szpt_pre_service2
</artifactId>
<version>
1.0-SNAPSHOT
</version>
<properties>
<mysql-connector.version>
8.0.16
</mysql-connector.version>
<java.version>
1.8
</java.version>
<project.build.sourceEncoding>
UTF-8
</project.build.sourceEncoding>
<project.reporting.outputEncoding>
UTF-8
</project.reporting.outputEncoding>
<spring-boot.version>
2.3.12.RELEASE
</spring-boot.version>
<druid.version>
1.1.10
</druid.version>
<swagger.version>
2.9.2
</swagger.version>
</properties>
<parent>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-parent
</artifactId>
<version>
2.3.12.RELEASE
</version>
<relativePath/>
<!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-web
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-test
</artifactId>
<scope>
test
</scope>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-aop
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-configuration-processor
</artifactId>
<optional>
true
</optional>
</dependency>
<!--启用热部署-->
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-devtools
</artifactId>
<optional>
true
</optional>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-validation
</artifactId>
<version>
2.3.1.RELEASE
</version>
</dependency>
<dependency>
<groupId>
com.baomidou
</groupId>
<artifactId>
mybatis-plus-boot-starter
</artifactId>
<version>
3.3.1
</version>
</dependency>
<dependency>
<groupId>
com.github.pagehelper
</groupId>
<artifactId>
pagehelper-spring-boot-starter
</artifactId>
<version>
1.2.5
</version>
<exclusions>
<exclusion>
<groupId>
org.mybatis
</groupId>
<artifactId>
mybatis
</artifactId>
</exclusion>
<exclusion>
<groupId>
org.mybatis
</groupId>
<artifactId>
mybatis-spring
</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>
mysql
</groupId>
<artifactId>
mysql-connector-java
</artifactId>
<version>
${mysql-connector.version}
</version>
</dependency>
<dependency>
<groupId>
com.alibaba
</groupId>
<artifactId>
druid
</artifactId>
<version>
${druid.version}
</version>
</dependency>
<dependency>
<groupId>
org.apache.commons
</groupId>
<artifactId>
commons-lang3
</artifactId>
</dependency>
<dependency>
<groupId>
cn.hutool
</groupId>
<artifactId>
hutool-all
</artifactId>
<version>
5.8.2
</version>
</dependency>
</dependencies>
<build>
<defaultGoal>
compile
</defaultGoal>
<finalName>
szpt_pre_service
</finalName>
<plugins>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-compiler-plugin
</artifactId>
<version>
3.1
</version>
<configuration>
<source>
1.8
</source>
<target>
1.8
</target>
<compilerArgs>
<arg>
-parameters
</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-maven-plugin
</artifactId>
</plugin>
</plugins>
<resources>
<resource>
<directory>
src/main/java
</directory>
<includes>
<include>
**/*.xml
</include>
</includes>
</resource>
<resource>
<directory>
src/main/resources
</directory>
</resource>
</resources>
</build>
</project>
src/main/java/com/zksy/szpt/Main.java
0 → 100644
View file @
cbaf93de
package
com
.
zksy
.
szpt
;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
import
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
;
import
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
;
import
org.springframework.boot.web.servlet.ServletComponentScan
;
/**
* Hello world!
*/
@SpringBootApplication
(
exclude
=
{
DataSourceAutoConfiguration
.
class
,
DataSourceTransactionManagerAutoConfiguration
.
class
,
})
@ServletComponentScan
public
class
Main
{
public
static
void
main
(
String
[]
args
)
{
SpringApplication
.
run
(
Main
.
class
,
args
);
}
}
src/main/java/com/zksy/szpt/aspect/AuthAspect.java
0 → 100644
View file @
cbaf93de
package
com
.
zksy
.
szpt
.
aspect
;
import
com.zksy.szpt.domain.HttpResult
;
import
com.zksy.szpt.domain.HttpResultState
;
import
com.zksy.szpt.service.AppStoreService
;
import
com.zksy.szpt.util.EncryptUtil
;
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.aspectj.lang.reflect.CodeSignature
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.stereotype.Component
;
import
org.springframework.web.context.request.RequestContextHolder
;
import
org.springframework.web.context.request.ServletRequestAttributes
;
import
javax.annotation.Resource
;
import
javax.servlet.http.HttpServletRequest
;
import
java.util.*
;
//@Aspect//声明切面,标记类(1时间,2地点,3内容)
//@Component
public
class
AuthAspect
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
AuthAspect
.
class
);
@Resource
AppStoreService
appStoreService
;
//
@Pointcut
(
"execution( * com.zksy.szpt.controller.*.*(..))"
)
private
void
auth
()
{
}
@Around
(
value
=
"auth()"
)
public
Object
auth
(
ProceedingJoinPoint
joinPoint
)
throws
Throwable
{
ServletRequestAttributes
attributes
=
(
ServletRequestAttributes
)
RequestContextHolder
.
getRequestAttributes
();
HttpServletRequest
request
=
attributes
.
getRequest
();
Object
[]
paramValues
=
joinPoint
.
getArgs
();
String
[]
paramNames
=
((
CodeSignature
)
joinPoint
.
getSignature
()).
getParameterNames
();
// 按请求参数名及参数值相互连接组成一个字符串
Map
<
String
,
String
>
param
=
new
HashMap
<>();
for
(
int
i
=
0
;
i
<
paramNames
.
length
;
i
++)
{
if
(
paramValues
[
i
]
instanceof
Map
)
{
//接口参数
Map
<
String
,
Object
>
bodyPara
=
(
Map
<
String
,
Object
>)
paramValues
[
i
];
Iterator
<
Map
.
Entry
<
String
,
Object
>>
iterator
=
bodyPara
.
entrySet
().
iterator
();
while
(
iterator
.
hasNext
())
{
Map
.
Entry
<
String
,
Object
>
entry
=
iterator
.
next
();
String
key
=
entry
.
getKey
();
Object
value
=
entry
.
getValue
();
param
.
put
(
key
,
value
==
null
?
""
:
value
.
toString
());
}
}
else
{
//系统级参数
param
.
put
(
paramNames
[
i
],
paramValues
[
i
].
toString
());
}
}
String
appSecret
=
appStoreService
.
getAppSecretByAppKey
(
param
.
get
(
"appKey"
));
//appKey不存在
if
(
appSecret
==
null
)
{
HttpResultState
httpResultState
=
HttpResultState
.
NOTIFICATION
;
logger
.
info
(
"appKey:{}不存在"
,
param
.
get
(
"appKey"
));
httpResultState
.
setMessage
(
"不存在的appKey"
);
return
new
HttpResult
<
String
>(
httpResultState
);
}
//客户端传递过来的签名
String
clientSign
=
param
.
get
(
"sign"
);
param
.
remove
(
"sign"
);
//根据客户端的参数生成的签名
String
serverSign
=
EncryptUtil
.
getInstance
().
shaEncode
(
appSecret
+
sortJoin
(
param
)
+
appSecret
);
//传递的签名通过
if
(
serverSign
.
equals
(
clientSign
))
{
return
joinPoint
.
proceed
();
}
else
{
//传递的签名没有通过
logger
.
info
(
"appKey:{}没有通过验证"
,
param
.
get
(
"appKey"
));
return
new
HttpResult
<
String
>(
HttpResultState
.
INVALID_TOKEN
);
}
}
private
String
sortJoin
(
Map
<
String
,
String
>
map
)
{
// 移除值为空的
map
.
entrySet
().
removeIf
(
entry
->
Objects
.
isNull
(
entry
.
getValue
())
||
""
.
equals
(
entry
.
getValue
()));
List
<
Map
.
Entry
<
String
,
String
>>
infoIds
=
new
ArrayList
<>(
map
.
entrySet
());
// 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序)
infoIds
.
sort
((
o1
,
o2
)
->
o1
.
getKey
().
compareToIgnoreCase
(
o2
.
getKey
()));
StringBuilder
sb
=
new
StringBuilder
();
for
(
Map
.
Entry
<
String
,
String
>
infoId
:
infoIds
)
{
sb
.
append
(
infoId
.
getKey
());
// sb.append("=");
sb
.
append
(
infoId
.
getValue
());
// sb.append("&");
}
return
sb
.
substring
(
0
,
sb
.
length
());
}
}
src/main/java/com/zksy/szpt/aspect/GlobalExceptionHandler.java
0 → 100644
View file @
cbaf93de
package
com
.
zksy
.
szpt
.
aspect
;
import
com.zksy.szpt.domain.HttpResult
;
import
com.zksy.szpt.domain.HttpResultState
;
import
org.apache.ibatis.javassist.NotFoundException
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.dao.DataAccessException
;
import
org.springframework.dao.DuplicateKeyException
;
import
org.springframework.http.converter.HttpMessageNotReadableException
;
import
org.springframework.web.bind.MethodArgumentNotValidException
;
import
org.springframework.web.bind.MissingServletRequestParameterException
;
import
org.springframework.web.bind.annotation.ControllerAdvice
;
import
org.springframework.web.bind.annotation.ExceptionHandler
;
import
org.springframework.web.bind.annotation.ResponseBody
;
import
org.springframework.web.method.annotation.MethodArgumentTypeMismatchException
;
import
org.springframework.web.servlet.NoHandlerFoundException
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.validation.ConstraintViolationException
;
import
java.util.stream.Collectors
;
/**
* Created by wcy on 2024/12/26.
* 全局异常处理,包括404
*/
@ControllerAdvice
public
class
GlobalExceptionHandler
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
GlobalExceptionHandler
.
class
);
//一般错误
@ExceptionHandler
(
value
=
Exception
.
class
)
@ResponseBody
public
HttpResult
<
HttpResultState
>
defaultErrorHandle
(
HttpServletRequest
req
,
Exception
e
)
{
logger
.
error
(
"错误信息如下:"
,
e
);
HttpResultState
state
=
HttpResultState
.
ERROR
;
return
new
HttpResult
<>(
state
);
}
//not found
@ResponseBody
@ExceptionHandler
(
value
=
{
NotFoundException
.
class
,
NoHandlerFoundException
.
class
})
public
HttpResult
<
HttpResultState
>
handlerNotFoundException
(
HttpServletRequest
req
,
Exception
e
)
{
HttpResultState
state
=
HttpResultState
.
NOT_FOUND
;
state
.
setMessage
(
"请求的资源"
+
req
.
getRequestURL
()
+
"不存在"
);
return
new
HttpResult
<>(
state
);
}
//region 输入参数相关的异常
//valid注解
//(Bean 校验异常)
@ExceptionHandler
(
value
=
MethodArgumentNotValidException
.
class
)
@ResponseBody
public
HttpResult
<
HttpResultState
>
handlerMethodArgumentNotValidException
(
HttpServletRequest
req
,
MethodArgumentNotValidException
e
)
{
logger
.
warn
(
e
.
getMessage
());
HttpResultState
state
=
HttpResultState
.
INVALID_PARAMETER
;
state
.
setMessage
(
e
.
getBindingResult
().
getFieldErrors
().
stream
().
map
(
k
->
k
.
getField
()
+
"["
+
k
.
getRejectedValue
()
+
"]"
+
k
.
getDefaultMessage
()).
collect
(
Collectors
.
joining
(
";"
)));
return
new
HttpResult
<>(
state
);
}
//validate注解
//(方法参数校验异常)如实体类中的@Size注解配置和数据库中该字段的长度不统一等问题
@ExceptionHandler
(
value
=
ConstraintViolationException
.
class
)
@ResponseBody
public
HttpResult
<
HttpResultState
>
handlerConstraintViolationException
(
HttpServletRequest
req
,
ConstraintViolationException
e
)
{
logger
.
warn
(
e
.
getMessage
());
HttpResultState
state
=
HttpResultState
.
INVALID_PARAMETER
;
state
.
setMessage
(
e
.
getMessage
());
return
new
HttpResult
<>(
state
);
}
//RequestBody反序列化失败
@ResponseBody
@ExceptionHandler
({
HttpMessageNotReadableException
.
class
})
public
HttpResult
<
HttpResultState
>
messageExceptionHandler
(
HttpMessageNotReadableException
e
)
{
logger
.
warn
(
"http请求参数转换异常: "
+
e
.
getMessage
());
HttpResultState
state
=
HttpResultState
.
INVALID_PARAMETER
;
state
.
setMessage
(
"请求参数不正确"
);
return
new
HttpResult
<>(
state
);
}
//RequestParam参数缺失
@ResponseBody
@ExceptionHandler
({
MissingServletRequestParameterException
.
class
})
public
HttpResult
<
HttpResultState
>
MissParameterExceptionHandler
(
MissingServletRequestParameterException
e
)
{
logger
.
warn
(
e
.
getMessage
());
HttpResultState
state
=
HttpResultState
.
INVALID_PARAMETER
;
state
.
setMessage
(
e
.
getMessage
());
return
new
HttpResult
<>(
state
);
}
//RequestParam参数类型错误
@ResponseBody
@ExceptionHandler
({
MethodArgumentTypeMismatchException
.
class
})
public
HttpResult
<
HttpResultState
>
MethodArgumentTypeMismatchExceptionHandler
(
MethodArgumentTypeMismatchException
e
)
{
logger
.
warn
(
e
.
getMessage
());
HttpResultState
state
=
HttpResultState
.
INVALID_PARAMETER
;
state
.
setMessage
(
e
.
getCause
().
getMessage
());
return
new
HttpResult
<>(
state
);
}
// @ResponseBody
// @ExceptionHandler({ParameterDataTypeException.class})
// public HttpResult<HttpResultState> ParameterDataTypeExceptionHandler(ParameterDataTypeException e) {
// logger.warn(e.getMessage());
// HttpResultState state = HttpResultState.INVALID_PARAMETER;
// state.setMessage(e.getMessage());
// return new HttpResult<>(state);
// }
//endregion
//region 数据库相关异常
//处理数据层面的顶级异常
@ResponseBody
@ExceptionHandler
({
DataAccessException
.
class
})
public
HttpResult
<
HttpResultState
>
DataAccessExceptionHandler
(
DataAccessException
e
)
{
logger
.
error
(
e
.
getMessage
());
HttpResultState
state
=
HttpResultState
.
DATABASE
;
return
new
HttpResult
<>(
state
);
}
//违反唯一约束
@ResponseBody
@ExceptionHandler
({
DuplicateKeyException
.
class
})
public
HttpResult
<
HttpResultState
>
DuplicateKeyExceptionHandler
(
DuplicateKeyException
e
)
{
logger
.
warn
(
e
.
getMessage
());
HttpResultState
state
=
HttpResultState
.
DUPLICATED_KEY
;
state
.
setMessage
(
e
.
getCause
().
getMessage
());
return
new
HttpResult
<>(
state
);
}
//endregion
// @ResponseBody
// @ExceptionHandler({NotificationException.class})
// public HttpResult<HttpResultState> NotificationExceptionHandler(NotificationException e) {
// HttpResultState state = HttpResultState.NOTIFICATION;
// state.setMessage(e.getMessage());
// return new HttpResult<>(state);
// }
}
src/main/java/com/zksy/szpt/aspect/ResponseBodyAnalysis.java
0 → 100644
View file @
cbaf93de
package
com
.
zksy
.
szpt
.
aspect
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.zksy.szpt.domain.HttpResult
;
import
org.springframework.core.MethodParameter
;
import
org.springframework.http.MediaType
;
import
org.springframework.http.server.ServerHttpRequest
;
import
org.springframework.http.server.ServerHttpResponse
;
import
org.springframework.web.bind.annotation.RestControllerAdvice
;
import
org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Type
;
@RestControllerAdvice
(
basePackages
=
"com.zksy.szpt.controller"
)
public
class
ResponseBodyAnalysis
implements
ResponseBodyAdvice
{
private
final
ObjectMapper
Mapper
;
public
ResponseBodyAnalysis
(
ObjectMapper
mapper
)
{
Mapper
=
mapper
;
}
@Override
public
Object
beforeBodyWrite
(
Object
body
,
MethodParameter
arg1
,
MediaType
arg2
,
Class
arg3
,
ServerHttpRequest
arg4
,
ServerHttpResponse
arg5
)
{
if
(
body
instanceof
HttpResult
)
{
return
body
;
//异常处理
}
else
{
HttpResult
httpResult
=
new
HttpResult
(
body
);
if
(
body
instanceof
String
)
{
//如果control层返回的结果是字符串,则需要手动转换
try
{
return
Mapper
.
writeValueAsString
(
httpResult
);
}
catch
(
JsonProcessingException
e
)
{
}
}
else
if
(
body
==
null
)
{
//特殊情况需要,string却返回null的时候
Method
method
=
arg1
.
getMethod
();
Type
type
=
method
.
getReturnType
();
if
(
"java.lang.String"
.
equals
(
type
.
getTypeName
()))
{
try
{
return
Mapper
.
writeValueAsString
(
httpResult
);
}
catch
(
JsonProcessingException
e
)
{
}
}
}
return
httpResult
;
//其他类型处理
}
}
@Override
public
boolean
supports
(
MethodParameter
arg0
,
Class
arg1
)
{
return
true
;
}
}
\ No newline at end of file
src/main/java/com/zksy/szpt/aspect/SignatureAspect.java
0 → 100644
View file @
cbaf93de
package
com
.
zksy
.
szpt
.
aspect
;
import
cn.hutool.crypto.digest.DigestUtil
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.zksy.szpt.domain.HttpResult
;
import
com.zksy.szpt.domain.HttpResultState
;
import
com.zksy.szpt.service.AppStoreService
;
import
com.zksy.szpt.util.EncryptUtil
;
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.aspectj.lang.reflect.CodeSignature
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.stereotype.Component
;
import
org.springframework.web.context.request.RequestContextHolder
;
import
org.springframework.web.context.request.ServletRequestAttributes
;
import
javax.annotation.Resource
;
import
javax.servlet.http.HttpServletRequest
;
@Aspect
//声明切面,标记类(1时间,2地点,3内容)
@Component
public
class
SignatureAspect
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
AuthAspect
.
class
);
@Resource
AppStoreService
appStoreService
;
@Resource
ObjectMapper
objectMapper
;
//
@Pointcut
(
"execution( * com.zksy.szpt.controller.*.*(..))"
)
private
void
auth
()
{
}
@Around
(
value
=
"auth()"
)
public
Object
auth
(
ProceedingJoinPoint
joinPoint
)
throws
Throwable
{
ServletRequestAttributes
attributes
=
(
ServletRequestAttributes
)
RequestContextHolder
.
getRequestAttributes
();
HttpServletRequest
request
=
attributes
.
getRequest
();
Object
[]
paramValues
=
joinPoint
.
getArgs
();
String
[]
paramNames
=
((
CodeSignature
)
joinPoint
.
getSignature
()).
getParameterNames
();
// 获取请求头中的参数
String
appId
=
request
.
getHeader
(
"appId"
);
String
nonce
=
request
.
getHeader
(
"nonce"
);
String
timestamp
=
request
.
getHeader
(
"timestamp"
);
String
signature
=
request
.
getHeader
(
"signature"
);
String
appSecret
=
appStoreService
.
getAppSecretByAppKey
(
appId
);
// String generatedSignature = EncryptUtil.getInstance().shaEncode(appId + nonce + timestamp + objectMapper.writeValueAsString(paramValues[0]) + appSecret);
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
.
setMessage
(
"签名验证失败"
);
return
new
HttpResult
<
String
>(
httpResultState
);
}
else
{
return
joinPoint
.
proceed
();
}
}
}
src/main/java/com/zksy/szpt/config/MybatisConfig.java
0 → 100644
View file @
cbaf93de
package
com
.
zksy
.
szpt
.
config
;
import
com.alibaba.druid.pool.DruidDataSource
;
import
com.baomidou.mybatisplus.core.MybatisConfiguration
;
import
com.github.pagehelper.PageInterceptor
;
import
org.apache.ibatis.plugin.Interceptor
;
import
org.apache.ibatis.session.SqlSessionFactory
;
import
org.mybatis.spring.SqlSessionFactoryBean
;
import
org.mybatis.spring.SqlSessionTemplate
;
import
org.mybatis.spring.annotation.MapperScan
;
import
org.springframework.beans.factory.annotation.Qualifier
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
org.springframework.boot.jdbc.DataSourceBuilder
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Primary
;
import
org.springframework.core.io.support.PathMatchingResourcePatternResolver
;
import
org.springframework.jdbc.datasource.DataSourceTransactionManager
;
import
javax.sql.DataSource
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.List
;
import
java.util.Properties
;
@Configuration
@MapperScan
(
basePackages
=
{
"com.zksy.szpt.mapper"
},
sqlSessionTemplateRef
=
"sqlSessionTemplate"
)
public
class
MybatisConfig
{
@Bean
(
name
=
"dataSource"
)
@Primary
@ConfigurationProperties
(
prefix
=
"spring.datasource"
)
public
DataSource
getDateSource
()
{
return
DataSourceBuilder
.
create
().
type
(
DruidDataSource
.
class
).
build
();
}
@Bean
(
name
=
"sqlSessionFactory"
)
@Primary
public
SqlSessionFactory
getSqlSessionFactory
(
@Qualifier
(
"dataSource"
)
DataSource
datasource
)
throws
Exception
{
SqlSessionFactoryBean
bean
=
new
SqlSessionFactoryBean
();
bean
.
setDataSource
(
datasource
);
MybatisConfiguration
configuration
=
new
MybatisConfiguration
();
configuration
.
setCallSettersOnNulls
(
true
);
configuration
.
setMapUnderscoreToCamelCase
(
true
);
configuration
.
setLogImpl
(
org
.
apache
.
ibatis
.
logging
.
slf4j
.
Slf4jImpl
.
class
);
bean
.
setConfiguration
(
configuration
);
Interceptor
interceptor
=
new
PageInterceptor
();
Properties
properties
=
new
Properties
();
properties
.
setProperty
(
"helperDialect"
,
"mysql"
);
interceptor
.
setProperties
(
properties
);
bean
.
setPlugins
(
interceptor
);
org
.
springframework
.
core
.
io
.
Resource
[]
resources1
=
new
PathMatchingResourcePatternResolver
().
getResources
(
"classpath*:mapper/*.xml"
);
List
<
org
.
springframework
.
core
.
io
.
Resource
>
list
=
new
ArrayList
<>(
Arrays
.
asList
(
resources1
));
list
.
addAll
(
new
ArrayList
<>(
Arrays
.
asList
(
resources1
)));
bean
.
setMapperLocations
(
list
.
toArray
(
new
org
.
springframework
.
core
.
io
.
Resource
[
0
]));
return
bean
.
getObject
();
}
@Primary
@Bean
(
name
=
"transactionManager"
)
public
DataSourceTransactionManager
getTransactionManager
()
{
return
new
DataSourceTransactionManager
(
getDateSource
());
}
@Bean
(
"sqlSessionTemplate"
)
// 表示这个数据源是默认数据源
@Primary
public
SqlSessionTemplate
getSqlSessionTemplate
(
@Qualifier
(
"sqlSessionFactory"
)
SqlSessionFactory
sessionFactory
)
{
return
new
SqlSessionTemplate
(
sessionFactory
);
}
}
src/main/java/com/zksy/szpt/config/WebConfig.java
0 → 100644
View file @
cbaf93de
package
com
.
zksy
.
szpt
.
config
;
import
org.springframework.stereotype.Component
;
import
org.springframework.web.servlet.config.annotation.InterceptorRegistration
;
import
org.springframework.web.servlet.config.annotation.InterceptorRegistry
;
import
org.springframework.web.servlet.config.annotation.WebMvcConfigurer
;
import
javax.annotation.Resource
;
@Component
public
class
WebConfig
implements
WebMvcConfigurer
{
@Override
public
void
addInterceptors
(
InterceptorRegistry
registry
)
{
// 多个拦截器组成一个拦截器链
// InterceptorRegistration interceptorRegistration = registry.addInterceptor(signatureInterceptor).order(1);
// addPathPatterns 用于添加拦截规则
// interceptorRegistration.addPathPatterns("/**");
// excludePathPatterns 用户排除拦截
//排除swagger
// interceptorRegistration.excludePathPatterns("/v2/**");
// interceptorRegistration.excludePathPatterns("/webjars/**");
// interceptorRegistration.excludePathPatterns("/swagger-resources/**");
// interceptorRegistration.excludePathPatterns("/configuration/**");
// //排除登录
// interceptorRegistration.excludePathPatterns("/rest/user/login");
// interceptorRegistration.excludePathPatterns("/rest/user/loginByToken");
// registry.addInterceptor(logInterceptor).order(2);
}
}
src/main/java/com/zksy/szpt/controller/InfSettingController.java
0 → 100644
View file @
cbaf93de
package
com
.
zksy
.
szpt
.
controller
;
import
com.zksy.szpt.domain.dto.AppStoreDTO
;
import
com.zksy.szpt.service.AppStoreService
;
import
org.springframework.web.bind.annotation.PostMapping
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RestController
;
@RestController
public
class
InfSettingController
{
private
final
AppStoreService
appStoreService
;
public
InfSettingController
(
AppStoreService
infApiSettingService
)
{
this
.
appStoreService
=
infApiSettingService
;
}
@PostMapping
(
"/infSetting"
)
public
Object
infSetting
(
@RequestBody
AppStoreDTO
appStoreDTO
)
{
return
appStoreService
.
getAppSecretByAppKey
(
"1"
);
}
}
src/main/java/com/zksy/szpt/domain/HttpResult.java
0 → 100644
View file @
cbaf93de
package
com
.
zksy
.
szpt
.
domain
;
public
class
HttpResult
<
T
>
{
private
T
data
;
private
int
code
;
private
String
message
;
private
long
timestamp
;
public
HttpResult
()
{
this
.
code
=
HttpResultState
.
SUCCESS
.
getCode
();
this
.
message
=
HttpResultState
.
SUCCESS
.
getMessage
();
this
.
timestamp
=
System
.
currentTimeMillis
();
}
public
HttpResult
(
T
data
)
{
this
.
data
=
data
;
this
.
code
=
HttpResultState
.
SUCCESS
.
getCode
();
this
.
message
=
HttpResultState
.
SUCCESS
.
getMessage
();
this
.
timestamp
=
System
.
currentTimeMillis
();
}
public
HttpResult
(
HttpResultState
state
)
{
this
.
code
=
state
.
getCode
();
this
.
message
=
state
.
getMessage
();
this
.
timestamp
=
System
.
currentTimeMillis
();
}
public
static
<
T
>
HttpResult
<
T
>
success
()
{
return
new
HttpResult
<>();
}
public
static
<
T
>
HttpResult
<
T
>
success
(
T
data
)
{
return
new
HttpResult
<>(
data
);
}
public
T
getData
()
{
return
data
;
}
public
void
setData
(
T
data
)
{
this
.
data
=
data
;
}
public
int
getCode
()
{
return
code
;
}
public
void
setCode
(
int
code
)
{
this
.
code
=
code
;
}
public
String
getMessage
()
{
return
message
;
}
public
void
setMessage
(
String
message
)
{
this
.
message
=
message
;
}
public
long
getTimestamp
()
{
return
timestamp
;
}
public
void
setTimestamp
(
long
timestamp
)
{
this
.
timestamp
=
timestamp
;
}
}
\ No newline at end of file
src/main/java/com/zksy/szpt/domain/HttpResultState.java
0 → 100644
View file @
cbaf93de
package
com
.
zksy
.
szpt
.
domain
;
public
enum
HttpResultState
{
SUCCESS
(
9000
,
"成功"
),
INVALID_PARAMETER
(
9020
,
"无效的输入参数"
),
NOTIFICATION
(
9030
,
"警告"
),
MULTI_DEVICE_LOGIN
(
9040
,
"登录已失效,账户已在别处登录,请重新登录"
),
EXPIRE
(
9041
,
"登录已经过期,请重新登录"
),
INVALID_TOKEN
(
9042
,
"身份验证失败"
),
GATEWAY
(
9050
,
"请求的服务不存在,请联系管理员"
),
DATABASE
(
9060
,
"服务器错误1,请联系管理员"
),
DUPLICATED_KEY
(
9061
,
"数据已存在"
),
NOT_FOUND
(
9070
,
"请求的资源不存在"
),
DEGRADATION
(
9080
,
"服务降级"
),
ERROR
(
9999
,
"服务器错误2,请联系管理员"
);
HttpResultState
(
Integer
code
,
String
message
)
{
this
.
code
=
code
;
this
.
message
=
message
;
}
private
Integer
code
;
private
String
message
;
public
Integer
getCode
()
{
return
code
;
}
public
void
setCode
(
Integer
code
)
{
this
.
code
=
code
;
}
public
String
getMessage
()
{
return
message
;
}
public
void
setMessage
(
String
message
)
{
this
.
message
=
message
;
}
}
src/main/java/com/zksy/szpt/domain/dto/AppStoreDTO.java
0 → 100644
View file @
cbaf93de
package
com
.
zksy
.
szpt
.
domain
.
dto
;
public
class
AppStoreDTO
{
private
Long
id
;
private
String
appKey
;
private
String
appSecret
;
private
String
create_time
;
public
Long
getId
()
{
return
id
;
}
public
void
setId
(
Long
id
)
{
this
.
id
=
id
;
}
public
String
getAppKey
()
{
return
appKey
;
}
public
void
setAppKey
(
String
appKey
)
{
this
.
appKey
=
appKey
;
}
public
String
getAppSecret
()
{
return
appSecret
;
}
public
void
setAppSecret
(
String
appSecret
)
{
this
.
appSecret
=
appSecret
;
}
public
String
getCreate_time
()
{
return
create_time
;
}
public
void
setCreate_time
(
String
create_time
)
{
this
.
create_time
=
create_time
;
}
}
src/main/java/com/zksy/szpt/domain/po/AppStore.java
0 → 100644
View file @
cbaf93de
package
com
.
zksy
.
szpt
.
domain
.
po
;
import
com.baomidou.mybatisplus.annotation.TableId
;
import
com.baomidou.mybatisplus.annotation.TableName
;
@TableName
(
"tb_app_store"
)
public
class
AppStore
{
@TableId
private
Long
id
;
private
String
appKey
;
private
String
appSecret
;
private
String
create_time
;
public
Long
getId
()
{
return
id
;
}
public
void
setId
(
Long
id
)
{
this
.
id
=
id
;
}
public
String
getAppKey
()
{
return
appKey
;
}
public
void
setAppKey
(
String
appKey
)
{
this
.
appKey
=
appKey
;
}
public
String
getAppSecret
()
{
return
appSecret
;
}
public
void
setAppSecret
(
String
appSecret
)
{
this
.
appSecret
=
appSecret
;
}
public
String
getCreate_time
()
{
return
create_time
;
}
public
void
setCreate_time
(
String
create_time
)
{
this
.
create_time
=
create_time
;
}
}
src/main/java/com/zksy/szpt/filter/ReusableBodyRequestWrapper.java
0 → 100644
View file @
cbaf93de
package
com
.
zksy
.
szpt
.
filter
;
import
org.apache.tomcat.util.http.fileupload.IOUtils
;
import
javax.servlet.ReadListener
;
import
javax.servlet.ServletInputStream
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletRequestWrapper
;
import
java.io.*
;
/**
* 该类用于包装HttpServletRequest,以便在读取请求体后仍可重复读取
*/
public
class
ReusableBodyRequestWrapper
extends
HttpServletRequestWrapper
{
//参数字节数组,用于存储请求体的字节数据
private
byte
[]
requestBody
;
//Http请求对象
private
HttpServletRequest
request
;
/**
* 构造函数,初始化包装类
* @param request 原始HttpServletRequest对象
* @throws IOException 如果读取请求体时发生IO错误
*/
public
ReusableBodyRequestWrapper
(
HttpServletRequest
request
)
throws
IOException
{
super
(
request
);
this
.
request
=
request
;
}
/**
* 重写getInputStream方法,实现请求体的重复读取
* @return 包含请求体数据的ServletInputStream对象
* @throws IOException 如果读取请求体时发生IO错误
*/
@Override
public
ServletInputStream
getInputStream
()
throws
IOException
{
/**
* 每次调用此方法时将数据流中的数据读取出来,然后再回填到InputStream之中
* 解决通过@RequestBody和@RequestParam(POST方式)读取一次后控制器拿不到参数问题
*/
//仅当requestBody未初始化时,从请求中读取并存储到requestBody
if
(
null
==
this
.
requestBody
)
{
ByteArrayOutputStream
baos
=
new
ByteArrayOutputStream
();
IOUtils
.
copy
(
request
.
getInputStream
(),
baos
);
this
.
requestBody
=
baos
.
toByteArray
();
}
//创建一个 ByteArrayInputStream 对象,用于重复读取requestBody
final
ByteArrayInputStream
bais
=
new
ByteArrayInputStream
(
requestBody
);
return
new
ServletInputStream
()
{
@Override
public
boolean
isFinished
()
{
//始终返回false,表示数据流未完成
return
false
;
}
@Override
public
boolean
isReady
()
{
//始终返回false,表示数据流未准备好
return
false
;
}
@Override
public
void
setReadListener
(
ReadListener
listener
)
{
//不执行任何操作,因为该数据流不支持异步操作
}
@Override
public
int
read
()
{
//从ByteArrayInputStream中读取数据
return
bais
.
read
();
}
};
}
/**
* 获取请求体的字节数组
* @return 请求体的字节数组
*/
public
byte
[]
getRequestBody
()
{
return
requestBody
;
}
/**
* 重写getReader方法,返回一个基于getInputStream的BufferedReader
* @return 包含请求体数据的BufferedReader对象
* @throws IOException 如果读取请求体时发生IO错误
*/
@Override
public
BufferedReader
getReader
()
throws
IOException
{
//基于getInputStream创建BufferedReader
return
new
BufferedReader
(
new
InputStreamReader
(
this
.
getInputStream
()));
}
}
\ No newline at end of file
src/main/java/com/zksy/szpt/filter/SignatureVerificationFilter.java
0 → 100644
View file @
cbaf93de
package
com
.
zksy
.
szpt
.
filter
;
import
cn.hutool.crypto.digest.DigestUtil
;
import
cn.hutool.json.JSONUtil
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.zksy.szpt.domain.HttpResult
;
import
com.zksy.szpt.domain.HttpResultState
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.core.annotation.Order
;
import
org.springframework.http.MediaType
;
import
org.springframework.stereotype.Component
;
import
org.springframework.util.StreamUtils
;
import
org.springframework.util.StringUtils
;
import
org.springframework.web.filter.OncePerRequestFilter
;
import
javax.annotation.Resource
;
import
javax.servlet.FilterChain
;
import
javax.servlet.ServletException
;
import
javax.servlet.annotation.WebFilter
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
import
java.nio.charset.StandardCharsets
;
import
java.util.Map
;
@Order
(
1
)
@WebFilter
(
urlPatterns
=
"/**"
,
filterName
=
"SignatureVerificationFilter"
)
@Component
public
class
SignatureVerificationFilter
extends
OncePerRequestFilter
{
public
static
Logger
logger
=
LoggerFactory
.
getLogger
(
SignatureVerificationFilter
.
class
);
private
final
ObjectMapper
objectMapper
;
public
SignatureVerificationFilter
(
ObjectMapper
objectMapper
)
{
this
.
objectMapper
=
objectMapper
;
}
@Override
protected
void
doFilterInternal
(
HttpServletRequest
request
,
HttpServletResponse
response
,
FilterChain
filterChain
)
throws
ServletException
,
IOException
{
// 对request进行包装,支持重复读取body
ReusableBodyRequestWrapper
requestWrapper
=
new
ReusableBodyRequestWrapper
(
request
);
// 校验签名
if
(
this
.
verifySignature
(
requestWrapper
,
response
))
{
filterChain
.
doFilter
(
requestWrapper
,
response
);
}
}
// 签名秘钥
private
String
secretKey
=
"2"
;
/**
* 校验签名
*
* @param request HTTP请求
* @param response HTTP响应
* @return 签名验证结果
* @throws IOException 如果读取请求体失败
*/
public
boolean
verifySignature
(
HttpServletRequest
request
,
HttpServletResponse
response
)
throws
IOException
{
// 签名
String
appId
=
request
.
getHeader
(
"appId"
);
// 签名
String
sign
=
request
.
getHeader
(
"signature"
);
// 随机数
String
nonce
=
request
.
getHeader
(
"nonce"
);
// 时间戳
String
timestampStr
=
request
.
getHeader
(
"timestamp"
);
if
(!
StringUtils
.
hasText
(
sign
)
||
!
StringUtils
.
hasText
(
nonce
)
||
!
StringUtils
.
hasText
(
timestampStr
))
{
this
.
write
(
response
,
"参数错误"
);
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
=
objectMapper
.
writeValueAsString
(
objectMapper
.
readValue
(
StreamUtils
.
copyToString
(
request
.
getInputStream
(),
StandardCharsets
.
UTF_8
),
Map
.
class
));
// 需要签名的数据:secretKey+noce+timestampStr+body
// 校验签名
String
data
=
String
.
format
(
"%s%s%s%s%s"
,
appId
,
nonce
,
timestampStr
,
body
,
this
.
secretKey
);
if
(!
DigestUtil
.
md5Hex
(
data
).
equals
(
sign
))
{
write
(
response
,
"签名有误"
);
return
false
;
}
return
true
;
}
/**
* 向客户端写入响应信息
*
* @param response HTTP响应
* @param msg 响应信息
* @throws IOException 如果写入失败
*/
private
void
write
(
HttpServletResponse
response
,
String
msg
)
throws
IOException
{
HttpResultState
httpResultState
=
HttpResultState
.
INVALID_TOKEN
;
httpResultState
.
setMessage
(
msg
);
HttpResult
<
String
>
httpResult
=
new
HttpResult
<>(
httpResultState
);
response
.
setContentType
(
MediaType
.
APPLICATION_JSON_VALUE
);
response
.
setCharacterEncoding
(
StandardCharsets
.
UTF_8
.
name
());
response
.
getWriter
().
write
(
JSONUtil
.
toJsonStr
(
httpResult
));
}
}
src/main/java/com/zksy/szpt/mapper/AppStoreMapper.java
0 → 100644
View file @
cbaf93de
package
com
.
zksy
.
szpt
.
mapper
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
com.zksy.szpt.domain.po.AppStore
;
public
interface
AppStoreMapper
extends
BaseMapper
<
AppStore
>
{
}
src/main/java/com/zksy/szpt/service/AppStoreService.java
0 → 100644
View file @
cbaf93de
package
com
.
zksy
.
szpt
.
service
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.zksy.szpt.domain.po.AppStore
;
import
com.zksy.szpt.mapper.AppStoreMapper
;
import
org.springframework.stereotype.Service
;
import
java.util.List
;
@Service
public
class
AppStoreService
{
private
final
AppStoreMapper
appStoreMapper
;
public
AppStoreService
(
AppStoreMapper
appStoreMapper
)
{
this
.
appStoreMapper
=
appStoreMapper
;
}
public
String
getAppSecretByAppKey
(
String
appKey
)
{
LambdaQueryWrapper
<
AppStore
>
queryWrapper
=
new
LambdaQueryWrapper
<>();
queryWrapper
.
eq
(
AppStore:
:
getAppKey
,
appKey
);
List
<
AppStore
>
tbAppStorePOList
=
appStoreMapper
.
selectList
(
queryWrapper
);
if
(
tbAppStorePOList
!=
null
&&
!
tbAppStorePOList
.
isEmpty
())
{
return
tbAppStorePOList
.
get
(
0
).
getAppSecret
();
}
return
null
;
}
}
src/main/java/com/zksy/szpt/util/EncryptUtil.java
0 → 100644
View file @
cbaf93de
package
com
.
zksy
.
szpt
.
util
;
import
com.sun.org.apache.xerces.internal.impl.dv.util.Base64
;
import
javax.crypto.Cipher
;
import
javax.crypto.KeyGenerator
;
import
javax.crypto.SecretKey
;
import
javax.crypto.spec.SecretKeySpec
;
import
java.nio.charset.StandardCharsets
;
import
java.security.MessageDigest
;
import
java.security.SecureRandom
;
public
class
EncryptUtil
{
private
static
final
String
DES
=
"DES"
;
private
static
final
String
AES
=
"AES"
;
/**
* 编码格式;默认使用uft-8
*/
private
final
String
charset
=
"utf-8"
;
/**
* DES
*/
private
final
int
keySizeDES
=
0
;
/**
* AES
*/
private
final
int
keySizeAES
=
128
;
private
static
EncryptUtil
instant
;
private
EncryptUtil
()
{
//单例
}
//双重锁
public
static
EncryptUtil
getInstance
()
{
if
(
instant
==
null
)
{
synchronized
(
EncryptUtil
.
class
)
{
if
(
instant
==
null
)
{
instant
=
new
EncryptUtil
();
}
}
}
return
instant
;
}
/**
* 使用KeyGenerator双向加密,DES/AES,注意这里转化为字符串的时候是将2进制转为16进制格式的字符串,不是直接转,因为会出错
*
* @param res 加密的原文
* @param algorithm 加密使用的算法名称
* @param key 加密的秘钥
* @param keySize
* @param isEncode
*/
private
String
keyGeneratorES
(
String
res
,
String
algorithm
,
String
key
,
int
keySize
,
boolean
isEncode
)
{
try
{
KeyGenerator
kg
=
KeyGenerator
.
getInstance
(
algorithm
);
if
(
keySize
==
0
)
{
byte
[]
keyBytes
=
charset
==
null
?
key
.
getBytes
()
:
key
.
getBytes
(
charset
);
kg
.
init
(
new
SecureRandom
(
keyBytes
));
}
else
if
(
key
==
null
)
{
kg
.
init
(
keySize
);
}
else
{
byte
[]
keyBytes
=
charset
==
null
?
key
.
getBytes
()
:
key
.
getBytes
(
charset
);
kg
.
init
(
keySize
,
new
SecureRandom
(
keyBytes
));
}
SecretKey
sk
=
kg
.
generateKey
();
SecretKeySpec
sks
=
new
SecretKeySpec
(
sk
.
getEncoded
(),
algorithm
);
Cipher
cipher
=
Cipher
.
getInstance
(
algorithm
);
if
(
isEncode
)
{
cipher
.
init
(
Cipher
.
ENCRYPT_MODE
,
sks
);
byte
[]
resBytes
=
charset
==
null
?
res
.
getBytes
()
:
res
.
getBytes
(
charset
);
return
parseByte2HexStr
(
cipher
.
doFinal
(
resBytes
));
}
else
{
cipher
.
init
(
Cipher
.
DECRYPT_MODE
,
sks
);
return
new
String
(
cipher
.
doFinal
(
parseHexStr2Byte
(
res
)));
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
null
;
}
/**
* 将二进制转换成16进制
*/
public
String
parseByte2HexStr
(
byte
[]
buf
)
{
StringBuffer
sb
=
new
StringBuffer
();
for
(
int
i
=
0
;
i
<
buf
.
length
;
i
++)
{
String
hex
=
Integer
.
toHexString
(
buf
[
i
]
&
0xFF
);
if
(
hex
.
length
()
==
1
)
{
hex
=
'0'
+
hex
;
}
sb
.
append
(
hex
.
toUpperCase
());
}
return
sb
.
toString
();
}
/**
* 将16进制转换为二进制
*/
public
byte
[]
parseHexStr2Byte
(
String
hexStr
)
{
if
(
hexStr
.
length
()
<
1
)
return
null
;
byte
[]
result
=
new
byte
[
hexStr
.
length
()
/
2
];
for
(
int
i
=
0
;
i
<
hexStr
.
length
()
/
2
;
i
++)
{
int
high
=
Integer
.
parseInt
(
hexStr
.
substring
(
i
*
2
,
i
*
2
+
1
),
16
);
int
low
=
Integer
.
parseInt
(
hexStr
.
substring
(
i
*
2
+
1
,
i
*
2
+
2
),
16
);
result
[
i
]
=
(
byte
)
(
high
*
16
+
low
);
}
return
result
;
}
/**
* 使用DES加密算法进行加密(可逆)
*
* @param res 需要加密的原文
* @param key 秘钥
*/
private
String
DESEncode
(
String
res
,
String
key
)
{
return
keyGeneratorES
(
res
,
DES
,
key
,
keySizeDES
,
true
);
}
/**
* 对使用DES加密算法的密文进行解密(可逆)
*
* @param res 需要解密的密文
* @param key 秘钥
*/
private
String
DESDecode
(
String
res
,
String
key
)
{
return
keyGeneratorES
(
res
,
DES
,
key
,
keySizeDES
,
false
);
}
/**
* 使用AES加密算法经行加密(可逆)
*
* @param res 需要加密的密文
* @param key 秘钥
*/
public
String
AESEncode
(
String
res
,
String
key
)
{
return
keyGeneratorES
(
res
,
AES
,
key
,
keySizeAES
,
true
);
}
/**
* 对使用AES加密算法的密文进行解密
*
* @param res 需要解密的密文
* @param key 秘钥
*/
private
String
AESDecode
(
String
res
,
String
key
)
{
return
keyGeneratorES
(
res
,
AES
,
key
,
keySizeAES
,
false
);
}
/**
* 使用Base64进行加密
*
* @param res 密文
*/
public
String
Base64Encode
(
String
res
)
{
return
Base64
.
encode
(
res
.
getBytes
());
}
/**
* 使用Base64进行解密
*
* @param res
*/
public
String
Base64Decode
(
String
res
)
{
byte
[]
bytes
=
Base64
.
decode
(
res
);
return
null
==
bytes
?
null
:
new
String
(
bytes
);
}
//md5
public
String
md5Hex
(
String
src
)
{
try
{
MessageDigest
md5
=
MessageDigest
.
getInstance
(
"MD5"
);
byte
[]
bs
=
md5
.
digest
(
src
.
getBytes
());
return
parseByte2HexStr
(
bs
);
}
catch
(
Exception
e
)
{
return
null
;
}
}
public
String
shaEncode
(
String
inStr
)
{
MessageDigest
sha
=
null
;
try
{
sha
=
MessageDigest
.
getInstance
(
"SHA"
);
}
catch
(
Exception
e
)
{
System
.
out
.
println
(
e
.
toString
());
e
.
printStackTrace
();
return
""
;
}
byte
[]
byteArray
=
inStr
.
getBytes
(
StandardCharsets
.
UTF_8
);
byte
[]
md5Bytes
=
sha
.
digest
(
byteArray
);
StringBuffer
hexValue
=
new
StringBuffer
();
for
(
int
i
=
0
;
i
<
md5Bytes
.
length
;
i
++)
{
int
val
=
((
int
)
md5Bytes
[
i
])
&
0xff
;
if
(
val
<
16
)
{
hexValue
.
append
(
"0"
);
}
hexValue
.
append
(
Integer
.
toHexString
(
val
));
}
return
hexValue
.
toString
();
}
public
String
encrypt_ECB_PKCS5Padding
(
String
keyValue
,
String
data
)
{
byte
[]
result
=
null
;
SecretKey
key
=
new
SecretKeySpec
(
parseHexStr2Byte
(
keyValue
),
"AES"
);
try
{
Cipher
cipher
=
Cipher
.
getInstance
(
"AES/ECB/PKCS5Padding"
);
cipher
.
init
(
Cipher
.
ENCRYPT_MODE
,
key
);
result
=
cipher
.
doFinal
(
parseHexStr2Byte
(
data
));
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
parseByte2HexStr
(
result
);
}
}
\ No newline at end of file
src/main/java/com/zksy/szpt/util/SignatureUtil.java
0 → 100644
View file @
cbaf93de
package
com
.
zksy
.
szpt
.
util
;
import
cn.hutool.crypto.digest.DigestUtil
;
import
org.springframework.util.StringUtils
;
import
java.util.UUID
;
public
class
SignatureUtil
{
/**
* 生成签名
*
* @param body 请求体
* @param secretKey 密钥
* @param nonce 随机数
* @param timestamp 时间戳
* @return 签名
*/
public
static
String
generateSignature
(
String
body
,
String
secretKey
,
String
nonce
,
String
timestamp
)
{
if
(!
StringUtils
.
hasText
(
body
)
||
!
StringUtils
.
hasText
(
secretKey
)
||
!
StringUtils
.
hasText
(
nonce
)
||
!
StringUtils
.
hasText
(
timestamp
))
{
throw
new
IllegalArgumentException
(
"参数不能为空"
);
}
// 按照 secretKey + nonce + timestamp + body 的顺序拼接字符串
String
data
=
String
.
format
(
"%s%s%s%s"
,
secretKey
,
nonce
,
timestamp
,
body
);
System
.
out
.
println
(
"data = "
+
data
);
// 使用MD5算法计算签名
String
sign
=
DigestUtil
.
md5Hex
(
data
);
return
sign
;
}
public
static
void
main
(
String
[]
args
)
{
// 示例参数
String
body
=
"{\n"
+
" \"fromAccountId\": \"张三\",\n"
+
" \"toAccountId\": \"李四\",\n"
+
" \"transferPrice\": 100\n"
+
"}"
;
//秘钥
String
secretKey
=
"b0e8668b-bcf2-4d73-abd4-893bbc1c6079"
;
// 随机数
String
nonce
=
UUID
.
randomUUID
().
toString
().
replace
(
"-"
,
""
);
// 时间戳
long
timestamp
=
System
.
currentTimeMillis
()
/
1000
;
// 生成签名
String
sign
=
generateSignature
(
body
,
secretKey
,
nonce
,
String
.
valueOf
(
timestamp
));
// 输出生成的签名
System
.
out
.
println
(
"X-Sign: "
+
sign
);
System
.
out
.
println
(
"X-Nonce: "
+
nonce
);
System
.
out
.
println
(
"X-Timestamp: "
+
timestamp
);
}
}
src/main/resources/application-dev.yml
0 → 100644
View file @
cbaf93de
spring
:
datasource
:
url
:
jdbc:mysql://192.168.168.110:3306/swagger?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8
username
:
root
password
:
123456
driver-class-name
:
com.mysql.cj.jdbc.Driver
type
:
com.alibaba.druid.pool.DruidDataSource
src/main/resources/application.yml
0 → 100644
View file @
cbaf93de
server
:
port
:
8086
spring
:
profiles
:
active
:
dev
main
:
allow-bean-definition-overriding
:
true
mvc
:
throw-exception-if-no-handler-found
:
true
resources
:
add-mappings
:
false
# 文件上传大小限制
servlet
:
multipart
:
enabled
:
true
#是否启用http上传处理
max-request-size
:
2000MB
#最大请求文件的大小
max-file-size
:
1000MB
#设置单个文件最大长度
file-size-threshold
:
500MB
#当文件达到多少时进行磁盘写入
\ No newline at end of file
src/main/resources/logback-spring.xml
0 → 100644
View file @
cbaf93de
<?xml version="1.0" encoding="UTF-8"?>
<configuration
debug=
"false"
>
<!--定义属性,设置控制台打印模板-->
<property
name=
"STDOUT_LOG_PATTERN"
value=
"%date{yyyy-MM-dd HH:mm:ss} %highlight(%-5level) %boldYellow(%thread) %boldGreen(%logger) %boldMagenta(%L) %msg%n"
/>
<property
name=
"LOG_PATTERN"
value=
"%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}[%L] - %msg%n"
/>
<!--文件日志-->
<appender
name=
"fileAppender"
class=
"ch.qos.logback.core.rolling.RollingFileAppender"
>
<rollingPolicy
class=
"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"
>
<!--日志文件输出的文件名-->
<FileNamePattern>
logs/%d{yyyy-MM-dd}.%i.log
</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>
30
</MaxHistory>
<!--日志文件最大的大小-->
<maxFileSize>
100MB
</maxFileSize>
</rollingPolicy>
<encoder
class=
"ch.qos.logback.classic.encoder.PatternLayoutEncoder"
>
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>
${LOG_PATTERN}
</pattern>
</encoder>
<!--输出日志级别等于此级别的日志信息-->
<filter
class=
"ch.qos.logback.classic.filter.LevelFilter"
>
<level>
INFO
</level>
<onMatch>
ACCEPT
</onMatch>
<onMismatch>
DENY
</onMismatch>
<!-- onMatch="ACCEPT" 表示匹配该级别及以上-->
<!-- onMatch="DENY" 表示不匹配该级别及以上-->
<!-- onMatch="NEUTRAL" 表示该级别及以上的,由下一个filter处理,如果当前是最后一个,则表示匹配该级别及以上-->
<!-- onMismatch="ACCEPT" 表示匹配该级别以下-->
<!-- onMismatch="NEUTRAL" 表示该级别及以下的,由下一个filter处理,如果当前是最后一个,则不匹配该级别以下的-->
<!-- onMismatch="DENY" 表示不匹配该级别以下的-->
</filter>
</appender>
<!--异常文件日志-->
<appender
name=
"errorFileAppender"
class=
"ch.qos.logback.core.rolling.RollingFileAppender"
>
<rollingPolicy
class=
"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"
>
<FileNamePattern>
logs/%d{yyyy-MM-dd}-[ERROR].%i.log
</FileNamePattern>
<MaxHistory>
30
</MaxHistory>
<maxFileSize>
100MB
</maxFileSize>
</rollingPolicy>
<encoder
class=
"ch.qos.logback.classic.encoder.PatternLayoutEncoder"
>
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>
${LOG_PATTERN}
</pattern>
</encoder>
<!--输出日志级别是大于或等于此级别的日志信息-->
<filter
class=
"ch.qos.logback.classic.filter.ThresholdFilter"
>
<level>
WARN
</level>
</filter>
</appender>
<!--sql文件日志-->
<appender
name=
"sqlFileAppender"
class=
"ch.qos.logback.core.rolling.RollingFileAppender"
>
<rollingPolicy
class=
"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"
>
<!--日志文件输出的文件名-->
<FileNamePattern>
logs/%d{yyyy-MM-dd}-[SQL].%i.log
</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>
30
</MaxHistory>
<!--日志文件最大的大小-->
<maxFileSize>
100MB
</maxFileSize>
</rollingPolicy>
<encoder
class=
"ch.qos.logback.classic.encoder.PatternLayoutEncoder"
>
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>
${LOG_PATTERN}
</pattern>
</encoder>
</appender>
<!--控制台-->
<appender
name=
"STDOUT"
class=
"ch.qos.logback.core.ConsoleAppender"
>
<encoder
class=
"ch.qos.logback.classic.encoder.PatternLayoutEncoder"
>
<pattern>
${STDOUT_LOG_PATTERN}
</pattern>
</encoder>
</appender>
<!--定义了三种记录器,优先级由高到低-->
<!-- mybatis sql-->
<!--根据包路径-->
<!-- <logger name="com.zksy.szpcs" level="INFO" additivity="false">-->
<!-- <appender-ref ref="fileAppender"/>-->
<!-- <appender-ref ref="STDOUT"/>-->
<!-- <appender-ref ref="errorFileAppender"/>-->
<!-- </logger>-->
<!--getLogger找不到的时候调用 尽量不用,不然引用的jar包中打印的日志也会显示-->
<!-- <root level="INFO">-->
<!-- <appender-ref ref="STDOUT"/>-->
<!-- <appender-ref ref="fileAppender"/>-->
<!-- <appender-ref ref="errorFileAppender"/>-->
<!-- </root>-->
<!-- 屏蔽swagger包的日志-->
<logger
name=
"springfox.documentation"
level=
"OFF"
>
</logger>
<!-- 根据配置文件spring.profiles.active选择不同的日志配置-->
<springProfile
name=
"dev, default"
>
<logger
name=
"com.zksy.szpt.mapper"
level=
"DEBUG"
additivity=
"false"
>
<appender-ref
ref=
"STDOUT"
/>
</logger>
<root
level=
"INFO"
>
<appender-ref
ref=
"STDOUT"
/>
</root>
</springProfile>
<springProfile
name=
"prod"
>
<logger
name=
"com.zksy.szpt.mapper"
level=
"DEBUG"
additivity=
"false"
>
<appender-ref
ref=
"sqlFileAppender"
/>
</logger>
<root
level=
"INFO"
>
<appender-ref
ref=
"fileAppender"
/>
<appender-ref
ref=
"errorFileAppender"
/>
</root>
</springProfile>
</configuration>
src/test/java/com/zksy/szpt/MainTest.java
0 → 100644
View file @
cbaf93de
package
com
.
zksy
.
szpt
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertTrue
;
import
org.junit.jupiter.api.Test
;
/**
* A simple unit test
*/
public
class
MainTest
{
/**
* Rigorous Test :-)
*/
@Test
public
void
shouldAnswerWithTrue
()
{
assertTrue
(
true
);
}
}
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