Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nnjcy-data-model
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ljb
nnjcy-data-model
Commits
20f008fa
Commit
20f008fa
authored
Sep 18, 2023
by
wqc
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
解决访问跨域配置Security
parent
f5c2f250
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
680 additions
and
2 deletions
+680
-2
spider-flow-web/src/main/java/com/zq/spiderflow/configuration/AppTokenUtils.java
+120
-0
spider-flow-web/src/main/java/com/zq/spiderflow/configuration/JwtAccessDeniedHandler.java
+38
-0
spider-flow-web/src/main/java/com/zq/spiderflow/configuration/JwtAuthenticationEntryPoint.java
+40
-0
spider-flow-web/src/main/java/com/zq/spiderflow/configuration/MybatisPlusConfig.java
+49
-0
spider-flow-web/src/main/java/com/zq/spiderflow/configuration/ProjectConfig.java
+65
-0
spider-flow-web/src/main/java/com/zq/spiderflow/configuration/SecurityConfig.java
+124
-0
spider-flow-web/src/main/java/com/zq/spiderflow/configuration/TokenConfigurer.java
+39
-0
spider-flow-web/src/main/java/com/zq/spiderflow/configuration/TokenFilter.java
+75
-0
spider-flow-web/src/main/java/com/zq/spiderflow/configuration/TokenProvider.java
+126
-0
spider-flow-web/src/main/java/com/zq/spiderflow/controller/SpiderFlowController.java
+4
-2
No files found.
spider-flow-web/src/main/java/com/zq/spiderflow/configuration/AppTokenUtils.java
0 → 100644
View file @
20f008fa
package
com
.
zq
.
spiderflow
.
configuration
;
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import
cn.hutool.core.date.DateField
;
import
cn.hutool.core.date.DateUtil
;
import
com.alibaba.fastjson.JSON
;
import
com.zq.common.base.SecurityProperties
;
import
com.zq.common.config.redis.RedisUtils
;
import
com.zq.common.vo.AppTokenVo
;
import
io.jsonwebtoken.Claims
;
import
io.jsonwebtoken.JwtBuilder
;
import
io.jsonwebtoken.Jwts
;
import
io.jsonwebtoken.SignatureAlgorithm
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.InitializingBean
;
import
org.springframework.stereotype.Component
;
import
org.springframework.util.StringUtils
;
import
javax.crypto.spec.SecretKeySpec
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.xml.bind.DatatypeConverter
;
import
java.security.Key
;
import
java.util.Date
;
import
java.util.concurrent.TimeUnit
;
/**
* @author /
*/
@Slf4j
@Component
@RequiredArgsConstructor
public
class
AppTokenUtils
implements
InitializingBean
{
private
RedisUtils
redisUtils
;
private
static
final
String
APP_TOKEN_KEY
=
"appToken"
;
private
static
Key
key
;
private
static
SignatureAlgorithm
signatureAlgorithm
;
@Override
public
void
afterPropertiesSet
()
{
signatureAlgorithm
=
SignatureAlgorithm
.
HS512
;
byte
[]
keyBytes
=
DatatypeConverter
.
parseBase64Binary
(
SecurityProperties
.
BASE64SECRET
);
key
=
new
SecretKeySpec
(
keyBytes
,
signatureAlgorithm
.
getJcaName
());
}
public
static
String
createToken
(
AppTokenVo
tokenVo
,
long
minutes
)
{
long
nowMillis
=
System
.
currentTimeMillis
();
Date
now
=
new
Date
(
nowMillis
);
JwtBuilder
jwtBuilder
=
Jwts
.
builder
()
.
setSubject
(
tokenVo
.
getPhone
())
.
setIssuedAt
(
now
)
.
claim
(
APP_TOKEN_KEY
,
tokenVo
)
.
signWith
(
signatureAlgorithm
,
key
)
// 加入ID确保生成的 Token 都不一致
.
setId
(
tokenVo
.
getUserId
().
toString
());
if
(
minutes
>=
0
)
{
long
expMillis
=
nowMillis
+
(
minutes
*
60
*
1000
);
Date
exp
=
new
Date
(
expMillis
);
jwtBuilder
.
setExpiration
(
exp
);
}
return
jwtBuilder
.
compact
();
}
public
static
AppTokenVo
getAppTokenVo
(
String
token
)
{
try
{
Claims
claims
=
Jwts
.
parser
()
.
setSigningKey
(
DatatypeConverter
.
parseBase64Binary
(
SecurityProperties
.
BASE64SECRET
))
.
parseClaimsJws
(
token
)
.
getBody
();
// fix bug: 当前用户如果没有任何权限时,在输入用户名后,刷新验证码会抛IllegalArgumentException
return
JSON
.
parseObject
(
JSON
.
toJSONString
(
claims
.
get
(
APP_TOKEN_KEY
)),
AppTokenVo
.
class
);
}
catch
(
Exception
e
)
{
return
null
;
}
}
/**
* @param token 需要检查的token
*/
public
void
checkRenewal
(
String
token
)
{
// 判断是否续期token,计算token的过期时间
long
time
=
redisUtils
.
getExpire
(
SecurityProperties
.
ONLINEKEY
+
token
)
*
1000
;
Date
expireDate
=
DateUtil
.
offset
(
new
Date
(),
DateField
.
MILLISECOND
,
(
int
)
time
);
// 判断当前时间与过期时间的时间差
long
differ
=
expireDate
.
getTime
()
-
System
.
currentTimeMillis
();
// 如果在续期检查的范围内,则续期
if
(
differ
<=
SecurityProperties
.
DETECT
)
{
long
renew
=
time
+
SecurityProperties
.
RENEW
;
redisUtils
.
expire
(
SecurityProperties
.
ONLINEKEY
+
token
,
renew
,
TimeUnit
.
MILLISECONDS
);
}
}
public
static
String
resolveToken
(
HttpServletRequest
request
)
{
String
bearerToken
=
request
.
getHeader
(
SecurityProperties
.
HEADER
);
if
(
StringUtils
.
hasText
(
bearerToken
)
&&
bearerToken
.
startsWith
(
SecurityProperties
.
getTokenStartWith
()))
{
// 去掉令牌前缀
return
bearerToken
.
replace
(
SecurityProperties
.
getTokenStartWith
(),
""
);
}
return
null
;
}
}
spider-flow-web/src/main/java/com/zq/spiderflow/configuration/JwtAccessDeniedHandler.java
0 → 100644
View file @
20f008fa
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
zq
.
spiderflow
.
configuration
;
import
org.springframework.security.access.AccessDeniedException
;
import
org.springframework.security.web.access.AccessDeniedHandler
;
import
org.springframework.stereotype.Component
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
/**
* @author Zheng Jie
*/
@Component
public
class
JwtAccessDeniedHandler
implements
AccessDeniedHandler
{
@Override
public
void
handle
(
HttpServletRequest
request
,
HttpServletResponse
response
,
AccessDeniedException
accessDeniedException
)
throws
IOException
{
//当用户在没有授权的情况下访问受保护的REST资源时,将调用此方法发送403 Forbidden响应
response
.
sendError
(
HttpServletResponse
.
SC_FORBIDDEN
,
accessDeniedException
.
getMessage
());
}
}
spider-flow-web/src/main/java/com/zq/spiderflow/configuration/JwtAuthenticationEntryPoint.java
0 → 100644
View file @
20f008fa
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
zq
.
spiderflow
.
configuration
;
import
org.springframework.security.core.AuthenticationException
;
import
org.springframework.security.web.AuthenticationEntryPoint
;
import
org.springframework.stereotype.Component
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
/**
* @author Zheng Jie
*/
@Component
public
class
JwtAuthenticationEntryPoint
implements
AuthenticationEntryPoint
{
@Override
public
void
commence
(
HttpServletRequest
request
,
HttpServletResponse
response
,
AuthenticationException
authException
)
throws
IOException
{
// 当用户尝试访问安全的REST资源而不提供任何凭据时,将调用此方法发送401 响应
response
.
sendError
(
HttpServletResponse
.
SC_UNAUTHORIZED
,
authException
==
null
?
"Unauthorized"
:
authException
.
getMessage
());
}
}
spider-flow-web/src/main/java/com/zq/spiderflow/configuration/MybatisPlusConfig.java
0 → 100644
View file @
20f008fa
package
com
.
zq
.
spiderflow
.
configuration
;
import
com.baomidou.mybatisplus.annotation.DbType
;
import
com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer
;
import
com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor
;
import
com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor
;
import
com.github.pagehelper.PageInterceptor
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
java.util.Properties
;
@Configuration
public
class
MybatisPlusConfig
{
/**
* MybatisPlus分页插件
*/
@Bean
public
MybatisPlusInterceptor
mybatisPlusInterceptor
()
{
MybatisPlusInterceptor
interceptor
=
new
MybatisPlusInterceptor
();
interceptor
.
addInnerInterceptor
(
new
PaginationInnerInterceptor
(
DbType
.
H2
));
return
interceptor
;
}
/**
* 官方原话
* MybatisPlus新的分页插件,一缓和二缓遵循mybatis的规则,
* 需要设置 MybatisConfiguration#useDeprecatedExecutor = false
* 避免缓存出现问题(该属性会在旧插件移除后一同移除)
*/
@SuppressWarnings
(
value
=
{
"deprecation"
})
@Bean
public
ConfigurationCustomizer
configurationCustomizer
()
{
return
configuration
->
configuration
.
setUseDeprecatedExecutor
(
false
);
}
/**
* pagehelper分页插件
*/
@Bean
public
PageInterceptor
pageInterceptor
()
{
PageInterceptor
pageInterceptor
=
new
PageInterceptor
();
Properties
properties
=
new
Properties
();
properties
.
put
(
"helperDialect"
,
"mysql"
);
pageInterceptor
.
setProperties
(
properties
);
return
pageInterceptor
;
}
}
spider-flow-web/src/main/java/com/zq/spiderflow/configuration/ProjectConfig.java
0 → 100644
View file @
20f008fa
package
com
.
zq
.
spiderflow
.
configuration
;
import
cn.hutool.core.io.FileUtil
;
import
cn.hutool.core.net.NetUtil
;
import
cn.hutool.system.OsInfo
;
import
cn.hutool.system.SystemUtil
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
org.springframework.stereotype.Component
;
/**
* @author wilmiam
* @since 2021/11/12 11:19
*/
@Component
@ConfigurationProperties
(
prefix
=
"project"
)
public
class
ProjectConfig
{
public
static
String
version
=
"v1.1"
;
public
static
String
windowsPath
=
"D:\\jcy-file"
;
public
static
String
linuxPath
=
"/instrument"
;
public
static
final
String
MAPPER_PATH
=
"/instrument/**"
;
public
static
final
String
HOME_URL
=
"http://"
+
NetUtil
.
getLocalhostStr
()
+
":9679/"
;
public
static
final
String
SALT
=
"MaiLu/1301"
;
public
static
final
String
SYSTEM_TAG
=
"oa-instrument"
;
public
void
setVersion
(
String
version
)
{
ProjectConfig
.
version
=
version
;
}
public
void
setWindowsPath
(
String
windowsPath
)
{
ProjectConfig
.
windowsPath
=
windowsPath
;
if
(
FileUtil
.
exist
(
windowsPath
))
{
FileUtil
.
mkdir
(
windowsPath
);
}
}
public
void
setLinuxPath
(
String
linuxPath
)
{
ProjectConfig
.
linuxPath
=
linuxPath
;
if
(
FileUtil
.
exist
(
linuxPath
))
{
FileUtil
.
mkdir
(
linuxPath
);
}
}
/**
* 获取当前系统路径
*
* @return
*/
public
static
String
getSysPath
()
{
OsInfo
osInfo
=
SystemUtil
.
getOsInfo
();
if
(
osInfo
.
isWindows
())
{
return
windowsPath
;
}
else
if
(
osInfo
.
isLinux
())
{
return
linuxPath
;
}
return
linuxPath
;
}
}
spider-flow-web/src/main/java/com/zq/spiderflow/configuration/SecurityConfig.java
0 → 100644
View file @
20f008fa
package
com
.
zq
.
spiderflow
.
configuration
;
import
com.zq.common.annotation.AnonymousAccess
;
import
com.zq.common.config.redis.RedisUtils
;
import
lombok.RequiredArgsConstructor
;
import
org.springframework.context.ApplicationContext
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.http.HttpMethod
;
import
org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity
;
import
org.springframework.security.config.annotation.web.builders.HttpSecurity
;
import
org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
;
import
org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
;
import
org.springframework.security.config.core.GrantedAuthorityDefaults
;
import
org.springframework.security.config.http.SessionCreationPolicy
;
import
org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
;
import
org.springframework.security.crypto.password.PasswordEncoder
;
import
org.springframework.web.method.HandlerMethod
;
import
org.springframework.web.servlet.mvc.method.RequestMappingInfo
;
import
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
;
import
java.util.HashSet
;
import
java.util.Map
;
import
java.util.Set
;
/**
* @author Zheng Jie
*/
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@EnableGlobalMethodSecurity
(
prePostEnabled
=
true
,
securedEnabled
=
true
)
public
class
SecurityConfig
extends
WebSecurityConfigurerAdapter
{
private
final
TokenProvider
tokenProvider
;
private
RedisUtils
redisUtils
;
private
final
JwtAuthenticationEntryPoint
authenticationErrorHandler
;
private
final
JwtAccessDeniedHandler
jwtAccessDeniedHandler
;
private
final
ApplicationContext
applicationContext
;
@Bean
public
GrantedAuthorityDefaults
grantedAuthorityDefaults
()
{
// 去除 ROLE_ 前缀
return
new
GrantedAuthorityDefaults
(
""
);
}
@Bean
public
PasswordEncoder
passwordEncoder
()
{
// 密码加密方式
return
new
BCryptPasswordEncoder
();
}
@Override
protected
void
configure
(
HttpSecurity
httpSecurity
)
throws
Exception
{
// 搜寻匿名标记 url: @AnonymousAccess
Map
<
RequestMappingInfo
,
HandlerMethod
>
handlerMethodMap
=
applicationContext
.
getBean
(
RequestMappingHandlerMapping
.
class
).
getHandlerMethods
();
Set
<
String
>
anonymousUrls
=
new
HashSet
<>();
anonymousUrls
.
add
(
"/spiderflow/**/**"
);
for
(
Map
.
Entry
<
RequestMappingInfo
,
HandlerMethod
>
infoEntry
:
handlerMethodMap
.
entrySet
())
{
HandlerMethod
handlerMethod
=
infoEntry
.
getValue
();
AnonymousAccess
anonymousAccess
=
handlerMethod
.
getMethodAnnotation
(
AnonymousAccess
.
class
);
if
(
null
!=
anonymousAccess
)
{
anonymousUrls
.
addAll
(
infoEntry
.
getKey
().
getPatternsCondition
().
getPatterns
());
}
}
httpSecurity
// 禁用 CSRF
.
csrf
().
disable
()
// .addFilterBefore(new CorsConfig(), UsernamePasswordAuthenticationFilter.class) //在指定过滤器前添加过滤器
// 授权异常
.
exceptionHandling
()
.
authenticationEntryPoint
(
authenticationErrorHandler
)
.
accessDeniedHandler
(
jwtAccessDeniedHandler
)
// 防止iframe 造成跨域
.
and
()
.
headers
()
.
frameOptions
()
.
disable
()
// 不创建会话
.
and
()
.
sessionManagement
()
.
sessionCreationPolicy
(
SessionCreationPolicy
.
STATELESS
)
.
and
()
.
authorizeRequests
()
// 静态资源等等
.
antMatchers
(
HttpMethod
.
GET
,
"/*.html"
,
"/**/*.html"
,
"/**/*.css"
,
"/**/*.js"
,
"/**/*.xlxs"
,
"/webSocket/**"
).
permitAll
()
// swagger 文档
.
antMatchers
(
"/swagger-ui.html"
).
permitAll
()
.
antMatchers
(
"/swagger-resources/**"
).
permitAll
()
.
antMatchers
(
"/webjars/**"
).
permitAll
()
.
antMatchers
(
"/*/api-docs"
).
permitAll
()
// 文件
.
antMatchers
(
"/avatar/**"
).
permitAll
()
.
antMatchers
(
"/file/**"
).
permitAll
()
// 阿里巴巴 druid
.
antMatchers
(
"/druid/**"
).
permitAll
()
.
antMatchers
(
"/test/**"
).
permitAll
()
// 放行OPTIONS请求
.
antMatchers
(
HttpMethod
.
OPTIONS
,
"/**"
).
permitAll
()
// 自定义匿名访问所有url放行 : 允许匿名和带权限以及登录用户访问
.
antMatchers
(
anonymousUrls
.
toArray
(
new
String
[
0
])).
permitAll
()
.
antMatchers
(
"/instrument/notSueCaseReview/getUnReviewNotSueCase/**"
).
authenticated
()
.
antMatchers
(
"/instrument/notSueCaseReview/getReviewNotSueCaseHistory/**"
).
authenticated
()
.
antMatchers
(
"/instrument/handling/getNotSueCase/**"
).
authenticated
()
// 所有请求都需要认证
.
anyRequest
().
authenticated
()
.
and
().
apply
(
securityConfigurerAdapter
());
}
private
TokenConfigurer
securityConfigurerAdapter
()
{
return
new
TokenConfigurer
(
tokenProvider
);
}
}
spider-flow-web/src/main/java/com/zq/spiderflow/configuration/TokenConfigurer.java
0 → 100644
View file @
20f008fa
package
com
.
zq
.
spiderflow
.
configuration
;
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import
com.zq.common.config.redis.RedisUtils
;
import
lombok.RequiredArgsConstructor
;
import
org.springframework.security.config.annotation.SecurityConfigurerAdapter
;
import
org.springframework.security.config.annotation.web.builders.HttpSecurity
;
import
org.springframework.security.web.DefaultSecurityFilterChain
;
import
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
;
/**
* @author /
*/
@RequiredArgsConstructor
public
class
TokenConfigurer
extends
SecurityConfigurerAdapter
<
DefaultSecurityFilterChain
,
HttpSecurity
>
{
private
final
TokenProvider
tokenProvider
;
private
RedisUtils
redisUtils
;
@Override
public
void
configure
(
HttpSecurity
http
)
{
TokenFilter
customFilter
=
new
TokenFilter
(
tokenProvider
,
redisUtils
);
http
.
addFilterBefore
(
customFilter
,
UsernamePasswordAuthenticationFilter
.
class
);
}
}
spider-flow-web/src/main/java/com/zq/spiderflow/configuration/TokenFilter.java
0 → 100644
View file @
20f008fa
package
com
.
zq
.
spiderflow
.
configuration
;
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import
cn.hutool.core.util.StrUtil
;
import
com.zq.common.base.SecurityProperties
;
import
com.zq.common.config.redis.RedisUtils
;
import
com.zq.common.utils.TokenUtils
;
import
com.zq.common.vo.OnlineUserDto
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.context.SecurityContextHolder
;
import
org.springframework.util.StringUtils
;
import
org.springframework.web.filter.GenericFilterBean
;
import
javax.servlet.FilterChain
;
import
javax.servlet.ServletException
;
import
javax.servlet.ServletRequest
;
import
javax.servlet.ServletResponse
;
import
javax.servlet.http.HttpServletRequest
;
import
java.io.IOException
;
/**
* @author /
*/
@Slf4j
public
class
TokenFilter
extends
GenericFilterBean
{
private
final
TokenProvider
tokenProvider
;
private
RedisUtils
redisUtils
;
public
TokenFilter
(
TokenProvider
tokenProvider
,
RedisUtils
redisUtils
)
{
this
.
tokenProvider
=
tokenProvider
;
this
.
redisUtils
=
redisUtils
;
}
@Override
public
void
doFilter
(
ServletRequest
servletRequest
,
ServletResponse
servletResponse
,
FilterChain
filterChain
)
throws
IOException
,
ServletException
{
HttpServletRequest
httpServletRequest
=
(
HttpServletRequest
)
servletRequest
;
String
token
=
TokenProvider
.
resolveToken
(
httpServletRequest
);
// 对于 Token 为空的不需要去查 Redis
if
(
StrUtil
.
isNotBlank
(
token
))
{
OnlineUserDto
onlineUserDto
=
null
;
try
{
onlineUserDto
=
redisUtils
.
getObj
(
SecurityProperties
.
ONLINEKEY
+
token
,
OnlineUserDto
.
class
);
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
());
}
if
(
onlineUserDto
!=
null
&&
StringUtils
.
hasText
(
token
))
{
Authentication
authentication
=
tokenProvider
.
getAuthentication
(
token
);
SecurityContextHolder
.
getContext
().
setAuthentication
(
authentication
);
// Token 续期
tokenProvider
.
checkRenewal
(
token
);
// 存到线程上下文
TokenUtils
.
setAdminContext
(
onlineUserDto
);
}
}
filterChain
.
doFilter
(
servletRequest
,
servletResponse
);
}
}
spider-flow-web/src/main/java/com/zq/spiderflow/configuration/TokenProvider.java
0 → 100644
View file @
20f008fa
package
com
.
zq
.
spiderflow
.
configuration
;
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import
cn.hutool.core.date.DateField
;
import
cn.hutool.core.date.DateUtil
;
import
cn.hutool.core.util.IdUtil
;
import
cn.hutool.core.util.ObjectUtil
;
import
com.zq.common.base.SecurityProperties
;
import
com.zq.common.config.redis.RedisUtils
;
import
io.jsonwebtoken.Claims
;
import
io.jsonwebtoken.Jwts
;
import
io.jsonwebtoken.SignatureAlgorithm
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.InitializingBean
;
import
org.springframework.security.authentication.UsernamePasswordAuthenticationToken
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.GrantedAuthority
;
import
org.springframework.security.core.authority.SimpleGrantedAuthority
;
import
org.springframework.security.core.userdetails.User
;
import
org.springframework.stereotype.Component
;
import
org.springframework.util.StringUtils
;
import
javax.crypto.spec.SecretKeySpec
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.xml.bind.DatatypeConverter
;
import
java.security.Key
;
import
java.util.Arrays
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.Date
;
import
java.util.concurrent.TimeUnit
;
import
java.util.stream.Collectors
;
/**
* @author /
*/
@Slf4j
@Component
@RequiredArgsConstructor
public
class
TokenProvider
implements
InitializingBean
{
private
RedisUtils
redisUtils
;
private
static
final
String
AUTHORITIES_KEY
=
"auth"
;
private
static
Key
key
;
private
static
SignatureAlgorithm
signatureAlgorithm
;
@Override
public
void
afterPropertiesSet
()
{
signatureAlgorithm
=
SignatureAlgorithm
.
HS512
;
byte
[]
keyBytes
=
DatatypeConverter
.
parseBase64Binary
(
SecurityProperties
.
BASE64SECRET
);
key
=
new
SecretKeySpec
(
keyBytes
,
signatureAlgorithm
.
getJcaName
());
}
public
static
String
createToken
(
Authentication
authentication
)
{
String
authorities
=
authentication
.
getAuthorities
().
stream
()
.
map
(
GrantedAuthority:
:
getAuthority
)
.
collect
(
Collectors
.
joining
(
","
));
return
Jwts
.
builder
()
.
setSubject
(
authentication
.
getName
())
.
claim
(
AUTHORITIES_KEY
,
authorities
)
.
signWith
(
signatureAlgorithm
,
key
)
// 加入ID确保生成的 Token 都不一致
.
setId
(
IdUtil
.
simpleUUID
())
.
compact
();
}
public
Authentication
getAuthentication
(
String
token
)
{
Claims
claims
=
Jwts
.
parser
()
.
setSigningKey
(
DatatypeConverter
.
parseBase64Binary
(
SecurityProperties
.
BASE64SECRET
))
.
parseClaimsJws
(
token
)
.
getBody
();
// fix bug: 当前用户如果没有任何权限时,在输入用户名后,刷新验证码会抛IllegalArgumentException
Object
authoritiesStr
=
claims
.
get
(
AUTHORITIES_KEY
);
Collection
<?
extends
GrantedAuthority
>
authorities
=
ObjectUtil
.
isNotEmpty
(
authoritiesStr
)
?
Arrays
.
stream
(
authoritiesStr
.
toString
().
split
(
","
))
.
map
(
SimpleGrantedAuthority:
:
new
)
.
collect
(
Collectors
.
toList
())
:
Collections
.
emptyList
();
User
principal
=
new
User
(
claims
.
getSubject
(),
""
,
authorities
);
return
new
UsernamePasswordAuthenticationToken
(
principal
,
token
,
authorities
);
}
/**
* @param token 需要检查的token
*/
public
void
checkRenewal
(
String
token
)
{
// 判断是否续期token,计算token的过期时间
long
time
=
redisUtils
.
getExpire
(
SecurityProperties
.
ONLINEKEY
+
token
)
*
1000
;
Date
expireDate
=
DateUtil
.
offset
(
new
Date
(),
DateField
.
MILLISECOND
,
(
int
)
time
);
// 判断当前时间与过期时间的时间差
long
differ
=
expireDate
.
getTime
()
-
System
.
currentTimeMillis
();
// 如果在续期检查的范围内,则续期
if
(
differ
<=
SecurityProperties
.
DETECT
)
{
long
renew
=
time
+
SecurityProperties
.
RENEW
;
redisUtils
.
expire
(
SecurityProperties
.
ONLINEKEY
+
token
,
renew
,
TimeUnit
.
MILLISECONDS
);
}
}
public
static
String
resolveToken
(
HttpServletRequest
request
)
{
String
bearerToken
=
request
.
getHeader
(
SecurityProperties
.
HEADER
);
if
(
StringUtils
.
hasText
(
bearerToken
)
&&
bearerToken
.
startsWith
(
SecurityProperties
.
getTokenStartWith
()))
{
// 去掉令牌前缀
return
bearerToken
.
replace
(
SecurityProperties
.
getTokenStartWith
(),
""
);
}
return
null
;
}
}
spider-flow-web/src/main/java/com/zq/spiderflow/controller/SpiderFlowController.java
View file @
20f008fa
...
...
@@ -8,6 +8,7 @@ import com.zq.spiderflow.core.service.SpiderFlowService;
import
com.zq.spiderflow.core.utils.ExecutorsUtils
;
import
com.zq.spiderflow.core.vo.SpiderFlowVo
;
import
com.zq.spiderflow.vo.ResultVo
;
import
lombok.RequiredArgsConstructor
;
import
org.apache.commons.lang3.StringUtils
;
import
org.apache.commons.lang3.math.NumberUtils
;
import
org.slf4j.Logger
;
...
...
@@ -46,6 +47,7 @@ import java.util.stream.Collectors;
* @author Administrator
*
*/
@RequiredArgsConstructor
@RestController
@RequestMapping
(
value
=
"/spiderflow"
)
public
class
SpiderFlowController
{
...
...
@@ -99,7 +101,7 @@ public class SpiderFlowController {
* 爬虫列表
* @return Page<SpiderFlow> 所有爬虫的列表页
*/
@
Reque
stMapping
(
"/list"
)
@
Po
stMapping
(
"/list"
)
public
IPage
<
SpiderFlow
>
list
(
@RequestBody
SpiderFlowVo
vo
)
{
return
spiderFlowService
.
page
(
new
Page
<
SpiderFlow
>(
vo
.
getPage
(),
vo
.
getSize
()),
new
LambdaQueryWrapper
<
SpiderFlow
>().
like
(
SpiderFlow
::
getName
,
vo
.
getName
()));
}
...
...
@@ -191,7 +193,7 @@ public class SpiderFlowController {
}
}
@
Reque
stMapping
(
"/shapes"
)
@
Po
stMapping
(
"/shapes"
)
public
List
<
Shape
>
shapes
(){
return
ExecutorsUtils
.
shapes
();
}
...
...
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