Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
jinli gu
Eladmin
Commits
ebb12cd0
"admin-console/vscode:/vscode.git/clone" did not exist on "5866aaee67e61fe060d41554e56ff48efec4bbe0"
Unverified
Commit
ebb12cd0
authored
Dec 29, 2018
by
elunez
Committed by
GitHub
Dec 29, 2018
Browse files
Merge pull request #2 from everhopingandwaiting/master
redis限流
parents
81078698
29c2b5f8
Changes
8
Hide whitespace changes
Inline
Side-by-side
README.md
View file @
ebb12cd0
...
@@ -68,4 +68,4 @@
...
@@ -68,4 +68,4 @@
-
QQ交流群:891137268
-
QQ交流群:891137268
-
作者邮箱:
zhengjie@tom
.com
-
作者邮箱:
elunez@qq
.com
pom.xml
View file @
ebb12cd0
...
@@ -75,7 +75,10 @@
...
@@ -75,7 +75,10 @@
<artifactId>
commons-pool2
</artifactId>
<artifactId>
commons-pool2
</artifactId>
<version>
2.5.0
</version>
<version>
2.5.0
</version>
</dependency>
</dependency>
<dependency>
<groupId>
org.apache.commons
</groupId>
<artifactId>
commons-lang3
</artifactId>
</dependency>
<!--jwt-->
<!--jwt-->
<dependency>
<dependency>
<groupId>
io.jsonwebtoken
</groupId>
<groupId>
io.jsonwebtoken
</groupId>
...
...
src/main/java/me/zhengjie/common/aop/limit/Limit.java
0 → 100644
View file @
ebb12cd0
package
me.zhengjie.common.aop.limit
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
/**
* @author jacky
*/
@Target
(
ElementType
.
METHOD
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
Limit
{
// 资源名称,用于描述接口功能
String
name
()
default
""
;
// 资源 key
String
key
()
default
""
;
// key prefix
String
prefix
()
default
""
;
// 时间的,单位秒
int
period
();
// 限制访问次数
int
count
();
// 限制类型
LimitType
limitType
()
default
LimitType
.
CUSTOMER
;
}
src/main/java/me/zhengjie/common/aop/limit/LimitAspect.java
0 → 100644
View file @
ebb12cd0
package
me.zhengjie.common.aop.limit
;
import
com.google.common.collect.ImmutableList
;
import
me.zhengjie.common.exception.BadRequestException
;
import
me.zhengjie.common.utils.IpUtil
;
import
me.zhengjie.common.utils.RequestHolder
;
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.aspectj.lang.reflect.MethodSignature
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.data.redis.core.script.DefaultRedisScript
;
import
org.springframework.data.redis.core.script.RedisScript
;
import
org.springframework.stereotype.Component
;
import
javax.servlet.http.HttpServletRequest
;
import
java.lang.reflect.Method
;
@Aspect
@Component
public
class
LimitAspect
{
@Autowired
private
RedisTemplate
redisTemplate
;
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
LimitAspect
.
class
);
@Pointcut
(
"@annotation(Limit)"
)
public
void
pointcut
()
{
//
}
@Around
(
"pointcut()"
)
public
Object
around
(
ProceedingJoinPoint
joinPoint
)
throws
Throwable
{
HttpServletRequest
request
=
RequestHolder
.
getHttpServletRequest
();
MethodSignature
signature
=
(
MethodSignature
)
joinPoint
.
getSignature
();
Method
signatureMethod
=
signature
.
getMethod
();
Limit
limit
=
signatureMethod
.
getAnnotation
(
Limit
.
class
);
LimitType
limitType
=
limit
.
limitType
();
String
name
=
limit
.
name
();
String
key
=
limit
.
key
();
if
(
StringUtils
.
isEmpty
(
key
))
{
switch
(
limitType
)
{
case
IP:
key
=
IpUtil
.
getIP
(
request
);
break
;
default
:
key
=
signatureMethod
.
getName
();
}
}
ImmutableList
keys
=
ImmutableList
.
of
(
StringUtils
.
join
(
limit
.
prefix
(),
"_"
,
key
,
"_"
,
request
.
getRequestURI
().
replaceAll
(
"/"
,
"_"
)));
String
luaScript
=
buildLuaScript
();
RedisScript
<
Number
>
redisScript
=
new
DefaultRedisScript
<>(
luaScript
,
Number
.
class
);
Number
count
=
(
Number
)
redisTemplate
.
execute
(
redisScript
,
keys
,
limit
.
count
(),
limit
.
period
());
if
(
null
!=
count
&&
count
.
intValue
()
<=
limit
.
count
())
{
logger
.
info
(
"第{}次访问key为 {},描述为 [{}] 的接口"
,
count
,
keys
,
limit
.
name
());
return
joinPoint
.
proceed
();
}
else
{
throw
new
BadRequestException
(
"访问次数受限制"
);
}
}
/**
* 限流脚本
*/
private
String
buildLuaScript
()
{
return
"local c"
+
"\nc = redis.call('get',KEYS[1])"
+
"\nif c and tonumber(c) > tonumber(ARGV[1]) then"
+
"\nreturn c;"
+
"\nend"
+
"\nc = redis.call('incr',KEYS[1])"
+
"\nif tonumber(c) == 1 then"
+
"\nredis.call('expire',KEYS[1],ARGV[2])"
+
"\nend"
+
"\nreturn c;"
;
}
}
src/main/java/me/zhengjie/common/aop/limit/LimitType.java
0 → 100644
View file @
ebb12cd0
package
me.zhengjie.common.aop.limit
;
public
enum
LimitType
{
CUSTOMER
,
// by ip addr
IP
;
}
src/main/java/me/zhengjie/core/config/WebSecurityConfig.java
View file @
ebb12cd0
...
@@ -46,8 +46,8 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
...
@@ -46,8 +46,8 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Autowired
public
void
configureGlobal
(
AuthenticationManagerBuilder
auth
)
throws
Exception
{
public
void
configureGlobal
(
AuthenticationManagerBuilder
auth
)
throws
Exception
{
auth
auth
.
userDetailsService
(
jwtUserDetailsService
)
.
userDetailsService
(
jwtUserDetailsService
)
.
passwordEncoder
(
passwordEncoderBean
());
.
passwordEncoder
(
passwordEncoderBean
());
}
}
@Bean
@Bean
...
@@ -65,56 +65,55 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
...
@@ -65,56 +65,55 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
protected
void
configure
(
HttpSecurity
httpSecurity
)
throws
Exception
{
protected
void
configure
(
HttpSecurity
httpSecurity
)
throws
Exception
{
httpSecurity
httpSecurity
// 禁用 CSRF
// 禁用 CSRF
.
csrf
().
disable
()
.
csrf
().
disable
()
// 授权异常
// 授权异常
.
exceptionHandling
().
authenticationEntryPoint
(
unauthorizedHandler
).
and
()
.
exceptionHandling
().
authenticationEntryPoint
(
unauthorizedHandler
).
and
()
// 不创建会话
// 不创建会话
.
sessionManagement
().
sessionCreationPolicy
(
SessionCreationPolicy
.
STATELESS
).
and
()
.
sessionManagement
().
sessionCreationPolicy
(
SessionCreationPolicy
.
STATELESS
).
and
()
.
authorizeRequests
()
.
authorizeRequests
()
.
antMatchers
(
"/auth/**"
).
permitAll
()
.
antMatchers
(
"/auth/**"
).
permitAll
()
.
antMatchers
(
"/websocket/**"
).
permitAll
()
.
antMatchers
(
"/websocket/**"
).
permitAll
()
.
antMatchers
(
"/druid/**"
).
anonymous
()
// swagger start
.
antMatchers
(
"/swagger-ui.html"
).
anonymous
()
.
antMatchers
(
"/swagger-resources/**"
).
anonymous
()
.
antMatchers
(
"/webjars/**"
).
anonymous
()
.
antMatchers
(
"/*/api-docs"
).
anonymous
()
// swagger end
.
antMatchers
(
"/test/**"
).
anonymous
()
.
antMatchers
(
HttpMethod
.
OPTIONS
,
"/**"
).
anonymous
()
.
antMatchers
(
"/druid/**"
).
anonymous
()
// 所有请求都需要认证
// swagger start
.
anyRequest
().
authenticated
();
.
antMatchers
(
"/swagger-ui.html"
).
anonymous
()
.
antMatchers
(
"/swagger-resources/**"
).
anonymous
()
.
antMatchers
(
"/webjars/**"
).
anonymous
()
.
antMatchers
(
"/*/api-docs"
).
anonymous
()
// swagger end
.
antMatchers
(
HttpMethod
.
OPTIONS
,
"/**"
).
anonymous
()
// 所有请求都需要认证
.
anyRequest
().
authenticated
();
httpSecurity
httpSecurity
.
addFilterBefore
(
authenticationTokenFilter
,
UsernamePasswordAuthenticationFilter
.
class
);
.
addFilterBefore
(
authenticationTokenFilter
,
UsernamePasswordAuthenticationFilter
.
class
);
}
}
@Override
@Override
public
void
configure
(
WebSecurity
web
)
throws
Exception
{
public
void
configure
(
WebSecurity
web
)
throws
Exception
{
// AuthenticationTokenFilter will ignore the below paths
// AuthenticationTokenFilter will ignore the below paths
web
web
.
ignoring
()
.
ignoring
()
.
antMatchers
(
.
antMatchers
(
HttpMethod
.
POST
,
HttpMethod
.
POST
,
authenticationPath
authenticationPath
)
)
// allow anonymous resource requests
// allow anonymous resource requests
.
and
()
.
and
()
.
ignoring
()
.
ignoring
()
.
antMatchers
(
.
antMatchers
(
HttpMethod
.
GET
,
HttpMethod
.
GET
,
"/*.html"
,
"/*.html"
,
"/**/*.html"
,
"/**/*.html"
,
"/**/*.css"
,
"/**/*.css"
,
"/**/*.js"
"/**/*.js"
);
);
}
}
}
}
src/main/java/me/zhengjie/monitor/config/LogFilter.java
View file @
ebb12cd0
...
@@ -27,7 +27,7 @@ public class LogFilter extends Filter<ILoggingEvent>{
...
@@ -27,7 +27,7 @@ public class LogFilter extends Filter<ILoggingEvent>{
}
}
}
}
LogMessage
loggerMessage
=
new
LogMessage
(
LogMessage
loggerMessage
=
new
LogMessage
(
event
.
get
Message
()
event
.
get
FormattedMessage
()
/* repair format message*/
,
DateFormat
.
getDateTimeInstance
().
format
(
new
Date
(
event
.
getTimeStamp
())),
,
DateFormat
.
getDateTimeInstance
().
format
(
new
Date
(
event
.
getTimeStamp
())),
event
.
getThreadName
(),
event
.
getThreadName
(),
event
.
getLoggerName
(),
event
.
getLoggerName
(),
...
...
src/main/java/me/zhengjie/tools/rest/TestController.java
0 → 100644
View file @
ebb12cd0
package
me.zhengjie.tools.rest
;
import
me.zhengjie.common.aop.limit.Limit
;
import
org.springframework.security.access.prepost.PreAuthorize
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
java.util.concurrent.atomic.AtomicInteger
;
@RestController
@RequestMapping
(
"test"
)
public
class
TestController
{
private
static
final
AtomicInteger
ATOMIC_INTEGER
=
new
AtomicInteger
();
/**
* 测试限流注解,下面配置说明该接口 60秒内最多只能访问 10次,保存到redis的键名为 limit_test,
*/
@Limit
(
key
=
"test"
,
period
=
60
,
count
=
10
,
name
=
"testLimit"
,
prefix
=
"limit"
)
@GetMapping
(
"limit"
)
public
int
testLimit
()
{
return
ATOMIC_INTEGER
.
incrementAndGet
();
}
}
Write
Preview
Supports
Markdown
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