Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
cloud-backend
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
framework
cloud-backend
Commits
28a94138
Commit
28a94138
authored
Jun 05, 2023
by
袁伟铭
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
添加单点登录服务
parent
6fbbb1ff
Hide whitespace changes
Inline
Side-by-side
Showing
34 changed files
with
2071 additions
and
10 deletions
+2071
-10
admin-server/pom.xml
+5
-2
admin-server/src/main/java/com/zq/admin/modules/security/rest/AuthorizationController.java
+35
-0
admin-server/src/main/java/com/zq/admin/modules/system/domain/Dept.java
+10
-2
admin-server/src/main/java/com/zq/admin/modules/system/domain/User.java
+10
-2
admin-server/src/main/java/com/zq/admin/modules/system/service/DeptService.java
+3
-2
admin-server/src/main/java/com/zq/admin/modules/system/service/UserManager.java
+178
-0
admin-server/src/main/java/com/zq/admin/modules/system/service/UserService.java
+2
-0
admin-server/src/main/java/com/zq/admin/modules/system/service/impl/DeptServiceImpl.java
+6
-0
admin-server/src/main/java/com/zq/admin/modules/system/service/impl/UserServiceImpl.java
+6
-0
cas-server/pom.xml
+86
-0
cas-server/src/main/java/com/zq/cas/OauthApplication.java
+52
-0
cas-server/src/main/java/com/zq/cas/config/CasConfig.java
+180
-0
cas-server/src/main/java/com/zq/cas/config/JumpConfig.java
+29
-0
cas-server/src/main/java/com/zq/cas/config/JwtAccessDeniedHandler.java
+38
-0
cas-server/src/main/java/com/zq/cas/config/JwtAuthenticationEntryPoint.java
+40
-0
cas-server/src/main/java/com/zq/cas/config/MyAuthenticationFilter.java
+136
-0
cas-server/src/main/java/com/zq/cas/config/SpringCasAutoconfig.java
+107
-0
cas-server/src/main/java/com/zq/cas/config/SpringSecurityConfig.java
+188
-0
cas-server/src/main/java/com/zq/cas/config/TokenConfigurer.java
+42
-0
cas-server/src/main/java/com/zq/cas/config/TokenFilter.java
+95
-0
cas-server/src/main/java/com/zq/cas/config/TokenProvider.java
+137
-0
cas-server/src/main/java/com/zq/cas/config/feign/FeignConfig.java
+93
-0
cas-server/src/main/java/com/zq/cas/config/feign/FeignSpringFormEncoder.java
+55
-0
cas-server/src/main/java/com/zq/cas/controller/AuthorizationController.java
+143
-0
cas-server/src/main/java/com/zq/cas/feignclient/AdminFeignClient.java
+25
-0
cas-server/src/main/java/com/zq/cas/service/FyUserManager.java
+48
-0
cas-server/src/main/resources/application-dev.yml
+20
-0
cas-server/src/main/resources/application-product.yml
+20
-0
cas-server/src/main/resources/application-test.yml
+20
-0
cas-server/src/main/resources/application.yml
+18
-0
cas-server/src/main/resources/bootstrap.yml
+20
-0
cas-server/src/main/resources/logback-spring.xml
+201
-0
oauth-server/pom.xml
+19
-0
pom.xml
+4
-2
No files found.
admin-server/pom.xml
View file @
28a94138
...
...
@@ -43,6 +43,10 @@
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-validation
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-test
</artifactId>
<scope>
test
</scope>
</dependency>
...
...
@@ -210,4 +214,4 @@
</resources>
</build>
</project>
\ No newline at end of file
</project>
admin-server/src/main/java/com/zq/admin/modules/security/rest/AuthorizationController.java
View file @
28a94138
...
...
@@ -25,6 +25,8 @@ import com.zq.admin.exception.BadRequestException;
import
com.zq.admin.modules.security.service.OnlineUserService
;
import
com.zq.admin.modules.security.service.dto.AuthUserDto
;
import
com.zq.admin.modules.security.service.dto.JwtUserDto
;
import
com.zq.admin.modules.system.service.UserManager
;
import
com.zq.admin.modules.system.service.UserService
;
import
com.zq.admin.utils.RsaUtils
;
import
com.zq.admin.utils.SecurityUtils
;
import
com.zq.common.annotation.rest.AnonymousDeleteMapping
;
...
...
@@ -32,6 +34,7 @@ import com.zq.common.annotation.rest.AnonymousGetMapping;
import
com.zq.common.annotation.rest.AnonymousPostMapping
;
import
com.zq.common.config.redis.RedisUtils
;
import
com.zq.common.config.security.SecurityProperties
;
import
com.zq.common.vo.ResultVo
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
lombok.RequiredArgsConstructor
;
...
...
@@ -43,6 +46,8 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio
import
org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.context.SecurityContextHolder
;
import
org.springframework.security.core.userdetails.UserDetails
;
import
org.springframework.security.core.userdetails.UserDetailsService
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.RequestBody
;
...
...
@@ -72,6 +77,9 @@ public class AuthorizationController {
private
final
OnlineUserService
onlineUserService
;
private
final
TokenProvider
tokenProvider
;
private
final
AuthenticationManagerBuilder
authenticationManagerBuilder
;
private
final
UserDetailsService
userDetailsService
;
private
final
UserService
userService
;
private
final
UserManager
userManager
;
@Resource
private
LoginProperties
loginProperties
;
...
...
@@ -148,4 +156,31 @@ public class AuthorizationController {
return
new
ResponseEntity
<>(
HttpStatus
.
OK
);
}
@ApiOperation
(
"cas登录"
)
@AnonymousPostMapping
(
value
=
"/casLogin"
)
public
ResultVo
<
Map
<
String
,
Object
>>
casLogin
(
@RequestBody
AuthUserDto
authUser
,
HttpServletRequest
request
)
{
Boolean
existName
=
userService
.
isExistName
(
authUser
.
getUsername
());
if
(!
existName
)
{
userManager
.
addUser
(
authUser
.
getUsername
());
}
else
{
userManager
.
updateUser
(
authUser
.
getUsername
());
}
UserDetails
userDetails
=
userDetailsService
.
loadUserByUsername
(
authUser
.
getUsername
());
Authentication
authentication
=
new
UsernamePasswordAuthenticationToken
(
userDetails
,
null
,
userDetails
.
getAuthorities
());
SecurityContextHolder
.
getContext
().
setAuthentication
(
authentication
);
// 生成令牌
String
token
=
TokenProvider
.
createToken
(
authentication
);
final
JwtUserDto
jwtUserDto
=
(
JwtUserDto
)
authentication
.
getPrincipal
();
// 保存在线信息
onlineUserService
.
save
(
jwtUserDto
,
token
,
request
);
// 返回 token 与 用户信息
Map
<
String
,
Object
>
authInfo
=
new
HashMap
<
String
,
Object
>(
1
)
{{
put
(
"token"
,
token
);
}};
return
ResultVo
.
success
(
authInfo
);
}
}
admin-server/src/main/java/com/zq/admin/modules/system/domain/Dept.java
View file @
28a94138
...
...
@@ -67,6 +67,15 @@ public class Dept extends BaseEntity implements Serializable {
@ApiModelProperty
(
value
=
"子节点数目"
,
hidden
=
true
)
private
Integer
subCount
=
0
;
@ApiModelProperty
(
"法院分级码"
)
private
String
gradingCode
;
@ApiModelProperty
(
"机构代码"
)
private
String
orgCode
;
@ApiModelProperty
(
value
=
"简称"
)
private
String
abbreviation
;
@Override
public
boolean
equals
(
Object
o
)
{
if
(
this
==
o
)
{
...
...
@@ -85,4 +94,4 @@ public class Dept extends BaseEntity implements Serializable {
return
Objects
.
hash
(
id
,
name
);
}
}
\ No newline at end of file
}
admin-server/src/main/java/com/zq/admin/modules/system/domain/User.java
View file @
28a94138
...
...
@@ -106,6 +106,15 @@ public class User extends BaseEntity implements Serializable {
@ApiModelProperty
(
value
=
"最后修改密码的时间"
,
hidden
=
true
)
private
Date
pwdResetTime
;
@ApiModelProperty
(
"法院分级码"
)
private
String
gradingCode
;
@ApiModelProperty
(
"用户代码"
)
private
String
userCode
;
@ApiModelProperty
(
"身份证"
)
private
String
idCard
;
@Override
public
boolean
equals
(
Object
o
)
{
if
(
this
==
o
)
{
...
...
@@ -124,4 +133,4 @@ public class User extends BaseEntity implements Serializable {
return
Objects
.
hash
(
id
,
username
);
}
}
\ No newline at end of file
}
admin-server/src/main/java/com/zq/admin/modules/system/service/DeptService.java
View file @
28a94138
...
...
@@ -135,4 +135,6 @@ public interface DeptService {
*/
void
verification
(
Set
<
DeptDto
>
deptDtos
);
}
\ No newline at end of file
Dept
getById
(
Long
orgId
);
}
admin-server/src/main/java/com/zq/admin/modules/system/service/UserManager.java
0 → 100644
View file @
28a94138
package
com
.
zq
.
admin
.
modules
.
system
.
service
;
import
cn.hutool.core.collection.CollUtil
;
import
cn.hutool.core.util.StrUtil
;
import
cn.hutool.http.HttpUtil
;
import
cn.hutool.json.JSONObject
;
import
cn.hutool.json.JSONUtil
;
import
com.zq.admin.modules.system.domain.Dept
;
import
com.zq.admin.modules.system.domain.Job
;
import
com.zq.admin.modules.system.domain.Role
;
import
com.zq.admin.modules.system.domain.User
;
import
com.zq.admin.modules.system.repository.UserRepository
;
import
lombok.RequiredArgsConstructor
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.security.crypto.password.PasswordEncoder
;
import
org.springframework.stereotype.Service
;
import
java.sql.Timestamp
;
import
java.util.Date
;
import
java.util.HashSet
;
import
java.util.Set
;
/**
* @author wilmiam
* @since 2022/10/11 18:54
*/
@RequiredArgsConstructor
@Service
public
class
UserManager
{
private
final
DeptService
deptService
;
private
final
UserService
userService
;
private
final
UserRepository
userRepository
;
private
final
PasswordEncoder
passwordEncoder
;
@Value
(
"${spring.profiles.active:dev}"
)
private
String
active
;
public
void
addUser
(
String
username
)
{
if
(
"dev"
.
equals
(
active
))
{
return
;
}
String
resultStr
=
HttpUtil
.
get
(
"http://147.1.6.23/updatelist/getUserInfo/"
+
username
.
split
(
"@"
)[
0
]);
JSONObject
userObj
=
JSONUtil
.
parseObj
(
resultStr
);
Integer
xb
=
userObj
.
getInt
(
"XB"
,
0
);
Dept
dept
=
deptService
.
getById
(
userObj
.
getLong
(
"orgId"
));
if
(
dept
==
null
)
{
dept
=
addDept
(
userObj
.
getStr
(
"JGBS"
));
}
// 默认角色
Set
<
Role
>
roleSet
=
new
HashSet
<>();
Role
role
=
new
Role
();
role
.
setId
(
3L
);
roleSet
.
add
(
role
);
// 默认岗位
Set
<
Job
>
jobSet
=
new
HashSet
<>();
Job
job
=
new
Job
();
job
.
setId
(
3L
);
jobSet
.
add
(
job
);
User
user
=
new
User
();
user
.
setId
(
userObj
.
getLong
(
"userId"
));
user
.
setDept
(
dept
);
user
.
setRoles
(
roleSet
);
user
.
setJobs
(
jobSet
);
user
.
setUsername
(
userObj
.
getStr
(
"YOUXIANG"
));
user
.
setNickName
(
userObj
.
getStr
(
"XM"
));
user
.
setEmail
(
userObj
.
getStr
(
"YOUXIANG"
));
user
.
setPhone
(
userObj
.
getStr
(
"SJHM"
));
user
.
setGender
(
xb
==
1
?
"男"
:
xb
==
2
?
"女"
:
"未知"
);
user
.
setPassword
(
passwordEncoder
.
encode
(
"Gxfy2022"
));
user
.
setEnabled
(
userObj
.
getInt
(
"YX"
)
==
1
);
user
.
setIsAdmin
(
false
);
user
.
setGradingCode
(
userObj
.
getStr
(
"FY"
));
//法院分级码
user
.
setUserCode
(
userObj
.
getStr
(
"RYBS"
));
// 人员标识
user
.
setIdCard
(
userObj
.
getStr
(
"SFZHM"
));
// 身份证号码
user
.
setCreateTime
(
new
Timestamp
(
userObj
.
getDate
(
"CJSJ"
,
new
Date
()).
getTime
()));
user
.
setUpdateTime
(
new
Timestamp
(
userObj
.
getDate
(
"GXSJ"
,
new
Date
()).
getTime
()));
userService
.
create
(
user
);
}
private
Dept
addDept
(
String
orgBs
)
{
String
resultStr
=
HttpUtil
.
get
(
"http://147.1.6.23/updatelist/getOrgInfo/"
+
orgBs
);
JSONObject
orgObj
=
JSONUtil
.
parseObj
(
resultStr
);
//获取部门id(机构id)
Long
deptId
=
orgObj
.
getLong
(
"orgId"
);
//获取上级部门id
Long
pid
=
orgObj
.
getLong
(
"parentOrgId"
);
//获取机构标识
String
orgCodes
=
orgObj
.
getStr
(
"JGBS"
);
//获取法院代码
String
gradingCode
=
orgObj
.
getStr
(
"FY"
);
Dept
dept
=
new
Dept
();
dept
.
setId
(
deptId
);
dept
.
setDeptSort
(
orgObj
.
getInt
(
"PXH"
));
dept
.
setName
(
orgObj
.
getStr
(
"MC"
));
dept
.
setEnabled
(
orgObj
.
getInt
(
"YX"
)
==
1
);
dept
.
setPid
(
pid
);
dept
.
setGradingCode
(
gradingCode
);
// 法院分级码
dept
.
setOrgCode
(
orgCodes
);
// 机构标识
dept
.
setAbbreviation
(
orgObj
.
getStr
(
"JC"
));
// 机构简称
dept
.
setCreateTime
(
new
Timestamp
(
orgObj
.
getDate
(
"CJSJ"
,
new
Date
()).
getTime
()));
dept
.
setUpdateTime
(
new
Timestamp
(
orgObj
.
getDate
(
"GXSJ"
,
new
Date
()).
getTime
()));
deptService
.
create
(
dept
);
return
dept
;
}
public
void
updateUser
(
String
username
)
{
if
(
"dev"
.
equals
(
active
))
{
return
;
}
String
resultStr
=
HttpUtil
.
get
(
"http://147.1.6.23/updatelist/getUserInfo/"
+
username
.
split
(
"@"
)[
0
]);
JSONObject
userObj
=
JSONUtil
.
parseObj
(
resultStr
);
Integer
xb
=
userObj
.
getInt
(
"XB"
,
0
);
User
user
=
userRepository
.
findByUsername
(
username
);
user
.
setNickName
(
userObj
.
getStr
(
"XM"
));
user
.
setPhone
(
userObj
.
getStr
(
"SJHM"
));
user
.
setGender
(
xb
==
1
?
"男"
:
xb
==
2
?
"女"
:
"未知"
);
user
.
setEnabled
(
userObj
.
getInt
(
"YX"
)
==
1
);
user
.
setGradingCode
(
userObj
.
getStr
(
"FY"
));
user
.
setUserCode
(
userObj
.
getStr
(
"RYBS"
));
user
.
setIdCard
(
userObj
.
getStr
(
"SFZHM"
));
user
.
setUpdateTime
(
new
Timestamp
(
userObj
.
getDate
(
"GXSJ"
,
new
Date
()).
getTime
()));
if
(
StrUtil
.
isBlank
(
user
.
getPassword
()))
{
user
.
setPassword
(
passwordEncoder
.
encode
(
"Gxfy2022"
));
}
userRepository
.
save
(
user
);
}
/**
* 添加默认角色
*
* @param userId
*/
public
boolean
addDefaultRoleAndJob
(
Long
userId
)
{
User
user
=
userRepository
.
findById
(
userId
).
orElse
(
null
);
if
(
user
!=
null
)
{
Set
<
Role
>
roleSet
=
new
HashSet
<>();
Role
role
=
new
Role
();
role
.
setId
(
3L
);
// 公共角色ID
roleSet
.
add
(
role
);
Set
<
Job
>
jobSet
=
new
HashSet
<>();
Job
job
=
new
Job
();
job
.
setId
(
3L
);
// 其他岗位ID
jobSet
.
add
(
job
);
Set
<
Role
>
roles
=
user
.
getRoles
();
if
(
CollUtil
.
isNotEmpty
(
roles
)
||
!
roles
.
contains
(
role
))
{
roleSet
.
addAll
(
roles
);
}
Set
<
Job
>
jobs
=
user
.
getJobs
();
if
(
CollUtil
.
isNotEmpty
(
jobs
)
||
!
jobs
.
contains
(
job
))
{
jobSet
.
addAll
(
jobs
);
}
user
.
setRoles
(
roleSet
);
user
.
setJobs
(
jobSet
);
userRepository
.
save
(
user
);
return
true
;
}
return
false
;
}
}
admin-server/src/main/java/com/zq/admin/modules/system/service/UserService.java
View file @
28a94138
...
...
@@ -137,4 +137,6 @@ public interface UserService {
*/
void
updateCenter
(
User
resources
);
Boolean
isExistName
(
String
username
);
}
admin-server/src/main/java/com/zq/admin/modules/system/service/impl/DeptServiceImpl.java
View file @
28a94138
...
...
@@ -252,6 +252,12 @@ public class DeptServiceImpl implements DeptService {
}
}
@Override
public
Dept
getById
(
Long
orgId
)
{
Optional
<
Dept
>
deptOptional
=
deptRepository
.
findById
(
deptId
);
return
deptOptional
.
orElse
(
null
);
}
private
void
updateSubCnt
(
Long
deptId
)
{
if
(
deptId
!=
null
)
{
int
count
=
deptRepository
.
countByPid
(
deptId
);
...
...
admin-server/src/main/java/com/zq/admin/modules/system/service/impl/UserServiceImpl.java
View file @
28a94138
...
...
@@ -157,6 +157,12 @@ public class UserServiceImpl implements UserService {
}
@Override
public
Boolean
isExistName
(
String
username
)
{
User
user
=
userRepository
.
findByUsername
(
username
);
return
user
!=
null
;
}
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
void
delete
(
Set
<
Long
>
ids
)
{
for
(
Long
id
:
ids
)
{
...
...
cas-server/pom.xml
0 → 100644
View file @
28a94138
<?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"
>
<parent>
<artifactId>
cloud-backend
</artifactId>
<groupId>
com.zq
</groupId>
<version>
1.0.0
</version>
</parent>
<modelVersion>
4.0.0
</modelVersion>
<artifactId>
cas-server
</artifactId>
<properties>
<maven.compiler.source>
8
</maven.compiler.source>
<maven.compiler.target>
8
</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>
com.zq
</groupId>
<artifactId>
xxx-common-utils
</artifactId>
<version>
1.0.0
</version>
</dependency>
<!--服务注册-->
<dependency>
<groupId>
org.springframework.cloud
</groupId>
<artifactId>
spring-cloud-starter-netflix-eureka-client
</artifactId>
</dependency>
<!-- 连接配置中心 -->
<dependency>
<groupId>
org.springframework.cloud
</groupId>
<artifactId>
spring-cloud-starter-config
</artifactId>
</dependency>
<!--Spring boot Web容器-->
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-web
</artifactId>
</dependency>
<!--Spring boot 测试-->
<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>
<!--Spring boot 安全框架-->
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-security
</artifactId>
</dependency>
<!--Spring boot Redis-->
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-data-redis
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.cloud
</groupId>
<artifactId>
spring-cloud-starter-openfeign
</artifactId>
</dependency>
<!--CAS单点登陆-->
<dependency>
<groupId>
org.jasig.cas.client
</groupId>
<artifactId>
cas-client-core
</artifactId>
<version>
3.2.0
</version>
</dependency>
<dependency>
<groupId>
net.unicon.cas
</groupId>
<artifactId>
cas-client-autoconfig-support
</artifactId>
<version>
2.1.0-GA
</version>
</dependency>
</dependencies>
</project>
cas-server/src/main/java/com/zq/cas/OauthApplication.java
0 → 100644
View file @
28a94138
/*
* 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.
*
* //@EnableEurekaClient
//@EnableDiscoveryClient
*/
package
com
.
zq
.
cas
;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
import
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
;
import
org.springframework.cloud.client.discovery.EnableDiscoveryClient
;
import
org.springframework.cloud.openfeign.EnableFeignClients
;
import
org.springframework.web.bind.annotation.GetMapping
;
/**
* @author Zheng Jie
* @date 2018/11/15 9:20:19
*/
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
(
scanBasePackages
=
{
"com.zq.auth"
,
"com.zq.common.config"
},
exclude
=
DataSourceAutoConfiguration
.
class
)
public
class
OauthApplication
{
public
static
void
main
(
String
[]
args
)
{
SpringApplication
.
run
(
OauthApplication
.
class
,
args
);
}
/**
* 访问首页提示
*
* @return /
*/
@GetMapping
(
"/"
)
public
String
index
()
{
return
"Backend service started successfully"
;
}
}
cas-server/src/main/java/com/zq/cas/config/CasConfig.java
0 → 100644
View file @
28a94138
package
com
.
zq
.
cas
.
config
;
import
org.jasig.cas.client.session.SingleSignOutFilter
;
import
org.jasig.cas.client.session.SingleSignOutHttpSessionListener
;
import
org.jasig.cas.client.util.AssertionThreadLocalFilter
;
import
org.jasig.cas.client.util.HttpServletRequestWrapperFilter
;
import
org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.boot.web.servlet.FilterRegistrationBean
;
import
org.springframework.boot.web.servlet.ServletListenerRegistrationBean
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.security.web.authentication.logout.LogoutFilter
;
import
org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler
;
import
org.springframework.stereotype.Component
;
@Component
@Configuration
public
class
CasConfig
{
@Autowired
private
SpringCasAutoconfig
autoconfig
;
private
static
boolean
casEnabled
=
true
;
public
CasConfig
()
{
}
@Bean
public
SpringCasAutoconfig
getSpringCasAutoconfig
()
{
return
new
SpringCasAutoconfig
();
}
/**
* 添加监听器
*/
@Bean
public
ServletListenerRegistrationBean
<
SingleSignOutHttpSessionListener
>
singleSignOutHttpSessionListener
()
{
ServletListenerRegistrationBean
<
SingleSignOutHttpSessionListener
>
listener
=
new
ServletListenerRegistrationBean
<>();
listener
.
setEnabled
(
casEnabled
);
listener
.
setListener
(
new
SingleSignOutHttpSessionListener
());
listener
.
setOrder
(
1
);
return
listener
;
}
/**
* 登出过滤器
* (这个过滤器不知道有什么作用)
*/
// 没用到security 可以尝试这样写,或者使用自己项目的安全LogoutFilter
// @Bean
// public FilterRegistrationBean filterSingleRegistration() {
// FilterRegistrationBean registration = new FilterRegistrationBean();
// registration.setFilter(new SingleSignOutFilter());
// // 设定匹配的路径
// registration.addUrlPatterns("/logout");
// Map<String,String> initParameters = new HashMap<String, String>();
// initParameters.put("casServerUrlPrefix", autoconfig.getCasServerUrlPrefix());
// registration.setInitParameters(initParameters);
// // 设定加载的顺序
// registration.setOrder(2);
// return registration;
// }
@Bean
public
FilterRegistrationBean
<
LogoutFilter
>
logOutFilter
()
{
FilterRegistrationBean
<
LogoutFilter
>
filterRegistration
=
new
FilterRegistrationBean
<>();
LogoutFilter
logoutFilter
=
new
LogoutFilter
(
autoconfig
.
getCasServerUrlPrefix
()
+
"/logout?service="
+
autoconfig
.
getServerName
(),
new
SecurityContextLogoutHandler
());
filterRegistration
.
setFilter
(
logoutFilter
);
filterRegistration
.
setEnabled
(
casEnabled
);
if
(
autoconfig
.
getSignOutFilters
().
size
()
>
0
)
filterRegistration
.
setUrlPatterns
(
autoconfig
.
getSignOutFilters
());
else
filterRegistration
.
addUrlPatterns
(
"/logout"
);
filterRegistration
.
addInitParameter
(
"casServerUrlPrefix"
,
autoconfig
.
getCasServerUrlPrefix
());
filterRegistration
.
addInitParameter
(
"serverName"
,
autoconfig
.
getServerName
());
filterRegistration
.
setOrder
(
2
);
return
filterRegistration
;
}
/**
* 该过滤器用于实现单点登出功能,单点退出配置,一定要放在其他filter之前
*/
@Bean
public
FilterRegistrationBean
<
SingleSignOutFilter
>
singleSignOutFilter
()
{
FilterRegistrationBean
<
SingleSignOutFilter
>
filterRegistration
=
new
FilterRegistrationBean
<>();
filterRegistration
.
setFilter
(
new
SingleSignOutFilter
());
filterRegistration
.
setEnabled
(
casEnabled
);
if
(
autoconfig
.
getSignOutFilters
().
size
()
>
0
)
filterRegistration
.
setUrlPatterns
(
autoconfig
.
getSignOutFilters
());
else
filterRegistration
.
addUrlPatterns
(
"/*"
);
filterRegistration
.
addInitParameter
(
"casServerUrlPrefix"
,
autoconfig
.
getCasServerUrlPrefix
());
filterRegistration
.
addInitParameter
(
"serverName"
,
autoconfig
.
getServerName
());
filterRegistration
.
setOrder
(
3
);
return
filterRegistration
;
}
/**
* 授权过滤器,用于登录
* 该过滤器负责用户的认证工作
*/
@Bean
public
FilterRegistrationBean
<
MyAuthenticationFilter
>
authenticationFilter
()
{
FilterRegistrationBean
<
MyAuthenticationFilter
>
filterRegistration
=
new
FilterRegistrationBean
<>();
filterRegistration
.
setFilter
(
new
MyAuthenticationFilter
());
filterRegistration
.
setEnabled
(
casEnabled
);
if
(
autoconfig
.
getAuthFilters
().
size
()
>
0
)
filterRegistration
.
setUrlPatterns
(
autoconfig
.
getAuthFilters
());
else
filterRegistration
.
addUrlPatterns
(
"/*"
);
//casServerLoginUrl:cas服务的登陆url
filterRegistration
.
addInitParameter
(
"casServerLoginUrl"
,
autoconfig
.
getCasServerLoginUrl
());
//本项目登录ip+port
filterRegistration
.
addInitParameter
(
"serverName"
,
autoconfig
.
getServerName
());
filterRegistration
.
addInitParameter
(
"useSession"
,
autoconfig
.
isUseSession
()
?
"true"
:
"false"
);
filterRegistration
.
addInitParameter
(
"redirectAfterValidation"
,
autoconfig
.
isRedirectAfterValidation
()
?
"true"
:
"false"
);
filterRegistration
.
setOrder
(
4
);
return
filterRegistration
;
}
/**
* ticke验证器
* 该过滤器负责对Ticket的校验工作
*/
@Bean
public
FilterRegistrationBean
<
Cas20ProxyReceivingTicketValidationFilter
>
cas20ProxyReceivingTicketValidationFilter
()
{
FilterRegistrationBean
<
Cas20ProxyReceivingTicketValidationFilter
>
filterRegistration
=
new
FilterRegistrationBean
<>();
Cas20ProxyReceivingTicketValidationFilter
cas20ProxyReceivingTicketValidationFilter
=
new
Cas20ProxyReceivingTicketValidationFilter
();
cas20ProxyReceivingTicketValidationFilter
.
setServerName
(
autoconfig
.
getServerName
());
filterRegistration
.
setFilter
(
cas20ProxyReceivingTicketValidationFilter
);
filterRegistration
.
setEnabled
(
casEnabled
);
if
(
autoconfig
.
getValidateFilters
().
size
()
>
0
)
filterRegistration
.
setUrlPatterns
(
autoconfig
.
getValidateFilters
());
else
filterRegistration
.
addUrlPatterns
(
"/*"
);
filterRegistration
.
addInitParameter
(
"casServerUrlPrefix"
,
autoconfig
.
getCasServerUrlPrefix
());
filterRegistration
.
addInitParameter
(
"serverName"
,
autoconfig
.
getServerName
());
filterRegistration
.
setOrder
(
5
);
return
filterRegistration
;
}
/**
* wraper过滤器
* 该过滤器对HttpServletRequest请求包装, 可通过HttpServletRequest的getRemoteUser()方法获得登录用户的登录名
*/
@Bean
public
FilterRegistrationBean
<
HttpServletRequestWrapperFilter
>
httpServletRequestWrapperFilter
()
{
FilterRegistrationBean
<
HttpServletRequestWrapperFilter
>
filterRegistration
=
new
FilterRegistrationBean
<>();
filterRegistration
.
setFilter
(
new
HttpServletRequestWrapperFilter
());
filterRegistration
.
setEnabled
(
true
);
if
(
autoconfig
.
getRequestWrapperFilters
().
size
()
>
0
)
filterRegistration
.
setUrlPatterns
(
autoconfig
.
getRequestWrapperFilters
());
else
filterRegistration
.
addUrlPatterns
(
"/login"
);
filterRegistration
.
setOrder
(
6
);
return
filterRegistration
;
}
/**
* 该过滤器使得可以通过org.jasig.cas.client.util.AssertionHolder来获取用户的登录名。
* 比如AssertionHolder.getAssertion().getPrincipal().getName()。
* 这个类把Assertion信息放在ThreadLocal变量中,这样应用程序不在web层也能够获取到当前登录信息
*/
@Bean
public
FilterRegistrationBean
<
AssertionThreadLocalFilter
>
assertionThreadLocalFilter
()
{
FilterRegistrationBean
<
AssertionThreadLocalFilter
>
filterRegistration
=
new
FilterRegistrationBean
<>();
filterRegistration
.
setFilter
(
new
AssertionThreadLocalFilter
());
filterRegistration
.
setEnabled
(
true
);
if
(
autoconfig
.
getAssertionFilters
().
size
()
>
0
)
filterRegistration
.
setUrlPatterns
(
autoconfig
.
getAssertionFilters
());
else
filterRegistration
.
addUrlPatterns
(
"/*"
);
filterRegistration
.
setOrder
(
7
);
return
filterRegistration
;
}
}
cas-server/src/main/java/com/zq/cas/config/JumpConfig.java
0 → 100644
View file @
28a94138
package
com
.
zq
.
cas
.
config
;
import
cn.hutool.core.util.StrUtil
;
import
lombok.Data
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
org.springframework.context.annotation.Configuration
;
import
java.util.Map
;
/**
* @author wilmiam
* @since 2022/10/13 18:09
*/
@Data
@Configuration
@ConfigurationProperties
(
prefix
=
"jump"
)
public
class
JumpConfig
{
private
Map
<
String
,
String
>
domainMap
;
public
String
getDomain
(
String
systemTag
)
{
String
url
=
domainMap
.
get
(
systemTag
);
if
(
StrUtil
.
isBlank
(
url
))
{
url
=
domainMap
.
get
(
"default"
);
}
return
url
;
}
}
cas-server/src/main/java/com/zq/cas/config/JwtAccessDeniedHandler.java
0 → 100644
View file @
28a94138
/*
* 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
.
cas
.
config
;
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
());
}
}
cas-server/src/main/java/com/zq/cas/config/JwtAuthenticationEntryPoint.java
0 → 100644
View file @
28a94138
/*
* 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
.
cas
.
config
;
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
());
}
}
cas-server/src/main/java/com/zq/cas/config/MyAuthenticationFilter.java
0 → 100644
View file @
28a94138
package
com
.
zq
.
cas
.
config
;
import
cn.hutool.json.JSONUtil
;
import
com.zq.common.vo.ResultVo
;
import
lombok.extern.slf4j.Slf4j
;
import
org.jasig.cas.client.authentication.DefaultGatewayResolverImpl
;
import
org.jasig.cas.client.authentication.GatewayResolver
;
import
org.jasig.cas.client.util.AbstractCasFilter
;
import
org.jasig.cas.client.util.CommonUtils
;
import
org.jasig.cas.client.validation.Assertion
;
import
javax.servlet.*
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
javax.servlet.http.HttpSession
;
import
java.io.IOException
;
import
java.io.PrintWriter
;
@Slf4j
public
class
MyAuthenticationFilter
extends
AbstractCasFilter
{
private
String
casServerLoginUrl
;
private
boolean
renew
=
false
;
private
boolean
gateway
=
false
;
private
GatewayResolver
gatewayStorage
=
new
DefaultGatewayResolverImpl
();
public
MyAuthenticationFilter
()
{
}
protected
void
initInternal
(
FilterConfig
filterConfig
)
throws
ServletException
{
if
(!
this
.
isIgnoreInitConfiguration
())
{
super
.
initInternal
(
filterConfig
);
this
.
setCasServerLoginUrl
(
this
.
getPropertyFromInitParams
(
filterConfig
,
"casServerLoginUrl"
,
(
String
)
null
));
this
.
log
.
trace
(
"Loaded CasServerLoginUrl parameter: "
+
this
.
casServerLoginUrl
);
this
.
setRenew
(
this
.
parseBoolean
(
this
.
getPropertyFromInitParams
(
filterConfig
,
"renew"
,
"false"
)));
this
.
log
.
trace
(
"Loaded renew parameter: "
+
this
.
renew
);
this
.
setGateway
(
this
.
parseBoolean
(
this
.
getPropertyFromInitParams
(
filterConfig
,
"gateway"
,
"false"
)));
this
.
log
.
trace
(
"Loaded gateway parameter: "
+
this
.
gateway
);
String
gatewayStorageClass
=
this
.
getPropertyFromInitParams
(
filterConfig
,
"gatewayStorageClass"
,
(
String
)
null
);
if
(
gatewayStorageClass
!=
null
)
{
try
{
this
.
gatewayStorage
=
(
GatewayResolver
)
Class
.
forName
(
gatewayStorageClass
).
newInstance
();
}
catch
(
Exception
var4
)
{
this
.
log
.
error
(
String
.
valueOf
(
var4
),
var4
);
throw
new
ServletException
(
var4
);
}
}
}
}
public
void
init
()
{
super
.
init
();
CommonUtils
.
assertNotNull
(
this
.
casServerLoginUrl
,
"casServerLoginUrl cannot be null."
);
}
public
final
void
doFilter
(
ServletRequest
servletRequest
,
ServletResponse
servletResponse
,
FilterChain
filterChain
)
throws
IOException
,
ServletException
{
HttpServletRequest
request
=
(
HttpServletRequest
)
servletRequest
;
HttpServletResponse
response
=
(
HttpServletResponse
)
servletResponse
;
PrintWriter
out
=
null
;
HttpSession
session
=
request
.
getSession
(
false
);
Assertion
assertion
=
session
!=
null
?
(
Assertion
)
session
.
getAttribute
(
"_const_cas_assertion_"
)
:
null
;
if
(
assertion
!=
null
)
{
filterChain
.
doFilter
(
request
,
response
);
}
else
{
String
serviceUrl
=
this
.
constructServiceUrl
(
request
,
response
);
String
ticket
=
CommonUtils
.
safeGetParameter
(
request
,
this
.
getArtifactParameterName
());
boolean
wasGatewayed
=
this
.
gatewayStorage
.
hasGatewayedAlready
(
request
,
serviceUrl
);
if
(!
CommonUtils
.
isNotBlank
(
ticket
)
&&
!
wasGatewayed
)
{
this
.
log
.
debug
(
"no ticket and no assertion found"
);
String
modifiedServiceUrl
;
if
(
this
.
gateway
)
{
this
.
log
.
debug
(
"setting gateway attribute in session"
);
modifiedServiceUrl
=
this
.
gatewayStorage
.
storeGatewayInformation
(
request
,
serviceUrl
);
}
else
{
modifiedServiceUrl
=
serviceUrl
;
}
if
(
this
.
log
.
isDebugEnabled
())
{
this
.
log
.
debug
(
"Constructed service url: "
+
modifiedServiceUrl
);
}
String
urlToRedirectTo
=
CommonUtils
.
constructRedirectUrl
(
this
.
casServerLoginUrl
,
this
.
getServiceParameterName
(),
modifiedServiceUrl
,
this
.
renew
,
this
.
gateway
);
if
(
urlToRedirectTo
.
contains
(
"&"
))
{
String
[]
split
=
urlToRedirectTo
.
split
(
"&"
);
urlToRedirectTo
=
split
[
0
];
}
if
(
this
.
log
.
isDebugEnabled
())
{
this
.
log
.
debug
(
"redirecting to \""
+
urlToRedirectTo
+
"\""
);
}
//不适用它原来的,换成自定义重定向类型
//response.sendRedirect(urlToRedirectTo);
//这个的话无法使用 ip直接跳转登陆 必须使用 ip/oauth/login 才能登陆
/*if(serviceUrl.contains("logout") || serviceUrl.contains("login")){
response.sendRedirect(urlToRedirectTo);
}else {
response.setContentType("application/json;charset=UTF-8");
out = response.getWriter();
out.println(JSONUtil.toJsonStr(ResultVo.fail(401,"登陆身份已失效")));
out.flush();
out.close();
}*/
//不能使用 ip+/oauth/login 跳转登陆 接口200返回401,可直接ip和页面路由进行拦截跳转
response
.
setContentType
(
"application/json;charset=UTF-8"
);
out
=
response
.
getWriter
();
out
.
println
(
JSONUtil
.
toJsonStr
(
ResultVo
.
fail
(
401
,
"登陆身份已失效"
)));
out
.
flush
();
out
.
close
();
}
else
{
filterChain
.
doFilter
(
request
,
response
);
}
}
}
public
final
void
setRenew
(
boolean
renew
)
{
this
.
renew
=
renew
;
}
public
final
void
setGateway
(
boolean
gateway
)
{
this
.
gateway
=
gateway
;
}
public
final
void
setCasServerLoginUrl
(
String
casServerLoginUrl
)
{
this
.
casServerLoginUrl
=
casServerLoginUrl
;
}
public
final
void
setGatewayStorage
(
GatewayResolver
gatewayStorage
)
{
this
.
gatewayStorage
=
gatewayStorage
;
}
}
cas-server/src/main/java/com/zq/cas/config/SpringCasAutoconfig.java
0 → 100644
View file @
28a94138
package
com
.
zq
.
cas
.
config
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
org.springframework.boot.context.properties.EnableConfigurationProperties
;
import
java.util.Arrays
;
import
java.util.List
;
@EnableConfigurationProperties
(
SpringCasAutoconfig
.
class
)
@ConfigurationProperties
(
prefix
=
"spring.cas"
)
public
class
SpringCasAutoconfig
{
private
static
final
String
separator
=
","
;
private
String
validateFilters
;
private
String
signOutFilters
;
private
String
authFilters
;
private
String
assertionFilters
;
private
String
requestWrapperFilters
;
private
String
casServerUrlPrefix
;
private
String
casServerLoginUrl
;
private
String
serverName
;
private
boolean
useSession
=
true
;
private
boolean
redirectAfterValidation
=
true
;
public
List
<
String
>
getValidateFilters
()
{
return
Arrays
.
asList
(
validateFilters
.
split
(
separator
));
}
public
void
setValidateFilters
(
String
validateFilters
)
{
this
.
validateFilters
=
validateFilters
;
}
public
List
<
String
>
getSignOutFilters
()
{
return
Arrays
.
asList
(
signOutFilters
.
split
(
separator
));
}
public
void
setSignOutFilters
(
String
signOutFilters
)
{
this
.
signOutFilters
=
signOutFilters
;
}
public
List
<
String
>
getAuthFilters
()
{
return
Arrays
.
asList
(
authFilters
.
split
(
separator
));
}
public
void
setAuthFilters
(
String
authFilters
)
{
this
.
authFilters
=
authFilters
;
}
public
List
<
String
>
getAssertionFilters
()
{
return
Arrays
.
asList
(
assertionFilters
.
split
(
separator
));
}
public
void
setAssertionFilters
(
String
assertionFilters
)
{
this
.
assertionFilters
=
assertionFilters
;
}
public
List
<
String
>
getRequestWrapperFilters
()
{
return
Arrays
.
asList
(
requestWrapperFilters
.
split
(
separator
));
}
public
void
setRequestWrapperFilters
(
String
requestWrapperFilters
)
{
this
.
requestWrapperFilters
=
requestWrapperFilters
;
}
public
String
getCasServerUrlPrefix
()
{
return
casServerUrlPrefix
;
}
public
void
setCasServerUrlPrefix
(
String
casServerUrlPrefix
)
{
this
.
casServerUrlPrefix
=
casServerUrlPrefix
;
}
public
String
getCasServerLoginUrl
()
{
return
casServerLoginUrl
;
}
public
void
setCasServerLoginUrl
(
String
casServerLoginUrl
)
{
this
.
casServerLoginUrl
=
casServerLoginUrl
;
}
public
String
getServerName
()
{
return
serverName
;
}
public
void
setServerName
(
String
serverName
)
{
this
.
serverName
=
serverName
;
}
public
boolean
isRedirectAfterValidation
()
{
return
redirectAfterValidation
;
}
public
void
setRedirectAfterValidation
(
boolean
redirectAfterValidation
)
{
this
.
redirectAfterValidation
=
redirectAfterValidation
;
}
public
boolean
isUseSession
()
{
return
useSession
;
}
public
void
setUseSession
(
boolean
useSession
)
{
this
.
useSession
=
useSession
;
}
}
cas-server/src/main/java/com/zq/cas/config/SpringSecurityConfig.java
0 → 100644
View file @
28a94138
/*
* 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
.
cas
.
config
;
import
com.zq.common.annotation.AnonymousAccess
;
import
com.zq.common.config.redis.RedisUtils
;
import
com.zq.common.config.security.SecurityProperties
;
import
com.zq.common.utils.RequestMethodEnum
;
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.bind.annotation.RequestMethod
;
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.*
;
/**
* @author Zheng Jie
*/
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@EnableGlobalMethodSecurity
(
prePostEnabled
=
true
,
securedEnabled
=
true
)
public
class
SpringSecurityConfig
extends
WebSecurityConfigurerAdapter
{
private
final
TokenProvider
tokenProvider
;
private
final
JwtAuthenticationEntryPoint
authenticationErrorHandler
;
private
final
JwtAccessDeniedHandler
jwtAccessDeniedHandler
;
private
final
ApplicationContext
applicationContext
;
private
final
SecurityProperties
properties
;
private
final
RedisUtils
redisUtils
;
@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
RequestMappingHandlerMapping
requestMappingHandlerMapping
=
(
RequestMappingHandlerMapping
)
applicationContext
.
getBean
(
"requestMappingHandlerMapping"
);
Map
<
RequestMappingInfo
,
HandlerMethod
>
handlerMethodMap
=
requestMappingHandlerMapping
.
getHandlerMethods
();
// 获取匿名标记
Map
<
String
,
Set
<
String
>>
anonymousUrls
=
getAnonymousUrl
(
handlerMethodMap
);
Set
<
String
>
allType
=
anonymousUrls
.
get
(
RequestMethodEnum
.
ALL
.
getType
());
//不使用注解的时候在这添加url放行
// allType.add("/user/api/**");
httpSecurity
// 禁用 CSRF
.
csrf
().
disable
()
// .addFilterBefore(corsFilter, 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"
,
"/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
()
// 放行OPTIONS请求
.
antMatchers
(
HttpMethod
.
OPTIONS
,
"/**"
).
permitAll
()
// 自定义匿名访问所有url放行:允许匿名和带Token访问,细腻化到每个 Request 类型
// GET
.
antMatchers
(
HttpMethod
.
GET
,
anonymousUrls
.
get
(
RequestMethodEnum
.
GET
.
getType
()).
toArray
(
new
String
[
0
])).
permitAll
()
// POST
.
antMatchers
(
HttpMethod
.
POST
,
anonymousUrls
.
get
(
RequestMethodEnum
.
POST
.
getType
()).
toArray
(
new
String
[
0
])).
permitAll
()
// PUT
.
antMatchers
(
HttpMethod
.
PUT
,
anonymousUrls
.
get
(
RequestMethodEnum
.
PUT
.
getType
()).
toArray
(
new
String
[
0
])).
permitAll
()
// PATCH
.
antMatchers
(
HttpMethod
.
PATCH
,
anonymousUrls
.
get
(
RequestMethodEnum
.
PATCH
.
getType
()).
toArray
(
new
String
[
0
])).
permitAll
()
// DELETE
.
antMatchers
(
HttpMethod
.
DELETE
,
anonymousUrls
.
get
(
RequestMethodEnum
.
DELETE
.
getType
()).
toArray
(
new
String
[
0
])).
permitAll
()
// 所有类型的接口都放行
.
antMatchers
(
allType
.
toArray
(
new
String
[
0
])).
permitAll
()
// 所有请求都需要认证
.
anyRequest
().
authenticated
()
.
and
().
apply
(
securityConfigurerAdapter
());
}
private
TokenConfigurer
securityConfigurerAdapter
()
{
return
new
TokenConfigurer
(
tokenProvider
,
properties
,
redisUtils
);
}
private
Map
<
String
,
Set
<
String
>>
getAnonymousUrl
(
Map
<
RequestMappingInfo
,
HandlerMethod
>
handlerMethodMap
)
{
Map
<
String
,
Set
<
String
>>
anonymousUrls
=
new
HashMap
<>(
6
);
Set
<
String
>
get
=
new
HashSet
<>();
Set
<
String
>
post
=
new
HashSet
<>();
Set
<
String
>
put
=
new
HashSet
<>();
Set
<
String
>
patch
=
new
HashSet
<>();
Set
<
String
>
delete
=
new
HashSet
<>();
Set
<
String
>
all
=
new
HashSet
<>();
for
(
Map
.
Entry
<
RequestMappingInfo
,
HandlerMethod
>
infoEntry
:
handlerMethodMap
.
entrySet
())
{
HandlerMethod
handlerMethod
=
infoEntry
.
getValue
();
AnonymousAccess
anonymousAccess
=
handlerMethod
.
getMethodAnnotation
(
AnonymousAccess
.
class
);
if
(
null
!=
anonymousAccess
)
{
List
<
RequestMethod
>
requestMethods
=
new
ArrayList
<>(
infoEntry
.
getKey
().
getMethodsCondition
().
getMethods
());
RequestMethodEnum
request
=
RequestMethodEnum
.
find
(
requestMethods
.
size
()
==
0
?
RequestMethodEnum
.
ALL
.
getType
()
:
requestMethods
.
get
(
0
).
name
());
switch
(
Objects
.
requireNonNull
(
request
))
{
case
GET:
get
.
addAll
(
infoEntry
.
getKey
().
getPatternsCondition
().
getPatterns
());
break
;
case
POST:
post
.
addAll
(
infoEntry
.
getKey
().
getPatternsCondition
().
getPatterns
());
break
;
case
PUT:
put
.
addAll
(
infoEntry
.
getKey
().
getPatternsCondition
().
getPatterns
());
break
;
case
PATCH:
patch
.
addAll
(
infoEntry
.
getKey
().
getPatternsCondition
().
getPatterns
());
break
;
case
DELETE:
delete
.
addAll
(
infoEntry
.
getKey
().
getPatternsCondition
().
getPatterns
());
break
;
default
:
all
.
addAll
(
infoEntry
.
getKey
().
getPatternsCondition
().
getPatterns
());
break
;
}
}
}
anonymousUrls
.
put
(
RequestMethodEnum
.
GET
.
getType
(),
get
);
anonymousUrls
.
put
(
RequestMethodEnum
.
POST
.
getType
(),
post
);
anonymousUrls
.
put
(
RequestMethodEnum
.
PUT
.
getType
(),
put
);
anonymousUrls
.
put
(
RequestMethodEnum
.
PATCH
.
getType
(),
patch
);
anonymousUrls
.
put
(
RequestMethodEnum
.
DELETE
.
getType
(),
delete
);
anonymousUrls
.
put
(
RequestMethodEnum
.
ALL
.
getType
(),
all
);
return
anonymousUrls
;
}
}
cas-server/src/main/java/com/zq/cas/config/TokenConfigurer.java
0 → 100644
View file @
28a94138
/*
* 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
.
cas
.
config
;
import
com.zq.common.config.redis.RedisUtils
;
import
com.zq.common.config.security.SecurityProperties
;
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
final
SecurityProperties
properties
;
private
final
RedisUtils
redisUtils
;
@Override
public
void
configure
(
HttpSecurity
http
)
{
TokenFilter
customFilter
=
new
TokenFilter
(
tokenProvider
,
properties
,
redisUtils
);
http
.
addFilterBefore
(
customFilter
,
UsernamePasswordAuthenticationFilter
.
class
);
}
}
cas-server/src/main/java/com/zq/cas/config/TokenFilter.java
0 → 100644
View file @
28a94138
/*
* 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
.
cas
.
config
;
import
cn.hutool.core.util.StrUtil
;
import
com.zq.common.config.redis.BaseCacheKeys
;
import
com.zq.common.config.redis.RedisUtils
;
import
com.zq.common.config.security.SecurityProperties
;
import
com.zq.common.context.ContextUtils
;
import
com.zq.common.vo.OnlineUserDto
;
import
io.jsonwebtoken.ExpiredJwtException
;
import
org.apache.commons.lang3.StringUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.context.SecurityContextHolder
;
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
;
import
java.util.Objects
;
/**
* @author /
*/
public
class
TokenFilter
extends
GenericFilterBean
{
private
static
final
Logger
log
=
LoggerFactory
.
getLogger
(
TokenFilter
.
class
);
private
final
TokenProvider
tokenProvider
;
private
final
SecurityProperties
properties
;
private
final
RedisUtils
redisUtils
;
/**
* @param tokenProvider Token
* @param properties JWT
* @param redisUtils redis
*/
public
TokenFilter
(
TokenProvider
tokenProvider
,
SecurityProperties
properties
,
RedisUtils
redisUtils
)
{
this
.
properties
=
properties
;
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
.
getToken
(
httpServletRequest
);
// 对于 Token 为空的不需要去查 Redis
if
(
StrUtil
.
isNotBlank
(
token
))
{
OnlineUserDto
onlineUserDto
=
null
;
boolean
cleanUserCache
=
false
;
try
{
onlineUserDto
=
redisUtils
.
getObj
(
properties
.
getOnlineKey
()
+
token
,
OnlineUserDto
.
class
);
}
catch
(
ExpiredJwtException
e
)
{
log
.
error
(
e
.
getMessage
());
cleanUserCache
=
true
;
}
finally
{
if
(
cleanUserCache
||
Objects
.
isNull
(
onlineUserDto
))
{
String
username
=
String
.
valueOf
(
tokenProvider
.
getClaims
(
token
).
get
(
TokenProvider
.
AUTHORITIES_KEY
));
redisUtils
.
hdel
(
BaseCacheKeys
.
USER_DATA_MAP_KEY
,
username
);
}
}
if
(
onlineUserDto
!=
null
&&
StringUtils
.
isNotBlank
(
token
))
{
Authentication
authentication
=
tokenProvider
.
getAuthentication
(
token
);
SecurityContextHolder
.
getContext
().
setAuthentication
(
authentication
);
// Token 续期
tokenProvider
.
checkRenewal
(
token
);
// 设置当前用户
ContextUtils
.
setAdminContext
(
onlineUserDto
);
}
}
filterChain
.
doFilter
(
servletRequest
,
servletResponse
);
}
}
cas-server/src/main/java/com/zq/cas/config/TokenProvider.java
0 → 100644
View file @
28a94138
package
com
.
zq
.
cas
.
config
;
/*
* 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.config.redis.RedisUtils
;
import
com.zq.common.config.security.SecurityProperties
;
import
io.jsonwebtoken.Claims
;
import
io.jsonwebtoken.Jwts
;
import
io.jsonwebtoken.SignatureAlgorithm
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
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
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
final
RedisUtils
redisUtils
;
private
final
SecurityProperties
properties
;
public
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
(
properties
.
getBase64Secret
());
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
Claims
getClaims
(
String
token
)
{
return
Jwts
.
parser
()
.
setSigningKey
(
DatatypeConverter
.
parseBase64Binary
(
properties
.
getBase64Secret
()))
.
parseClaimsJws
(
token
)
.
getBody
();
}
public
Authentication
getAuthentication
(
String
token
)
{
Claims
claims
=
getClaims
(
token
);
// 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
(
properties
.
getOnlineKey
()
+
token
)
*
1000
;
Date
expireDate
=
DateUtil
.
offset
(
new
Date
(),
DateField
.
MILLISECOND
,
(
int
)
time
);
// 判断当前时间与过期时间的时间差
long
differ
=
expireDate
.
getTime
()
-
System
.
currentTimeMillis
();
// 如果在续期检查的范围内,则续期
if
(
differ
<=
properties
.
getDetect
())
{
long
renew
=
time
+
properties
.
getRenew
();
redisUtils
.
expire
(
properties
.
getOnlineKey
()
+
token
,
renew
,
TimeUnit
.
MILLISECONDS
);
}
}
public
String
getToken
(
HttpServletRequest
request
)
{
String
bearerToken
=
request
.
getHeader
(
properties
.
getHeader
());
if
(
StringUtils
.
isBlank
(
bearerToken
))
{
return
null
;
}
if
(
bearerToken
.
startsWith
(
properties
.
getTokenStartWith
()))
{
// 去掉令牌前缀
return
bearerToken
.
replace
(
properties
.
getTokenStartWith
(),
""
);
}
else
{
log
.
debug
(
"非法Token:{}"
,
bearerToken
);
}
return
null
;
}
}
cas-server/src/main/java/com/zq/cas/config/feign/FeignConfig.java
0 → 100644
View file @
28a94138
package
com
.
zq
.
cas
.
config
.
feign
;
import
com.zq.common.utils.HttpRequestUtils
;
import
feign.RequestInterceptor
;
import
feign.RequestTemplate
;
import
feign.codec.Encoder
;
import
org.springframework.beans.factory.ObjectFactory
;
import
org.springframework.boot.autoconfigure.http.HttpMessageConverters
;
import
org.springframework.cloud.openfeign.support.SpringEncoder
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
javax.servlet.http.HttpServletRequest
;
import
java.util.Arrays
;
import
java.util.Enumeration
;
import
java.util.List
;
/**
* @author wilmiam
* @since 2021-07-09 10:34
*/
@Configuration
public
class
FeignConfig
{
private
final
ObjectFactory
<
HttpMessageConverters
>
messageConverters
;
public
FeignConfig
(
ObjectFactory
<
HttpMessageConverters
>
messageConverters
)
{
this
.
messageConverters
=
messageConverters
;
}
/**
* 转发请求头
*/
private
static
final
List
<
String
>
FORWARD_HEADERS
=
Arrays
.
asList
(
"AUTHORIZATION"
,
"X-FORWARDED-FOR"
,
"X-FORWARDED-PROTO"
,
"X-FORWARDED-PORT"
,
"X-FORWARDED-HOST"
,
"FORWARDED"
,
"PROXY-CLIENT-IP"
,
"WL-PROXY-CLIENT-IP"
,
"HTTP_X_FORWARDED_FOR"
,
"HTTP_X_FORWARDED"
,
"HTTP_X_CLUSTER_CLIENT_IP"
,
"HTTP_CLIENT_IP"
,
"HTTP_FORWARDED_FOR"
,
"HTTP_FORWARDED"
,
"HTTP_VIA"
,
"REMOTE_ADDR"
,
"X-REAL-IP"
,
"HOST"
);
/**
* 解决fein远程调用丢失请求头
*
* @return
*/
@Bean
public
RequestInterceptor
requestInterceptor
()
{
return
new
RequestInterceptor
()
{
@Override
public
void
apply
(
RequestTemplate
template
)
{
HttpServletRequest
request
=
HttpRequestUtils
.
getRequest
();
if
(
request
==
null
)
{
return
;
}
Enumeration
<
String
>
headerNames
=
request
.
getHeaderNames
();
if
(
headerNames
!=
null
)
{
while
(
headerNames
.
hasMoreElements
())
{
String
name
=
headerNames
.
nextElement
();
// 不要设置content-length
if
(
"content-length"
.
equals
(
name
))
{
continue
;
}
if
(
FORWARD_HEADERS
.
contains
(
name
.
toUpperCase
()))
{
String
values
=
request
.
getHeader
(
name
);
template
.
header
(
name
,
values
);
}
}
}
}
};
}
@Bean
public
Encoder
feignEncoder
()
{
return
new
FeignSpringFormEncoder
(
new
SpringEncoder
(
messageConverters
));
}
}
cas-server/src/main/java/com/zq/cas/config/feign/FeignSpringFormEncoder.java
0 → 100644
View file @
28a94138
package
com
.
zq
.
cas
.
config
.
feign
;
import
feign.RequestTemplate
;
import
feign.codec.EncodeException
;
import
feign.codec.Encoder
;
import
feign.form.ContentType
;
import
feign.form.FormEncoder
;
import
feign.form.MultipartFormContentProcessor
;
import
feign.form.spring.SpringManyMultipartFilesWriter
;
import
feign.form.spring.SpringSingleMultipartFileWriter
;
import
org.springframework.web.multipart.MultipartFile
;
import
java.lang.reflect.Type
;
import
java.util.Collections
;
import
java.util.Map
;
/**
* feign 多文件上传配置
*
* @author Lander
*/
public
class
FeignSpringFormEncoder
extends
FormEncoder
{
public
FeignSpringFormEncoder
()
{
this
(
new
Default
());
}
public
FeignSpringFormEncoder
(
Encoder
delegate
)
{
super
(
delegate
);
MultipartFormContentProcessor
processor
=
(
MultipartFormContentProcessor
)
this
.
getContentProcessor
(
ContentType
.
MULTIPART
);
processor
.
addFirstWriter
(
new
SpringSingleMultipartFileWriter
());
processor
.
addFirstWriter
(
new
SpringManyMultipartFilesWriter
());
}
@Override
public
void
encode
(
Object
object
,
Type
bodyType
,
RequestTemplate
template
)
throws
EncodeException
{
if
(
bodyType
!=
null
&&
bodyType
.
equals
(
MultipartFile
[].
class
))
{
MultipartFile
[]
file
=
(
MultipartFile
[])
object
;
if
(
file
!=
null
)
{
Map
<
String
,
Object
>
data
=
Collections
.
singletonMap
(
file
.
length
==
0
?
""
:
file
[
0
].
getName
(),
object
);
super
.
encode
(
data
,
MAP_STRING_WILDCARD
,
template
);
return
;
}
}
else
if
(
bodyType
!=
null
&&
bodyType
.
equals
(
MultipartFile
.
class
))
{
MultipartFile
file
=
(
MultipartFile
)
object
;
if
(
file
!=
null
)
{
Map
<
String
,
Object
>
data
=
Collections
.
singletonMap
(
file
.
getName
(),
object
);
super
.
encode
(
data
,
MAP_STRING_WILDCARD
,
template
);
return
;
}
}
super
.
encode
(
object
,
bodyType
,
template
);
}
}
cas-server/src/main/java/com/zq/cas/controller/AuthorizationController.java
0 → 100644
View file @
28a94138
/*
* 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
.
cas
.
controller
;
import
cn.hutool.core.util.URLUtil
;
import
com.alibaba.fastjson.JSON
;
import
com.alibaba.fastjson.JSONObject
;
import
com.zq.cas.config.JumpConfig
;
import
com.zq.cas.config.SpringCasAutoconfig
;
import
com.zq.cas.service.FyUserManager
;
import
com.zq.common.annotation.AnonymousAccess
;
import
com.zq.common.annotation.rest.AnonymousPostMapping
;
import
com.zq.common.config.security.SecurityProperties
;
import
com.zq.common.vo.ResultVo
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestParam
;
import
org.springframework.web.bind.annotation.ResponseBody
;
import
org.springframework.web.bind.annotation.RestController
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
javax.servlet.http.HttpSession
;
import
java.io.IOException
;
import
java.security.Principal
;
/**
* @author Zheng Jie
* @date 2018-11-23
* 授权、根据token获取用户详细信息
*/
@Slf4j
@RestController
@RequestMapping
(
"/oauth"
)
@RequiredArgsConstructor
@Api
(
tags
=
"系统:系统授权接口"
)
public
class
AuthorizationController
{
private
final
JumpConfig
jumpConfig
;
private
final
SpringCasAutoconfig
casAutoconfig
;
private
final
SecurityProperties
properties
;
private
final
FyUserManager
fyUserManager
;
@RequestMapping
(
"/login"
)
@AnonymousAccess
public
void
casLogin
(
HttpServletRequest
request
,
HttpServletResponse
response
)
throws
IOException
{
Principal
principal
=
request
.
getUserPrincipal
();
String
username
=
principal
.
getName
();
if
(!
username
.
contains
(
"@"
))
{
username
=
username
+
"@gxfy.com"
;
}
log
.
info
(
"登录用户:"
+
username
);
ResultVo
resultVo
=
fyUserManager
.
casLogin
(
username
);
if
(
resultVo
.
isSuccess
())
{
}
JSONObject
object
=
JSON
.
parseObject
(
JSON
.
toJSONString
(
resultVo
.
getData
()));
String
sessionId
=
request
.
getRequestedSessionId
();
String
systemTag
=
request
.
getParameter
(
"systemTag"
);
String
domain
=
jumpConfig
.
getDomain
(
systemTag
);
response
.
sendRedirect
(
domain
+
"/#/verifyLogin?"
+
properties
.
getHeader
()
+
"="
+
object
.
getString
(
"token"
)
+
"&JSESSIONID="
+
sessionId
);
}
@ApiOperation
(
"退出登录"
)
@RequestMapping
(
value
=
"/logout"
)
@ResponseBody
@AnonymousAccess
public
ResultVo
<
String
>
logout
(
HttpSession
session
,
HttpServletRequest
request
,
HttpServletResponse
response
)
{
fyUserManager
.
logout
(
request
.
getHeader
(
properties
.
getHeader
()));
String
systemTag
=
request
.
getParameter
(
"systemTag"
);
// String ticket = request.getParameter("ticket");
request
.
removeAttribute
(
"ticket"
);
// if (StrUtil.isNotBlank(ticket)) {
// request.getParameter("ticket").trim();
// }
session
.
invalidate
();
request
.
getSession
().
invalidate
();
String
service
=
URLUtil
.
encode
(
casAutoconfig
.
getCasServerLoginUrl
()
+
"?systemTag="
+
systemTag
);
String
logoutUrl
=
casAutoconfig
.
getCasServerUrlPrefix
()
+
"/logout?service="
+
service
;
return
ResultVo
.
success
(
logoutUrl
);
}
//用于旧系统退出单点登录
@ApiOperation
(
"旧系统退出单点登录"
)
@RequestMapping
(
value
=
"/cas/logout"
)
@AnonymousAccess
public
void
casLogout
(
HttpSession
session
,
HttpServletRequest
request
,
HttpServletResponse
response
)
throws
IOException
{
fyUserManager
.
logout
(
request
.
getHeader
(
properties
.
getHeader
()));
request
.
removeAttribute
(
"ticket"
);
String
service
=
request
.
getParameter
(
"service"
);
session
.
invalidate
();
request
.
getSession
().
invalidate
();
String
logoutUrl
=
casAutoconfig
.
getCasServerUrlPrefix
()
+
"/logout?service="
+
service
;
response
.
sendRedirect
(
logoutUrl
);
}
@ApiOperation
(
"销毁token"
)
@RequestMapping
(
value
=
"/removeToken"
)
@ResponseBody
@AnonymousAccess
public
ResultVo
removeToken
(
HttpServletRequest
request
)
{
fyUserManager
.
logout
(
request
.
getHeader
(
properties
.
getHeader
()));
return
ResultVo
.
success
();
}
@ApiOperation
(
"获取token"
)
@AnonymousPostMapping
(
"/getToken"
)
public
ResultVo
removeToken
(
@RequestParam
(
"username"
)
String
username
)
{
if
(!
username
.
contains
(
"@"
))
{
username
=
username
+
"@gxfy.com"
;
}
ResultVo
resultVo
=
fyUserManager
.
casLogin
(
username
);
JSONObject
object
=
JSON
.
parseObject
(
JSON
.
toJSONString
(
resultVo
.
getData
()));
return
ResultVo
.
success
(
object
.
getString
(
"token"
));
}
}
cas-server/src/main/java/com/zq/cas/feignclient/AdminFeignClient.java
0 → 100644
View file @
28a94138
package
com
.
zq
.
cas
.
feignclient
;
import
com.zq.cas.config.feign.FeignConfig
;
import
com.zq.common.vo.ResultVo
;
import
org.springframework.cloud.openfeign.FeignClient
;
import
org.springframework.web.bind.annotation.DeleteMapping
;
import
org.springframework.web.bind.annotation.PostMapping
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
java.util.Map
;
/**
* @author wilmiam
* @since 2022/10/11 17:19
*/
@FeignClient
(
name
=
"ADMIN-SERVER"
,
path
=
"/admin"
,
configuration
=
FeignConfig
.
class
)
public
interface
AdminFeignClient
{
@PostMapping
(
value
=
"/auth/casLogin"
)
ResultVo
casLogin
(
@RequestBody
Map
<
String
,
Object
>
params
);
@DeleteMapping
(
value
=
"/auth/logout"
)
ResultVo
logout
();
}
cas-server/src/main/java/com/zq/cas/service/FyUserManager.java
0 → 100644
View file @
28a94138
package
com
.
zq
.
cas
.
service
;
import
cn.hutool.core.util.StrUtil
;
import
com.zq.cas.feignclient.AdminFeignClient
;
import
com.zq.common.utils.AssertUtils
;
import
com.zq.common.vo.ResultVo
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Component
;
import
java.util.HashMap
;
import
java.util.Map
;
@Slf4j
@Component
public
class
FyUserManager
{
@Autowired
private
AdminFeignClient
feignClient
;
/**
* fy用户单点登陆
*
* @param username
* @return
*/
public
ResultVo
casLogin
(
String
username
)
{
Map
<
String
,
Object
>
params
=
new
HashMap
<>();
params
.
put
(
"username"
,
username
);
ResultVo
resultVo
=
feignClient
.
casLogin
(
params
);
AssertUtils
.
isTrue
(
resultVo
.
isSuccess
(),
resultVo
.
getErrMsg
());
return
resultVo
;
}
/**
* fy用户登出
*
* @param token
*/
public
void
logout
(
String
token
)
{
if
(
StrUtil
.
isNotBlank
(
token
)
&&
!
"undefined"
.
equals
(
token
))
{
feignClient
.
logout
();
}
}
}
cas-server/src/main/resources/application-dev.yml
0 → 100644
View file @
28a94138
# 系统跳转配置
jump
:
domain-map
:
default
:
http://172.20.10.5:8026
oa-document-zat
:
http://192.168.0.29:8026/
default-ld
:
http://192.168.0.162:8026
spring
:
#单点登陆配置
cas
:
sign-out-filters
:
/oauth/logout
auth-filters
:
/oauth/login
validate-filters
:
/*
request-wrapper-filters
:
/*
assertion-filters
:
/*
redirect-after-validation
:
true
use-session
:
true
cas-server-login-url
:
http://175.178.197.14:8081/cas/login/login?service=http://172.20.10.5:9888/oauth/login
cas-server-url-prefix
:
http://175.178.197.14:8081/cas
server-name
:
172.20.10.5:9888
cas-server/src/main/resources/application-product.yml
0 → 100644
View file @
28a94138
# 系统跳转配置
jump
:
domain-map
:
default
:
http://147.1.5.135:8090
invoice
:
http://147.1.4.67:8060
archive
:
http://147.1.5.135:8090
spring
:
#单点登陆配置
cas
:
sign-out-filters
:
/oauth/logout
auth-filters
:
/oauth/login
validate-filters
:
/*
request-wrapper-filters
:
/*
assertion-filters
:
/*
redirect-after-validation
:
true
use-session
:
true
cas-server-login-url
:
http://147.1.6.16:8080/cas/login?service=http://147.1.5.135/oauth/login
cas-server-url-prefix
:
http://147.1.6.16:8080/cas
server-name
:
http://147.1.5.135
cas-server/src/main/resources/application-test.yml
0 → 100644
View file @
28a94138
# 系统跳转配置
jump
:
domain-map
:
default
:
http://147.1.4.67:8090
invoice
:
http://147.1.4.67:8060
archive
:
http://147.1.4.67:8090
spring
:
#单点登陆配置
cas
:
sign-out-filters
:
/oauth/logout
auth-filters
:
/oauth/login
validate-filters
:
/*
request-wrapper-filters
:
/*
assertion-filters
:
/*
redirect-after-validation
:
true
use-session
:
true
cas-server-login-url
:
http://172.18.3.137:8080/cas/login?service=http://147.1.4.67/oauth/login
cas-server-url-prefix
:
http://172.18.3.137:8080/cas
server-name
:
http://147.1.4.67
cas-server/src/main/resources/application.yml
0 → 100644
View file @
28a94138
server
:
port
:
${auth.port}
#配置数据源
spring
:
application
:
name
:
${auth.name}
redis
:
#数据库索引
host
:
${redis.url}
port
:
${redis.port}
password
:
${redis.password}
database
:
0
#连接超时时间
timeout
:
5000
#登录配置
login
:
single
:
true
cas-server/src/main/resources/bootstrap.yml
0 → 100644
View file @
28a94138
spring
:
profiles
:
active
:
@
profiles.active@
cloud
:
config
:
name
:
config
profile
:
${spring.profiles.active}
discovery
:
enabled
:
true
service-id
:
CONFIG-SERVER
eureka
:
instance
:
prefer-ip-address
:
true
lease-renewal-interval-in-seconds
:
2
#每间隔1s,向服务端发送一次心跳,证明自己依然"存活"
lease-expiration-duration-in-seconds
:
6
#告诉服务端,如果我2s之内没有给你发心跳,就代表我"死"了,将我踢出掉。
instance-id
:
${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
client
:
service-url
:
defaultZone
:
@
eureka.server.url@
cas-server/src/main/resources/logback-spring.xml
0 → 100644
View file @
28a94138
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--<include resource="org/springframework/boot/logging/logback/base.xml"/>-->
<include
resource=
"org/springframework/boot/logging/logback/defaults.xml"
/>
<include
resource=
"org/springframework/boot/logging/logback/console-appender.xml"
/>
<!-- 项目名称也是主要日志文件名 -->
<property
name=
"PROJECT_NAME"
value=
"oauth"
/>
<!-- 日志目录 -->
<property
name=
"LOG_PATH"
value=
"/data/logs/${LOG_PATH:-${PROJECT_NAME}}"
/>
<!-- 日志格式 -->
<property
name=
"LOG_PATTERN"
value=
"%d{yyyy-MM-dd HH:mm:ss.SSS} %5p ${PID:-} [%15.15t] %-40.40logger{39} : %m%n"
/>
<!-- the name of the application's logging context -->
<!-- by default each JMXConfigurator instance will be registered under the same name in the same JVM -->
<!-- we need to set the contextName for different apps, so that the jmxconfigurator won't collide -->
<contextName>
${PROJECT_NAME}
</contextName>
<jmxConfigurator/>
<!--主要日志配置 开始-->
<appender
name=
"SIZED_ROLLING_FILE"
class=
"ch.qos.logback.core.rolling.RollingFileAppender"
>
<encoder>
<pattern>
${LOG_PATTERN}
</pattern>
<charset>
UTF-8
</charset>
</encoder>
<file>
${LOG_PATH}/${LOG_FILE}.log
</file>
<rollingPolicy
class=
"ch.qos.logback.core.rolling.TimeBasedRollingPolicy"
>
<fileNamePattern>
${LOG_PATH}/${LOG_FILE}/${LOG_FILE}.%d{yyyy-MM-dd}.%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class=
"ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"
>
<maxFileSize>
50MB
</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!-- 日志文档保留天数 -->
<maxHistory>
15
</maxHistory>
</rollingPolicy>
</appender>
<!-- 异步输出 -->
<appender
name=
"MAIN-LOGGER-APPENDER"
class=
"ch.qos.logback.classic.AsyncAppender"
>
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>
0
</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>
512
</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref
ref=
"SIZED_ROLLING_FILE"
/>
</appender>
<!--主要日志配置 结束-->
<!--DEBUG日志配置 开始-->
<appender
name=
"DEBUG_FILE"
class=
"ch.qos.logback.core.rolling.RollingFileAppender"
>
<encoder>
<pattern>
${LOG_PATTERN}
</pattern>
<charset>
UTF-8
</charset>
</encoder>
<file>
${LOG_PATH}/debug.log
</file>
<rollingPolicy
class=
"ch.qos.logback.core.rolling.TimeBasedRollingPolicy"
>
<fileNamePattern>
${LOG_PATH}/debug/debug.%d{yyyy-MM-dd}.%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class=
"ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"
>
<maxFileSize>
50MB
</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!-- 日志文档保留天数 -->
<maxHistory>
15
</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录ERROR级别的 -->
<filter
class=
"ch.qos.logback.classic.filter.LevelFilter"
>
<level>
DEBUG
</level>
<onMatch>
ACCEPT
</onMatch>
<onMismatch>
DENY
</onMismatch>
</filter>
</appender>
<!-- 异步输出 -->
<appender
name=
"DEBUG-APPENDER"
class=
"ch.qos.logback.classic.AsyncAppender"
>
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>
0
</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>
512
</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref
ref=
"DEBUG_FILE"
/>
</appender>
<!--DEBUG日志配置 结束-->
<!--INFO日志配置 开始-->
<appender
name=
"INFO_FILE"
class=
"ch.qos.logback.core.rolling.RollingFileAppender"
>
<encoder>
<pattern>
${LOG_PATTERN}
</pattern>
<charset>
UTF-8
</charset>
</encoder>
<file>
${LOG_PATH}/info.log
</file>
<rollingPolicy
class=
"ch.qos.logback.core.rolling.TimeBasedRollingPolicy"
>
<fileNamePattern>
${LOG_PATH}/info/info.%d{yyyy-MM-dd}.%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class=
"ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"
>
<maxFileSize>
50MB
</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!-- 日志文档保留天数 -->
<maxHistory>
15
</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录ERROR级别的 -->
<filter
class=
"ch.qos.logback.classic.filter.LevelFilter"
>
<level>
INFO
</level>
<onMatch>
ACCEPT
</onMatch>
<onMismatch>
DENY
</onMismatch>
</filter>
</appender>
<!-- 异步输出 -->
<appender
name=
"INFO-APPENDER"
class=
"ch.qos.logback.classic.AsyncAppender"
>
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>
0
</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>
512
</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref
ref=
"INFO_FILE"
/>
</appender>
<!--INFO日志配置 结束-->
<!--WARN日志配置 开始-->
<appender
name=
"WARN_FILE"
class=
"ch.qos.logback.core.rolling.RollingFileAppender"
>
<encoder>
<pattern>
${LOG_PATTERN}
</pattern>
<charset>
UTF-8
</charset>
</encoder>
<file>
${LOG_PATH}/warn.log
</file>
<rollingPolicy
class=
"ch.qos.logback.core.rolling.TimeBasedRollingPolicy"
>
<fileNamePattern>
${LOG_PATH}/warn/warn.%d{yyyy-MM-dd}.%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class=
"ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"
>
<maxFileSize>
50MB
</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!-- 日志文档保留天数 -->
<maxHistory>
15
</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录ERROR级别的 -->
<filter
class=
"ch.qos.logback.classic.filter.LevelFilter"
>
<level>
WARN
</level>
<onMatch>
ACCEPT
</onMatch>
<onMismatch>
DENY
</onMismatch>
</filter>
</appender>
<!-- 异步输出 -->
<appender
name=
"WARN-APPENDER"
class=
"ch.qos.logback.classic.AsyncAppender"
>
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>
0
</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>
512
</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref
ref=
"WARN_FILE"
/>
</appender>
<!--WARN日志配置 结束-->
<!--ERROR错误日志配置 开始-->
<appender
name=
"ERROR_FILE"
class=
"ch.qos.logback.core.rolling.RollingFileAppender"
>
<!-- 正在记录的日志文件的路径及文件名 -->
<file>
${LOG_PATH}/error.log
</file>
<!--日志文件输出格式-->
<encoder>
<pattern>
${LOG_PATTERN}
</pattern>
<charset>
UTF-8
</charset>
<!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy
class=
"ch.qos.logback.core.rolling.TimeBasedRollingPolicy"
>
<fileNamePattern>
${LOG_PATH}/error/error.%d{yyyy-MM-dd}.%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class=
"ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"
>
<maxFileSize>
50MB
</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>
15
</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录ERROR级别的 -->
<filter
class=
"ch.qos.logback.classic.filter.LevelFilter"
>
<level>
ERROR
</level>
<onMatch>
ACCEPT
</onMatch>
<onMismatch>
DENY
</onMismatch>
</filter>
</appender>
<!-- 异步输出 -->
<appender
name=
"ERROR-APPENDER"
class=
"ch.qos.logback.classic.AsyncAppender"
>
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>
0
</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>
512
</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref
ref=
"ERROR_FILE"
/>
</appender>
<!--ERROR错误日志配置 结束-->
<root
level=
"INFO"
>
<!-- 控制台日志输出 -->
<appender-ref
ref=
"CONSOLE"
/>
<!-- 全部日志不区分级别 -->
<appender-ref
ref=
"MAIN-LOGGER-APPENDER"
/>
<!-- 区分日志级别 -->
<appender-ref
ref=
"DEBUG-APPENDER"
/>
<appender-ref
ref=
"INFO-APPENDER"
/>
<appender-ref
ref=
"WARN-APPENDER"
/>
<appender-ref
ref=
"ERROR-APPENDER"
/>
</root>
<logger
name=
"com.zq.cas"
level=
"DEBUG"
/>
<!--开发环境:打印控制台-->
<springProfile
name=
"!dev"
>
<logger
name=
"com.zq.cas.feignclient"
level=
"INFO"
/>
</springProfile>
</configuration>
oauth-server/pom.xml
0 → 100644
View file @
28a94138
<?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"
>
<parent>
<artifactId>
cloud-backend
</artifactId>
<groupId>
com.zq
</groupId>
<version>
1.0.0
</version>
</parent>
<modelVersion>
4.0.0
</modelVersion>
<artifactId>
oauth-server
</artifactId>
<properties>
<maven.compiler.source>
8
</maven.compiler.source>
<maven.compiler.target>
8
</maven.compiler.target>
</properties>
</project>
pom.xml
View file @
28a94138
...
...
@@ -12,7 +12,7 @@
<parent>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-parent
</artifactId>
<version>
2.
1.6.RELEASE
</version>
<version>
2.
5.8
</version>
</parent>
<properties>
...
...
@@ -42,6 +42,8 @@
<module>
user-server
</module>
<module>
admin-server
</module>
<module>
logging-server
</module>
<module>
oauth-server
</module>
<module>
cas-server
</module>
</modules>
<dependencies>
...
...
@@ -73,7 +75,7 @@
<dependency>
<groupId>
org.springframework.cloud
</groupId>
<artifactId>
spring-cloud-dependencies
</artifactId>
<version>
Greenwich.SR2
</version>
<version>
2020.0.6
</version>
<type>
pom
</type>
<scope>
import
</scope>
</dependency>
...
...
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