Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
spring-microservice-exam
Project
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
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
汪想
spring-microservice-exam
Commits
e9194a2d
Commit
e9194a2d
authored
Jul 06, 2019
by
tangyi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
登录支持微信小程序
parent
85e38885
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
82 changed files
with
1798 additions
and
288 deletions
+1798
-288
CHANGELOG.md
CHANGELOG.md
+9
-1
CommonConstant.java
...om/github/tangyi/common/core/constant/CommonConstant.java
+5
-0
SysConfigDto.java
.../java/com/github/tangyi/common/core/dto/SysConfigDto.java
+7
-9
SysProperties.java
...m/github/tangyi/common/core/properties/SysProperties.java
+22
-1
SysUtil.java
...ain/java/com/github/tangyi/common/core/utils/SysUtil.java
+26
-0
UserVo.java
...rc/main/java/com/github/tangyi/common/core/vo/UserVo.java
+40
-0
CustomFeignConfig.java
.../github/tangyi/common/feign/config/CustomFeignConfig.java
+4
-1
pom.xml
common/common-security/pom.xml
+7
-0
CustomResourceServerConfig.java
...yi/common/security/config/CustomResourceServerConfig.java
+10
-1
WxLoginConfig.java
...m/github/tangyi/common/security/config/WxLoginConfig.java
+53
-0
SecurityConstant.java
...hub/tangyi/common/security/constant/SecurityConstant.java
+5
-0
CustomUserDetailsService.java
...tangyi/common/security/core/CustomUserDetailsService.java
+15
-2
MobileSecurityConfigurer.java
...ngyi/common/security/mobile/MobileSecurityConfigurer.java
+1
-1
GsonHelper.java
...a/com/github/tangyi/common/security/utils/GsonHelper.java
+79
-0
WxAuthenticationFilter.java
...hub/tangyi/common/security/wx/WxAuthenticationFilter.java
+122
-0
WxAuthenticationProvider.java
...b/tangyi/common/security/wx/WxAuthenticationProvider.java
+46
-0
WxAuthenticationToken.java
...thub/tangyi/common/security/wx/WxAuthenticationToken.java
+65
-0
WxLoginSuccessHandler.java
...thub/tangyi/common/security/wx/WxLoginSuccessHandler.java
+81
-0
WxSecurityConfigurer.java
...ithub/tangyi/common/security/wx/WxSecurityConfigurer.java
+46
-0
WxUser.java
...ain/java/com/github/tangyi/common/security/wx/WxUser.java
+58
-0
auth-service.yml
config-service/src/main/resources/config/auth-service.yml
+10
-0
gateway-service.yml
config-service/src/main/resources/config/gateway-service.yml
+9
-8
user-service.yml
config-service/src/main/resources/config/user-service.yml
+1
-0
在线考试.pdb
docs/产品设计/数据库设计/在线考试.pdb
+0
-0
在线考试.pdm
docs/产品设计/数据库设计/在线考试.pdm
+0
-0
pom.xml
gateway-service/pom.xml
+0
-11
CorsConfig.java
...ain/java/com/github/tangyi/gateway/config/CorsConfig.java
+52
-0
GatewayConstant.java
.../com/github/tangyi/gateway/constants/GatewayConstant.java
+5
-0
DecodePasswordFilter.java
...m/github/tangyi/gateway/filters/DecodePasswordFilter.java
+24
-53
TokenRequestGlobalFilter.java
...thub/tangyi/gateway/filters/TokenRequestGlobalFilter.java
+70
-46
TokenResponseGlobalFilter.java
...hub/tangyi/gateway/filters/TokenResponseGlobalFilter.java
+1
-6
AccessToken.java
...ain/java/com/github/tangyi/gateway/model/AccessToken.java
+0
-5
AccessTokenJacksonSerializer.java
...ngyi/gateway/serializer/AccessTokenJacksonSerializer.java
+2
-1
pom.xml
pom.xml
+26
-0
README.md
service-api-impl/auth-service/README.md
+198
-0
pom.xml
service-api-impl/auth-service/pom.xml
+3
-8
SwaggerConfig.java
...ain/java/com/github/tangyi/auth/config/SwaggerConfig.java
+7
-5
WxConfig.java
...src/main/java/com/github/tangyi/auth/config/WxConfig.java
+42
-0
OauthClientDetailsController.java
.../tangyi/auth/controller/OauthClientDetailsController.java
+2
-2
WxProperties.java
.../java/com/github/tangyi/auth/properties/WxProperties.java
+23
-0
CustomTokenConverter.java
...com/github/tangyi/auth/security/CustomTokenConverter.java
+2
-0
CustomUserDetailsAuthenticationProvider.java
...uth/security/CustomUserDetailsAuthenticationProvider.java
+1
-1
CustomUserDetailsServiceImpl.java
...ub/tangyi/auth/security/CustomUserDetailsServiceImpl.java
+62
-3
WxSessionService.java
...java/com/github/tangyi/auth/service/WxSessionService.java
+62
-0
pom.xml
service-api-impl/exam-service/pom.xml
+0
-11
SwaggerConfig.java
...ain/java/com/github/tangyi/exam/config/SwaggerConfig.java
+7
-5
AnswerController.java
...a/com/github/tangyi/exam/controller/AnswerController.java
+1
-1
CourseController.java
...a/com/github/tangyi/exam/controller/CourseController.java
+1
-1
ExamRecordController.java
...m/github/tangyi/exam/controller/ExamRecordController.java
+1
-1
ExaminationController.java
.../github/tangyi/exam/controller/ExaminationController.java
+1
-1
KnowledgeController.java
...om/github/tangyi/exam/controller/KnowledgeController.java
+1
-1
SubjectController.java
.../com/github/tangyi/exam/controller/SubjectController.java
+1
-1
CustomGlobalExceptionHandler.java
...ithub/tangyi/exam/error/CustomGlobalExceptionHandler.java
+5
-1
pom.xml
service-api-impl/msc-service/pom.xml
+0
-11
SwaggerConfig.java
...main/java/com/github/tangyi/msc/config/SwaggerConfig.java
+7
-5
pom.xml
service-api-impl/user-service/pom.xml
+0
-11
SwaggerConfig.java
...ain/java/com/github/tangyi/user/config/SwaggerConfig.java
+7
-5
AttachmentController.java
...m/github/tangyi/user/controller/AttachmentController.java
+4
-4
LogController.java
...java/com/github/tangyi/user/controller/LogController.java
+1
-1
MenuController.java
...ava/com/github/tangyi/user/controller/MenuController.java
+5
-5
MobileController.java
...a/com/github/tangyi/user/controller/MobileController.java
+4
-0
RoleController.java
...ava/com/github/tangyi/user/controller/RoleController.java
+2
-2
RouteController.java
...va/com/github/tangyi/user/controller/RouteController.java
+1
-1
SysConfigController.java
...om/github/tangyi/user/controller/SysConfigController.java
+8
-4
TenantController.java
...a/com/github/tangyi/user/controller/TenantController.java
+1
-1
UserController.java
...ava/com/github/tangyi/user/controller/UserController.java
+10
-5
ValidateCodeController.java
...github/tangyi/user/controller/ValidateCodeController.java
+1
-2
CustomGlobalExceptionHandler.java
...ithub/tangyi/user/error/CustomGlobalExceptionHandler.java
+5
-1
AttachmentService.java
...ava/com/github/tangyi/user/service/AttachmentService.java
+3
-3
MobileService.java
...in/java/com/github/tangyi/user/service/MobileService.java
+5
-8
UserService.java
...main/java/com/github/tangyi/user/service/UserService.java
+47
-12
UserUtils.java
...src/main/java/com/github/tangyi/user/utils/UserUtils.java
+3
-3
UserAuthsMapper.xml
...ser-service/src/main/resources/mapper/UserAuthsMapper.xml
+5
-5
UserMapper.xml
...mpl/user-service/src/main/resources/mapper/UserMapper.xml
+59
-8
WxSession.java
...ain/java/com/github/tangyi/auth/api/module/WxSession.java
+23
-0
AttachmentConstant.java
...m/github/tangyi/user/api/constant/AttachmentConstant.java
+23
-0
UserDto.java
...src/main/java/com/github/tangyi/user/api/dto/UserDto.java
+95
-2
UserInfoDto.java
...main/java/com/github/tangyi/user/api/dto/UserInfoDto.java
+40
-0
UserServiceClient.java
...a/com/github/tangyi/user/api/feign/UserServiceClient.java
+37
-0
UserServiceClientFallbackImpl.java
...ser/api/feign/fallback/UserServiceClientFallbackImpl.java
+39
-0
Attachment.java
...in/java/com/github/tangyi/user/api/module/Attachment.java
+2
-1
User.java
...src/main/java/com/github/tangyi/user/api/module/User.java
+40
-0
No files found.
CHANGELOG.md
View file @
e9194a2d
Version v3.0.0 (2019-7-6)
--------------------------
新功能:
*
支持微信小程序登录
Version v3.0.0 (2019-7-4)
--------------------------
...
...
@@ -19,7 +27,7 @@ Version v3.0.0 (2019-6-23)
新功能:
#
增加短信验证码登录
*
增加短信验证码登录
*
增加消息中心服务
改进:
...
...
common/common-core/src/main/java/com/github/tangyi/common/core/constant/CommonConstant.java
View file @
e9194a2d
...
...
@@ -149,6 +149,11 @@ public class CommonConstant {
public
static
final
String
GRANT_TYPE_MOBILE
=
"mobile"
;
/**
* 微信类型
*/
public
static
final
String
GRANT_TYPE_WX
=
"wx"
;
/**
* 租户编号请求头
*/
public
static
final
String
TENANT_CODE_HEADER
=
"Tenant-Code"
;
...
...
service-api-impl/user-service/src/main/java/com/github/tangyi/user/config/SysConfig
.java
→
common/common-core/src/main/java/com/github/tangyi/common/core/dto/SysConfigDto
.java
View file @
e9194a2d
package
com
.
github
.
tangyi
.
user
.
config
;
package
com
.
github
.
tangyi
.
common
.
core
.
dto
;
import
lombok.Data
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
org.springframework.stereotype.Component
;
import
java.io.Serializable
;
/**
* 附件配置
*
* @author tangyi
* @date 2019
-02-24 20:06
* @date 2019
/07/05 15:05
*/
@Data
@Component
@ConfigurationProperties
(
prefix
=
"sys"
)
public
class
SysConfig
{
public
class
SysConfigDto
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* fastDfs服务器的HTTP地址
...
...
service-api-impl/auth-service/src/main/java/com/github/tangyi/auth
/properties/SysProperties.java
→
common/common-core/src/main/java/com/github/tangyi/common/core
/properties/SysProperties.java
View file @
e9194a2d
package
com
.
github
.
tangyi
.
auth
.
properties
;
package
com
.
github
.
tangyi
.
common
.
core
.
properties
;
import
com.fasterxml.jackson.annotation.JsonIgnore
;
import
lombok.Data
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
org.springframework.context.annotation.Configuration
;
...
...
@@ -14,7 +15,27 @@ import org.springframework.context.annotation.Configuration;
public
class
SysProperties
{
/**
* fastDfs服务器的HTTP地址
*/
private
String
fdfsHttpHost
;
/**
* 上传地址
*/
private
String
uploadUrl
;
/**
* 默认头像
*/
private
String
defaultAvatar
;
/**
* 管理员账号
*/
private
String
adminUser
;
/**
* 密码加密解密的key
*/
private
String
key
;
}
common/common-core/src/main/java/com/github/tangyi/common/core/utils/SysUtil.java
View file @
e9194a2d
...
...
@@ -4,6 +4,7 @@ import com.github.tangyi.common.security.constant.SecurityConstant;
import
com.github.tangyi.common.security.tenant.TenantContextHolder
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang.StringUtils
;
import
org.bouncycastle.util.encoders.Base64
;
import
org.springframework.security.core.context.SecurityContextHolder
;
import
org.springframework.security.core.userdetails.UserDetails
;
import
org.springframework.security.oauth2.common.OAuth2AccessToken
;
...
...
@@ -13,7 +14,11 @@ import org.springframework.security.web.authentication.WebAuthenticationDetails;
import
org.springframework.web.context.request.RequestContextHolder
;
import
org.springframework.web.context.request.ServletRequestAttributes
;
import
javax.crypto.Cipher
;
import
javax.crypto.spec.IvParameterSpec
;
import
javax.crypto.spec.SecretKeySpec
;
import
javax.servlet.http.HttpServletRequest
;
import
java.nio.charset.StandardCharsets
;
import
java.security.Principal
;
/**
...
...
@@ -25,6 +30,10 @@ import java.security.Principal;
@Slf4j
public
class
SysUtil
{
private
static
final
String
KEY_ALGORITHM
=
"AES"
;
private
static
final
String
DEFAULT_CIPHER_ALGORITHM
=
"AES/CBC/NOPadding"
;
/**
* 获取当前登录的用户名
*
...
...
@@ -93,4 +102,21 @@ public class SysUtil {
}
return
tenantCode
;
}
/**
* des解密
*
* @param data data
* @param pass pass
* @return String
* @author tangyi
* @date 2019/03/18 11:39
*/
public
static
String
decryptAES
(
String
data
,
String
pass
)
throws
Exception
{
Cipher
cipher
=
Cipher
.
getInstance
(
DEFAULT_CIPHER_ALGORITHM
);
cipher
.
init
(
Cipher
.
DECRYPT_MODE
,
new
SecretKeySpec
(
pass
.
getBytes
(),
KEY_ALGORITHM
),
new
IvParameterSpec
(
pass
.
getBytes
()));
byte
[]
result
=
cipher
.
doFinal
(
Base64
.
decode
(
data
.
getBytes
(
StandardCharsets
.
UTF_8
)));
return
new
String
(
result
,
StandardCharsets
.
UTF_8
);
}
}
common/common-core/src/main/java/com/github/tangyi/common/core/vo/UserVo.java
View file @
e9194a2d
...
...
@@ -85,5 +85,45 @@ public class UserVo extends BaseEntity<UserVo> {
*/
private
Integer
status
;
/**
* 引导注册人
*/
private
String
parentUid
;
/**
* 乡/镇
*/
private
String
streetId
;
/**
* 县
*/
private
String
countyId
;
/**
* 城市
*/
private
String
cityId
;
/**
* 省份
*/
private
String
provinceId
;
/**
* 最近登录时间
*/
private
Date
loginTime
;
/**
* 用户归档时间
*/
private
Date
lockTime
;
/**
* 微信
*/
private
String
wechat
;
}
common/common-feign/src/main/java/com/github/tangyi/common/feign/config/CustomFeignConfig.java
View file @
e9194a2d
...
...
@@ -12,7 +12,7 @@ import java.util.LinkedHashMap;
import
java.util.Map
;
/**
* 服务间调用携带
authorization
请求头
* 服务间调用携带
Authorization、Tenant-Code
请求头
*
* @author tangyi
* @date 2019-03-15 14:14
...
...
@@ -22,11 +22,14 @@ public class CustomFeignConfig implements RequestInterceptor {
private
static
final
String
TOKEN_HEADER
=
"authorization"
;
private
static
final
String
TENANT_HEADER
=
"Tenant-Code"
;
@Override
public
void
apply
(
RequestTemplate
requestTemplate
)
{
HttpServletRequest
request
=
getHttpServletRequest
();
if
(
request
!=
null
)
{
requestTemplate
.
header
(
TOKEN_HEADER
,
getHeaders
(
request
).
get
(
TOKEN_HEADER
));
requestTemplate
.
header
(
TENANT_HEADER
,
getHeaders
(
request
).
get
(
TENANT_HEADER
));
}
}
...
...
common/common-security/pom.xml
View file @
e9194a2d
...
...
@@ -27,5 +27,12 @@
<groupId>
javax.servlet
</groupId>
<artifactId>
javax.servlet-api
</artifactId>
</dependency>
<!-- commons-io -->
<dependency>
<groupId>
commons-io
</groupId>
<artifactId>
commons-io
</artifactId>
<version>
${commons-io.version}
</version>
</dependency>
</dependencies>
</project>
common/common-security/src/main/java/com/github/tangyi/common/security/config/CustomResourceServerConfig.java
View file @
e9194a2d
...
...
@@ -2,6 +2,7 @@ package com.github.tangyi.common.security.config;
import
com.github.tangyi.common.security.mobile.MobileSecurityConfigurer
;
import
com.github.tangyi.common.security.properties.FilterIgnorePropertiesConfig
;
import
com.github.tangyi.common.security.wx.WxSecurityConfigurer
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.security.config.annotation.web.builders.HttpSecurity
;
...
...
@@ -32,10 +33,16 @@ public class CustomResourceServerConfig extends ResourceServerConfigurerAdapter
*/
private
final
MobileSecurityConfigurer
mobileSecurityConfigurer
;
/**
* 微信登录配置
*/
private
final
WxSecurityConfigurer
wxSecurityConfigurer
;
@Autowired
public
CustomResourceServerConfig
(
FilterIgnorePropertiesConfig
filterIgnorePropertiesConfig
,
MobileSecurityConfigurer
mobileSecurityConfigurer
)
{
public
CustomResourceServerConfig
(
FilterIgnorePropertiesConfig
filterIgnorePropertiesConfig
,
MobileSecurityConfigurer
mobileSecurityConfigurer
,
WxSecurityConfigurer
wxSecurityConfigurer
)
{
this
.
filterIgnorePropertiesConfig
=
filterIgnorePropertiesConfig
;
this
.
mobileSecurityConfigurer
=
mobileSecurityConfigurer
;
this
.
wxSecurityConfigurer
=
wxSecurityConfigurer
;
}
@Override
...
...
@@ -55,5 +62,7 @@ public class CustomResourceServerConfig extends ResourceServerConfigurerAdapter
.
and
().
exceptionHandling
().
accessDeniedHandler
(
new
OAuth2AccessDeniedHandler
());
// 手机号登录
http
.
apply
(
mobileSecurityConfigurer
);
// 微信登录
http
.
apply
(
wxSecurityConfigurer
);
}
}
common/common-security/src/main/java/com/github/tangyi/common/security/config/WxLoginConfig.java
0 → 100644
View file @
e9194a2d
package
com
.
github
.
tangyi
.
common
.
security
.
config
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.github.tangyi.common.security.core.CustomUserDetailsService
;
import
com.github.tangyi.common.security.wx.WxLoginSuccessHandler
;
import
com.github.tangyi.common.security.wx.WxSecurityConfigurer
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Lazy
;
import
org.springframework.security.crypto.password.PasswordEncoder
;
import
org.springframework.security.oauth2.provider.ClientDetailsService
;
import
org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices
;
import
org.springframework.security.web.authentication.AuthenticationSuccessHandler
;
/**
* 微信登录相关配置
*
* @author tangyi
* @date 2019/07/05 19:44
*/
@Configuration
public
class
WxLoginConfig
{
/**
* 配置微信登录
*
* @return WxSecurityConfigurer
*/
@Bean
public
WxSecurityConfigurer
wxSecurityConfigurer
(
@Lazy
PasswordEncoder
encoder
,
@Lazy
ClientDetailsService
clientDetailsService
,
@Lazy
CustomUserDetailsService
userDetailsService
,
@Lazy
ObjectMapper
objectMapper
,
@Lazy
AuthorizationServerTokenServices
defaultAuthorizationServerTokenServices
)
{
WxSecurityConfigurer
wxSecurityConfigurer
=
new
WxSecurityConfigurer
();
wxSecurityConfigurer
.
setWxLoginSuccessHandler
(
wxLoginSuccessHandler
(
encoder
,
clientDetailsService
,
objectMapper
,
defaultAuthorizationServerTokenServices
));
wxSecurityConfigurer
.
setUserDetailsService
(
userDetailsService
);
return
wxSecurityConfigurer
;
}
/**
* 微信登录成功后的处理
*
* @return AuthenticationSuccessHandler
*/
@Bean
public
AuthenticationSuccessHandler
wxLoginSuccessHandler
(
PasswordEncoder
encoder
,
ClientDetailsService
clientDetailsService
,
ObjectMapper
objectMapper
,
AuthorizationServerTokenServices
defaultAuthorizationServerTokenServices
)
{
return
WxLoginSuccessHandler
.
builder
()
.
objectMapper
(
objectMapper
)
.
clientDetailsService
(
clientDetailsService
)
.
passwordEncoder
(
encoder
)
.
defaultAuthorizationServerTokenServices
(
defaultAuthorizationServerTokenServices
).
build
();
}
}
common/common-security/src/main/java/com/github/tangyi/common/security/constant/SecurityConstant.java
View file @
e9194a2d
...
...
@@ -42,6 +42,11 @@ public class SecurityConstant {
public
static
final
String
MOBILE_TOKEN_URL
=
"/mobile/token"
;
/**
* 微信登录URL
*/
public
static
final
String
WX_TOKEN_URL
=
"/wx/token"
;
/**
* 租户编号请求头
*/
public
static
final
String
TENANT_CODE_HEADER
=
"Tenant-Code"
;
...
...
common/common-security/src/main/java/com/github/tangyi/common/security/core/CustomUserDetailsService.java
View file @
e9194a2d
package
com
.
github
.
tangyi
.
common
.
security
.
core
;
import
com.github.tangyi.common.security.wx.WxUser
;
import
org.springframework.security.core.userdetails.UserDetails
;
import
org.springframework.security.core.userdetails.UsernameNotFoundException
;
...
...
@@ -20,16 +21,28 @@ public interface CustomUserDetailsService {
* @author tangyi
* @date 2019/05/28 21:06
*/
UserDetails
loadUserBy
Username
AndTenantCode
(
String
username
,
String
tenantCode
)
throws
UsernameNotFoundException
;
UserDetails
loadUserBy
Identifier
AndTenantCode
(
String
username
,
String
tenantCode
)
throws
UsernameNotFoundException
;
/**
* 根据社交账号和租户标识查询
*
* @param social social
* @param social
social
* @param tenantCode tenantCode
* @return UserDetails
* @author tangyi
* @date 2019/06/22 21:08
*/
UserDetails
loadUserBySocialAndTenantCode
(
String
social
,
String
tenantCode
)
throws
UsernameNotFoundException
;
/**
* 根据微信openId和租户标识查询
*
* @param code code
* @param tenantCode tenantCode
* @param wxUser wxUser
* @return UserDetails
* @author tangyi
* @date 2019/07/05 20:04:59
*/
UserDetails
loadUserByWxCodeAndTenantCode
(
String
code
,
String
tenantCode
,
WxUser
wxUser
)
throws
UsernameNotFoundException
;
}
common/common-security/src/main/java/com/github/tangyi/common/security/mobile/MobileSecurityConfigurer.java
View file @
e9194a2d
...
...
@@ -13,7 +13,7 @@ import org.springframework.security.web.authentication.AuthenticationSuccessHand
import
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
;
/**
* 手机登录配置
,配置
* 手机登录配置
*
* @author tangyi
* @date 2019/6/22 21:26
...
...
common/common-security/src/main/java/com/github/tangyi/common/security/utils/GsonHelper.java
0 → 100644
View file @
e9194a2d
package
com
.
github
.
tangyi
.
common
.
security
.
utils
;
import
com.google.gson.Gson
;
import
java.lang.reflect.Type
;
/**
* 基于Gson的json工具类
*
* @author tangyi
* @date 2017-11-23 18:03
*/
public
class
GsonHelper
{
/**
* Gson对象
*/
private
static
final
Gson
gson
=
new
Gson
();
/**
* 单例
*/
private
volatile
static
GsonHelper
instance
;
/**
* 获取单例
*
* @author tangyi
* @date 2017/11/23 18:10
*/
public
static
GsonHelper
getInstance
()
{
if
(
instance
==
null
)
{
synchronized
(
GsonHelper
.
class
)
{
if
(
instance
==
null
)
instance
=
new
GsonHelper
();
}
}
return
instance
;
}
/**
* 将json转为对象
*
* @param json json
* @param clazz clazz
* @return T
* @author tangyi
* @date 2017/11/23 18:09
*/
public
<
T
>
T
fromJson
(
String
json
,
Class
<
T
>
clazz
)
{
return
gson
.
fromJson
(
json
,
clazz
);
}
/**
* 将json转为对象
*
* @param json json
* @param type type
* @return T
* @author tangyi
* @date 2017/11/28 15:41
*/
public
<
T
>
T
fromJson
(
String
json
,
Type
type
)
{
return
gson
.
fromJson
(
json
,
type
);
}
/**
* 将对象转为json
*
* @param src
* @return String
* @author tangyi
* @date 2017/11/23 18:09
*/
public
String
toJson
(
Object
src
)
{
return
gson
.
toJson
(
src
);
}
}
common/common-security/src/main/java/com/github/tangyi/common/security/wx/WxAuthenticationFilter.java
0 → 100644
View file @
e9194a2d
package
com
.
github
.
tangyi
.
common
.
security
.
wx
;
import
com.github.tangyi.common.security.constant.SecurityConstant
;
import
com.github.tangyi.common.security.utils.GsonHelper
;
import
lombok.Getter
;
import
lombok.Setter
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.io.IOUtils
;
import
org.apache.commons.lang.StringUtils
;
import
org.springframework.http.HttpMethod
;
import
org.springframework.security.authentication.AuthenticationEventPublisher
;
import
org.springframework.security.authentication.AuthenticationServiceException
;
import
org.springframework.security.authentication.BadCredentialsException
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.AuthenticationException
;
import
org.springframework.security.core.context.SecurityContextHolder
;
import
org.springframework.security.core.userdetails.UsernameNotFoundException
;
import
org.springframework.security.web.AuthenticationEntryPoint
;
import
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter
;
import
org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken
;
import
org.springframework.security.web.util.matcher.AntPathRequestMatcher
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
/**
* 微信登录filter,登录时支持传入用户的资料,如姓名、电话、性别等
*
* @author tangyi
* @date 2019/07/05 19:32
*/
@Slf4j
public
class
WxAuthenticationFilter
extends
AbstractAuthenticationProcessingFilter
{
/**
* 微信登录的code参数,后续用code换取openId和sessionKey
*/
private
static
final
String
SPRING_SECURITY_FORM_WX_KEY
=
"code"
;
@Getter
@Setter
private
String
wxParameter
=
SPRING_SECURITY_FORM_WX_KEY
;
@Getter
@Setter
private
boolean
postOnly
=
true
;
@Getter
@Setter
private
AuthenticationEventPublisher
eventPublisher
;
@Getter
@Setter
private
AuthenticationEntryPoint
authenticationEntryPoint
;
public
WxAuthenticationFilter
()
{
super
(
new
AntPathRequestMatcher
(
SecurityConstant
.
WX_TOKEN_URL
,
HttpMethod
.
POST
.
name
()));
}
@Override
public
Authentication
attemptAuthentication
(
HttpServletRequest
request
,
HttpServletResponse
response
)
throws
AuthenticationException
{
if
(
postOnly
&&
!
request
.
getMethod
().
equals
(
HttpMethod
.
POST
.
name
()))
throw
new
AuthenticationServiceException
(
"Authentication method not supported: "
+
request
.
getMethod
());
// 获取code
String
code
=
obtainCode
(
request
);
if
(
code
==
null
)
{
code
=
""
;
}
code
=
code
.
trim
();
// 封装成token
WxAuthenticationToken
wxAuthenticationToken
=
new
WxAuthenticationToken
(
code
);
// 封装其它基本信息
setWxUserDetails
(
request
,
wxAuthenticationToken
);
setDetails
(
request
,
wxAuthenticationToken
);
Authentication
authResult
=
null
;
try
{
// 认证
authResult
=
this
.
getAuthenticationManager
().
authenticate
(
wxAuthenticationToken
);
logger
.
debug
(
"Authentication success: "
+
authResult
);
// 认证成功
eventPublisher
.
publishAuthenticationSuccess
(
authResult
);
SecurityContextHolder
.
getContext
().
setAuthentication
(
authResult
);
}
catch
(
Exception
failed
)
{
SecurityContextHolder
.
clearContext
();
logger
.
debug
(
"Authentication request failed: "
+
failed
);
eventPublisher
.
publishAuthenticationFailure
(
new
BadCredentialsException
(
failed
.
getMessage
(),
failed
),
new
PreAuthenticatedAuthenticationToken
(
"access-token"
,
"N/A"
));
try
{
authenticationEntryPoint
.
commence
(
request
,
response
,
new
UsernameNotFoundException
(
failed
.
getMessage
(),
failed
));
}
catch
(
Exception
e
)
{
logger
.
error
(
"authenticationEntryPoint handle error:{}"
,
failed
);
}
}
return
authResult
;
}
private
String
obtainCode
(
HttpServletRequest
request
)
{
return
request
.
getParameter
(
wxParameter
);
}
private
void
setDetails
(
HttpServletRequest
request
,
WxAuthenticationToken
authRequest
)
{
authRequest
.
setDetails
(
authenticationDetailsSource
.
buildDetails
(
request
));
}
/**
* 设置姓名、性别、头像等信息
*
* @param request request
* @param authRequest authRequest
*/
private
void
setWxUserDetails
(
HttpServletRequest
request
,
WxAuthenticationToken
authRequest
)
{
try
{
String
result
=
IOUtils
.
toString
(
request
.
getReader
());
if
(
StringUtils
.
isNotBlank
(
result
))
{
WxUser
user
=
GsonHelper
.
getInstance
().
fromJson
(
result
,
WxUser
.
class
);
authRequest
.
setWxUser
(
user
);
}
}
catch
(
IOException
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
}
}
}
common/common-security/src/main/java/com/github/tangyi/common/security/wx/WxAuthenticationProvider.java
0 → 100644
View file @
e9194a2d
package
com
.
github
.
tangyi
.
common
.
security
.
wx
;
import
com.github.tangyi.common.security.core.CustomUserDetailsService
;
import
com.github.tangyi.common.security.tenant.TenantContextHolder
;
import
lombok.Data
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.context.support.MessageSourceAccessor
;
import
org.springframework.security.authentication.AuthenticationProvider
;
import
org.springframework.security.authentication.BadCredentialsException
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.AuthenticationException
;
import
org.springframework.security.core.SpringSecurityMessageSource
;
import
org.springframework.security.core.userdetails.UserDetails
;
/**
* @author tangyi
* @date 2019/07/05 19:34
*/
@Slf4j
@Data
public
class
WxAuthenticationProvider
implements
AuthenticationProvider
{
private
MessageSourceAccessor
messages
=
SpringSecurityMessageSource
.
getAccessor
();
private
CustomUserDetailsService
customUserDetailsService
;
@Override
public
Authentication
authenticate
(
Authentication
authentication
)
throws
AuthenticationException
{
WxAuthenticationToken
wxAuthenticationToken
=
(
WxAuthenticationToken
)
authentication
;
// 微信的code
String
principal
=
wxAuthenticationToken
.
getPrincipal
().
toString
();
UserDetails
userDetails
=
customUserDetailsService
.
loadUserByWxCodeAndTenantCode
(
principal
,
TenantContextHolder
.
getTenantCode
(),
wxAuthenticationToken
.
getWxUser
());
if
(
userDetails
==
null
)
{
log
.
debug
(
"Authentication failed: no credentials provided"
);
throw
new
BadCredentialsException
(
messages
.
getMessage
(
"AbstractUserDetailsAuthenticationProvider.noopBindAccount"
,
"Noop Bind Account"
));
}
WxAuthenticationToken
authenticationToken
=
new
WxAuthenticationToken
(
userDetails
,
userDetails
.
getAuthorities
());
authenticationToken
.
setDetails
(
wxAuthenticationToken
.
getDetails
());
return
authenticationToken
;
}
@Override
public
boolean
supports
(
Class
<?>
authentication
)
{
return
WxAuthenticationToken
.
class
.
isAssignableFrom
(
authentication
);
}
}
common/common-security/src/main/java/com/github/tangyi/common/security/wx/WxAuthenticationToken.java
0 → 100644
View file @
e9194a2d
package
com
.
github
.
tangyi
.
common
.
security
.
wx
;
import
org.springframework.security.authentication.AbstractAuthenticationToken
;
import
org.springframework.security.core.GrantedAuthority
;
import
java.util.Collection
;
/**
* 微信登录token
*
* @author tangyi
* @date 2019/07/05 19:29
*/
public
class
WxAuthenticationToken
extends
AbstractAuthenticationToken
{
/**
* code
*/
private
final
Object
principal
;
private
WxUser
wxUser
;
public
WxAuthenticationToken
(
String
code
)
{
super
(
null
);
this
.
principal
=
code
;
setAuthenticated
(
false
);
}
public
WxAuthenticationToken
(
Object
principal
,
Collection
<?
extends
GrantedAuthority
>
authorities
)
{
super
(
authorities
);
this
.
principal
=
principal
;
super
.
setAuthenticated
(
true
);
}
@Override
public
Object
getCredentials
()
{
return
null
;
}
@Override
public
Object
getPrincipal
()
{
return
this
.
principal
;
}
@Override
public
void
setAuthenticated
(
boolean
isAuthenticated
)
throws
IllegalArgumentException
{
if
(
isAuthenticated
)
{
throw
new
IllegalArgumentException
(
"Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead"
);
}
super
.
setAuthenticated
(
false
);
}
@Override
public
void
eraseCredentials
()
{
super
.
eraseCredentials
();
}
public
WxUser
getWxUser
()
{
return
wxUser
;
}
public
void
setWxUser
(
WxUser
wxUser
)
{
this
.
wxUser
=
wxUser
;
}
}
common/common-security/src/main/java/com/github/tangyi/common/security/wx/WxLoginSuccessHandler.java
0 → 100644
View file @
e9194a2d
package
com
.
github
.
tangyi
.
common
.
security
.
wx
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.github.tangyi.common.security.constant.SecurityConstant
;
import
com.github.tangyi.common.security.utils.SecurityUtil
;
import
lombok.Builder
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.http.HttpHeaders
;
import
org.springframework.security.authentication.BadCredentialsException
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.crypto.password.PasswordEncoder
;
import
org.springframework.security.oauth2.common.OAuth2AccessToken
;
import
org.springframework.security.oauth2.common.exceptions.InvalidClientException
;
import
org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException
;
import
org.springframework.security.oauth2.provider.*
;
import
org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestValidator
;
import
org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices
;
import
org.springframework.security.web.authentication.AuthenticationSuccessHandler
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
import
java.io.PrintWriter
;
import
java.util.HashMap
;
/**
* 微信登录成功
*
* @author tangyi
* @date 2019/07/05 19:29
*/
@Slf4j
@Builder
public
class
WxLoginSuccessHandler
implements
AuthenticationSuccessHandler
{
private
static
final
String
BASIC_
=
"Basic "
;
private
ObjectMapper
objectMapper
;
private
PasswordEncoder
passwordEncoder
;
private
ClientDetailsService
clientDetailsService
;
private
AuthorizationServerTokenServices
defaultAuthorizationServerTokenServices
;
/**
* Called when a user has been successfully authenticated.
* 调用spring security oauth API 生成 oAuth2AccessToken
*
* @param request the request which caused the successful authentication
* @param response the response
* @param authentication the <tt>Authentication</tt> object which was created during
*/
@Override
public
void
onAuthenticationSuccess
(
HttpServletRequest
request
,
HttpServletResponse
response
,
Authentication
authentication
)
{
String
header
=
request
.
getHeader
(
HttpHeaders
.
AUTHORIZATION
);
if
(
header
==
null
||
!
header
.
startsWith
(
BASIC_
))
throw
new
UnapprovedClientAuthenticationException
(
"请求头中client信息为空"
);
try
{
String
[]
tokens
=
SecurityUtil
.
extractAndDecodeHeader
(
header
);
assert
tokens
.
length
==
2
;
String
clientId
=
tokens
[
0
];
ClientDetails
clientDetails
=
clientDetailsService
.
loadClientByClientId
(
clientId
);
// 校验secret
if
(!
passwordEncoder
.
matches
(
tokens
[
1
],
clientDetails
.
getClientSecret
()))
throw
new
InvalidClientException
(
"Given client ID does not match authenticated client"
);
TokenRequest
tokenRequest
=
new
TokenRequest
(
new
HashMap
<>(),
clientId
,
clientDetails
.
getScope
(),
"wx"
);
// 校验scope
new
DefaultOAuth2RequestValidator
().
validateScope
(
tokenRequest
,
clientDetails
);
OAuth2Request
oAuth2Request
=
tokenRequest
.
createOAuth2Request
(
clientDetails
);
OAuth2Authentication
oAuth2Authentication
=
new
OAuth2Authentication
(
oAuth2Request
,
authentication
);
OAuth2AccessToken
oAuth2AccessToken
=
defaultAuthorizationServerTokenServices
.
createAccessToken
(
oAuth2Authentication
);
response
.
setCharacterEncoding
(
"utf-8"
);
response
.
setContentType
(
SecurityConstant
.
CONTENT_TYPE
);
PrintWriter
printWriter
=
response
.
getWriter
();
printWriter
.
append
(
objectMapper
.
writeValueAsString
(
oAuth2AccessToken
));
}
catch
(
IOException
e
)
{
throw
new
BadCredentialsException
(
"Failed to decode basic authentication token"
);
}
}
}
common/common-security/src/main/java/com/github/tangyi/common/security/wx/WxSecurityConfigurer.java
0 → 100644
View file @
e9194a2d
package
com
.
github
.
tangyi
.
common
.
security
.
wx
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.github.tangyi.common.security.core.CustomUserDetailsService
;
import
lombok.Data
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.security.authentication.AuthenticationEventPublisher
;
import
org.springframework.security.authentication.AuthenticationManager
;
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.AuthenticationSuccessHandler
;
import
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
;
/**
* 微信登录配置
*
* @author tangyi
* @date 2019/07/05 19:29
*/
@Data
public
class
WxSecurityConfigurer
extends
SecurityConfigurerAdapter
<
DefaultSecurityFilterChain
,
HttpSecurity
>
{
@Autowired
private
ObjectMapper
objectMapper
;
@Autowired
private
AuthenticationEventPublisher
defaultAuthenticationEventPublisher
;
private
AuthenticationSuccessHandler
wxLoginSuccessHandler
;
private
CustomUserDetailsService
userDetailsService
;
@Override
public
void
configure
(
HttpSecurity
http
)
{
// 微信登录过滤器
WxAuthenticationFilter
wxAuthenticationFilter
=
new
WxAuthenticationFilter
();
wxAuthenticationFilter
.
setAuthenticationManager
(
http
.
getSharedObject
(
AuthenticationManager
.
class
));
wxAuthenticationFilter
.
setAuthenticationSuccessHandler
(
wxLoginSuccessHandler
);
wxAuthenticationFilter
.
setEventPublisher
(
defaultAuthenticationEventPublisher
);
WxAuthenticationProvider
wxAuthenticationProvider
=
new
WxAuthenticationProvider
();
wxAuthenticationProvider
.
setCustomUserDetailsService
(
userDetailsService
);
// 增加微信登录的过滤器
http
.
authenticationProvider
(
wxAuthenticationProvider
).
addFilterAfter
(
wxAuthenticationFilter
,
UsernamePasswordAuthenticationFilter
.
class
);
}
}
common/common-security/src/main/java/com/github/tangyi/common/security/wx/WxUser.java
0 → 100644
View file @
e9194a2d
package
com
.
github
.
tangyi
.
common
.
security
.
wx
;
import
lombok.Data
;
import
java.io.Serializable
;
/**
* 微信用户的基本信息
*
* @author tangyi
* @date 2019/07/06 15:58
*/
@Data
public
class
WxUser
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 姓名
*/
private
String
name
;
/**
* 性别
*/
private
Integer
sex
;
/**
* 头像地址
*/
private
String
avatarUrl
;
/**
* 详细描述
*/
private
String
userDesc
;
/**
* 国家
*/
private
String
country
;
/**
* 省
*/
private
String
province
;
/**
* 市
*/
private
String
city
;
/**
* 语言
*/
private
String
languang
;
}
config-service/src/main/resources/config/auth-service.yml
View file @
e9194a2d
...
...
@@ -117,6 +117,16 @@ cluster:
# 系统配置
sys
:
adminUser
:
${ADMIN_USER:admin}
# 管理员账号,默认是admin
fdfsHttpHost
:
${ATTACHMENT_HOST:http://192.168.0.95}:${ATTACHMENT_PORT:8080}
# fastDfs的HTTP配置
uploadUrl
:
api/user/v1/attachment/upload
defaultAvatar
:
https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif?imageView2/1/w/80/h/80
key
:
'
1234567887654321'
# 微信配置
wx
:
appId
:
wx597d9f972f991a8c
appSecret
:
b5d44266271a08c6f75a347712a7334e
grantType
:
authorization_code
logging
:
level
:
...
...
config-service/src/main/resources/config/gateway-service.yml
View file @
e9194a2d
...
...
@@ -28,16 +28,16 @@ spring:
zipkin
:
base-url
:
http://${ZIPKIN_HOST:localhost}:${ZIPKIN_PORT:9411}
# 指定了Zipkin服务器的地址
security
:
encode
:
key
:
'
1234567887654321'
# 系统配置
sys
:
adminUser
:
${ADMIN_USER:admin}
# 管理员账号,默认是admin
fdfsHttpHost
:
${ATTACHMENT_HOST:http://192.168.0.95}:${ATTACHMENT_PORT:8080}
# fastDfs的HTTP配置
uploadUrl
:
api/user/v1/attachment/upload
defaultAvatar
:
https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif?imageView2/1/w/80/h/80
key
:
'
1234567887654321'
# feign相关配置
feign
:
httpclient
:
enabled
:
false
okhttp
:
enabled
:
true
hystrix
:
enabled
:
true
...
...
@@ -83,9 +83,10 @@ preview:
-
api/msc
# 开启网关token转换
# 暂时关闭,此功能在微信端登录有问题
gateway
:
token-transfer
:
enabled
:
${GATEWAY_TOKEN_TRANSFER:
tru
e
}
enabled
:
${GATEWAY_TOKEN_TRANSFER:
fals
e
}
# 集群ID生成配置
cluster
:
...
...
config-service/src/main/resources/config/user-service.yml
View file @
e9194a2d
...
...
@@ -97,6 +97,7 @@ sys:
fdfsHttpHost
:
${ATTACHMENT_HOST:http://192.168.0.95}:${ATTACHMENT_PORT:8080}
# fastDfs的HTTP配置
uploadUrl
:
api/user/v1/attachment/upload
defaultAvatar
:
https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif?imageView2/1/w/80/h/80
key
:
'
1234567887654321'
# feign相关配置
feign
:
...
...
docs/产品设计/数据库设计/在线考试.pdb
View file @
e9194a2d
This diff is collapsed.
Click to expand it.
docs/产品设计/数据库设计/在线考试.pdm
View file @
e9194a2d
This diff is collapsed.
Click to expand it.
gateway-service/pom.xml
View file @
e9194a2d
...
...
@@ -35,17 +35,6 @@
<groupId>
de.codecentric
</groupId>
<artifactId>
spring-boot-admin-starter-client
</artifactId>
</dependency>
<!-- swagger -->
<dependency>
<groupId>
io.springfox
</groupId>
<artifactId>
springfox-swagger2
</artifactId>
</dependency>
<dependency>
<groupId>
io.springfox
</groupId>
<artifactId>
springfox-swagger-ui
</artifactId>
</dependency>
</dependencies>
<build>
...
...
gateway-service/src/main/java/com/github/tangyi/gateway/config/CorsConfig.java
0 → 100644
View file @
e9194a2d
package
com
.
github
.
tangyi
.
gateway
.
config
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.http.HttpHeaders
;
import
org.springframework.http.HttpMethod
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.server.reactive.ServerHttpRequest
;
import
org.springframework.http.server.reactive.ServerHttpResponse
;
import
org.springframework.web.cors.reactive.CorsUtils
;
import
org.springframework.web.server.ServerWebExchange
;
import
org.springframework.web.server.WebFilter
;
import
org.springframework.web.server.WebFilterChain
;
import
reactor.core.publisher.Mono
;
import
static
io
.
netty
.
handler
.
codec
.
http
.
cookie
.
CookieHeaderNames
.
MAX_AGE
;
import
static
org
.
springframework
.
web
.
cors
.
CorsConfiguration
.
ALL
;
/**
* 跨域配置
*
* @author tangyi
* @date 2019/07/06 17:12
*/
@Configuration
public
class
CorsConfig
{
@Bean
public
WebFilter
corsFilter
()
{
return
(
ServerWebExchange
ctx
,
WebFilterChain
chain
)
->
{
ServerHttpRequest
request
=
ctx
.
getRequest
();
if
(!
CorsUtils
.
isCorsRequest
(
request
))
return
chain
.
filter
(
ctx
);
HttpHeaders
requestHeaders
=
request
.
getHeaders
();
ServerHttpResponse
response
=
ctx
.
getResponse
();
HttpMethod
requestMethod
=
requestHeaders
.
getAccessControlRequestMethod
();
HttpHeaders
headers
=
response
.
getHeaders
();
headers
.
add
(
HttpHeaders
.
ACCESS_CONTROL_ALLOW_ORIGIN
,
requestHeaders
.
getOrigin
());
headers
.
addAll
(
HttpHeaders
.
ACCESS_CONTROL_ALLOW_HEADERS
,
requestHeaders
.
getAccessControlRequestHeaders
());
if
(
requestMethod
!=
null
)
headers
.
add
(
HttpHeaders
.
ACCESS_CONTROL_ALLOW_METHODS
,
requestMethod
.
name
());
headers
.
add
(
HttpHeaders
.
ACCESS_CONTROL_ALLOW_CREDENTIALS
,
"true"
);
headers
.
add
(
HttpHeaders
.
ACCESS_CONTROL_EXPOSE_HEADERS
,
ALL
);
headers
.
add
(
HttpHeaders
.
ACCESS_CONTROL_MAX_AGE
,
MAX_AGE
);
if
(
request
.
getMethod
()
==
HttpMethod
.
OPTIONS
)
{
response
.
setStatusCode
(
HttpStatus
.
OK
);
return
Mono
.
empty
();
}
return
chain
.
filter
(
ctx
);
};
}
}
gateway-service/src/main/java/com/github/tangyi/gateway/constants/GatewayConstant.java
View file @
e9194a2d
...
...
@@ -17,6 +17,11 @@ public class GatewayConstant {
public
static
final
String
MOBILE_TOKEN_URL
=
"/mobile/token"
;
/**
* 微信登录URL
*/
public
static
final
String
WX_TOKEN_URL
=
"/wx/token"
;
/**
* 注册
*/
public
static
final
String
REGISTER
=
"/user/register"
;
...
...
gateway-service/src/main/java/com/github/tangyi/gateway/filters/DecodePasswordFilter.java
View file @
e9194a2d
package
com
.
github
.
tangyi
.
gateway
.
filters
;
import
cn.hutool.core.codec.Base64
;
import
cn.hutool.core.util.StrUtil
;
import
com.github.tangyi.common.core.constant.CommonConstant
;
import
com.github.tangyi.common.core.properties.SysProperties
;
import
com.github.tangyi.common.core.utils.SysUtil
;
import
com.github.tangyi.gateway.constants.GatewayConstant
;
import
lombok.AllArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.
springframework.beans.factory.annotation.Value
;
import
org.
apache.commons.lang.StringUtils
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
;
import
org.springframework.cloud.gateway.filter.GatewayFilterChain
;
import
org.springframework.cloud.gateway.filter.GlobalFilter
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.core.Ordered
;
import
org.springframework.http.HttpMethod
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.server.reactive.ServerHttpRequest
;
import
org.springframework.web.server.ServerWebExchange
;
import
org.springframework.web.util.UriComponentsBuilder
;
import
reactor.core.publisher.Mono
;
import
javax.crypto.Cipher
;
import
javax.crypto.spec.IvParameterSpec
;
import
javax.crypto.spec.SecretKeySpec
;
import
java.net.URI
;
import
java.nio.charset.StandardCharsets
;
/**
* 解密过滤器
...
...
@@ -32,23 +29,16 @@ import java.nio.charset.StandardCharsets;
* @date 2019/3/18 11:30
*/
@Slf4j
@AllArgsConstructor
@Configuration
@ConditionalOnProperty
(
value
=
"s
ecurity.encode
.key"
)
@ConditionalOnProperty
(
value
=
"s
ys
.key"
)
public
class
DecodePasswordFilter
implements
GlobalFilter
,
Ordered
{
private
static
final
String
KEY_ALGORITHM
=
"AES"
;
private
static
final
String
DEFAULT_CIPHER_ALGORITHM
=
"AES/CBC/NOPadding"
;
private
static
final
String
CREDENTIAL
=
"credential"
;
private
static
final
String
PASSWORD
=
"password"
;
/**
* 约定的key
*/
@Value
(
"${security.encode.key}"
)
private
String
key
;
private
final
SysProperties
sysProperties
;
@Override
public
Mono
<
Void
>
filter
(
ServerWebExchange
exchange
,
GatewayFilterChain
chain
)
{
...
...
@@ -63,27 +53,24 @@ public class DecodePasswordFilter implements GlobalFilter, Ordered {
// 授权类型为密码模式则解密
if
(
CommonConstant
.
GRANT_TYPE_PASSWORD
.
equals
(
grantType
)
||
StrUtil
.
containsAnyIgnoreCase
(
uri
.
getPath
(),
GatewayConstant
.
REGISTER
))
{
String
credential
=
request
.
getQueryParams
().
getFirst
(
CREDENTIAL
);
if
(
credential
==
null
||
credential
.
isEmpty
())
{
log
.
info
(
"credential is empty..."
);
exchange
.
getResponse
().
setStatusCode
(
HttpStatus
.
UNAUTHORIZED
);
return
exchange
.
getResponse
().
setComplete
();
}
try
{
// 开始解密
credential
=
decryptAES
(
credential
,
key
);
credential
=
credential
.
trim
();
log
.
debug
(
"credential decrypt success:{}"
,
credential
);
}
catch
(
Exception
e
)
{
log
.
error
(
"credential decrypt fail:{}"
,
credential
);
if
(
StringUtils
.
isNotBlank
(
credential
))
{
try
{
// 开始解密
credential
=
SysUtil
.
decryptAES
(
credential
,
sysProperties
.
getKey
());
credential
=
credential
.
trim
();
log
.
debug
(
"credential decrypt success:{}"
,
credential
);
}
catch
(
Exception
e
)
{
log
.
error
(
"credential decrypt fail:{}"
,
credential
);
}
URI
newUri
=
UriComponentsBuilder
.
fromUri
(
uri
)
// 替换password字段
.
replaceQueryParam
(
PASSWORD
,
credential
)
// 替换credential字段
.
replaceQueryParam
(
CREDENTIAL
,
credential
)
.
build
(
true
).
toUri
();
request
=
request
.
mutate
().
uri
(
newUri
).
build
();
return
chain
.
filter
(
exchange
.
mutate
().
request
(
request
).
build
());
}
URI
newUri
=
UriComponentsBuilder
.
fromUri
(
uri
)
// 替换password字段
.
replaceQueryParam
(
PASSWORD
,
credential
)
// 替换credential字段
.
replaceQueryParam
(
CREDENTIAL
,
credential
)
.
build
(
true
).
toUri
();
request
=
request
.
mutate
().
uri
(
newUri
).
build
();
return
chain
.
filter
(
exchange
.
mutate
().
request
(
request
).
build
());
}
}
return
chain
.
filter
(
exchange
);
...
...
@@ -93,20 +80,4 @@ public class DecodePasswordFilter implements GlobalFilter, Ordered {
public
int
getOrder
()
{
return
-
100
;
}
/**
* des解密
*
* @param data data
* @param pass pass
* @return String
* @author tangyi
* @date 2019/03/18 11:39
*/
private
static
String
decryptAES
(
String
data
,
String
pass
)
throws
Exception
{
Cipher
cipher
=
Cipher
.
getInstance
(
DEFAULT_CIPHER_ALGORITHM
);
cipher
.
init
(
Cipher
.
DECRYPT_MODE
,
new
SecretKeySpec
(
pass
.
getBytes
(),
KEY_ALGORITHM
),
new
IvParameterSpec
(
pass
.
getBytes
()));
byte
[]
result
=
cipher
.
doFinal
(
Base64
.
decode
(
data
.
getBytes
(
StandardCharsets
.
UTF_8
)));
return
new
String
(
result
,
StandardCharsets
.
UTF_8
);
}
}
gateway-service/src/main/java/com/github/tangyi/gateway/filters/TokenRequestGlobalFilter.java
View file @
e9194a2d
...
...
@@ -25,7 +25,6 @@ import org.springframework.web.server.ServerWebExchange;
import
reactor.core.publisher.Flux
;
import
reactor.core.publisher.Mono
;
import
java.net.URI
;
import
java.nio.charset.StandardCharsets
;
import
java.util.List
;
import
java.util.concurrent.TimeUnit
;
...
...
@@ -64,54 +63,79 @@ public class TokenRequestGlobalFilter implements GlobalFilter, Ordered {
public
Mono
<
Void
>
filter
(
ServerWebExchange
exchange
,
GatewayFilterChain
chain
)
{
// 当前请求
ServerHttpRequest
request
=
exchange
.
getRequest
();
// 请求的URI
URI
uri
=
request
.
getURI
();
if
(
HttpMethod
.
POST
.
matches
(
request
.
getMethodValue
())
&&
StrUtil
.
containsAnyIgnoreCase
(
uri
.
getPath
(),
GatewayConstant
.
OAUTH_TOKEN_URL
,
GatewayConstant
.
REGISTER
,
GatewayConstant
.
MOBILE_TOKEN_URL
))
{
if
(
match
(
request
))
{
String
grantType
=
request
.
getQueryParams
().
getFirst
(
GatewayConstant
.
GRANT_TYPE
);
// 授权类型为密码、手机号模式
if
(
CommonConstant
.
GRANT_TYPE_PASSWORD
.
equals
(
grantType
)
||
CommonConstant
.
GRANT_TYPE_MOBILE
.
equals
(
grantType
)
||
GatewayConstant
.
GRANT_TYPE_REFRESH_TOKEN
.
equals
(
grantType
))
{
// 装饰器
ServerHttpResponseDecorator
decoratedResponse
=
new
ServerHttpResponseDecorator
(
exchange
.
getResponse
())
{
@Override
public
Mono
<
Void
>
writeWith
(
Publisher
<?
extends
DataBuffer
>
body
)
{
if
(
getStatusCode
()
!=
null
&&
getStatusCode
().
equals
(
HttpStatus
.
OK
)
&&
body
instanceof
Flux
)
{
Flux
<?
extends
DataBuffer
>
fluxBody
=
Flux
.
from
(
body
);
return
super
.
writeWith
(
fluxBody
.
buffer
().
map
(
dataBuffers
->
{
long
start
=
System
.
currentTimeMillis
();
List
<
String
>
contentList
=
Lists
.
newArrayList
();
dataBuffers
.
forEach
(
dataBuffer
->
{
byte
[]
content
=
new
byte
[
dataBuffer
.
readableByteCount
()];
dataBuffer
.
read
(
content
);
// 释放缓存
DataBufferUtils
.
release
(
dataBuffer
);
contentList
.
add
(
new
String
(
content
,
StandardCharsets
.
UTF_8
));
});
// 因为返回的数据量大时,获取到的buffer是不完整的,所以需要连接多个buffer
String
accessTokenContent
=
joiner
.
join
(
contentList
);
log
.
trace
(
"生成的accessToken: {}"
,
accessTokenContent
);
AccessToken
accessToken
=
JsonMapper
.
getInstance
().
fromJson
(
accessTokenContent
,
AccessToken
.
class
);
if
(
accessToken
==
null
||
StringUtils
.
isBlank
(
accessToken
.
getJti
()))
throw
new
InvalidAccessTokenException
(
"token转换失败!"
);
// 真正的access_token和refresh_token
String
realAccessToken
=
accessToken
.
getAccessToken
(),
realRefreshToken
=
accessToken
.
getRefreshToken
();
// 转换token
String
converted
=
JsonMapper
.
getInstance
().
toJson
(
accessToken
);
log
.
trace
(
"转换token结果:{}"
,
converted
);
// 将真正的access_token,refresh_token存入Redis,建立jti->access_token的映射关系,失效时间为token的失效时间
// 暂时用Redis
redisTemplate
.
opsForValue
().
set
(
GatewayConstant
.
GATEWAY_ACCESS_TOKENS
+
accessToken
.
getJti
(),
realAccessToken
,
accessToken
.
getExpiresIn
(),
TimeUnit
.
SECONDS
);
redisTemplate
.
opsForValue
().
set
(
GatewayConstant
.
GATEWAY_REFRESH_TOKENS
+
accessToken
.
getJti
(),
realRefreshToken
,
REFRESH_TOKEN_EXPIRE
,
TimeUnit
.
SECONDS
);
log
.
trace
(
"转换token和建立映射关系成功,耗时:{}ms"
,
System
.
currentTimeMillis
()
-
start
);
return
bufferFactory
().
wrap
(
converted
.
getBytes
());
}));
}
return
super
.
writeWith
(
body
);
}
};
return
chain
.
filter
(
exchange
.
mutate
().
response
(
decoratedResponse
).
build
());
// 授权类型为密码、手机号、微信openId
if
(
matchGrantType
(
grantType
))
{
return
chain
.
filter
(
exchange
.
mutate
().
response
(
responseDecorator
(
exchange
)).
build
());
}
}
return
chain
.
filter
(
exchange
);
}
/**
* 修改响应体
*
* @param exchange exchange
* @return ServerHttpResponseDecorator
*/
private
ServerHttpResponseDecorator
responseDecorator
(
ServerWebExchange
exchange
)
{
// 装饰器
return
new
ServerHttpResponseDecorator
(
exchange
.
getResponse
())
{
@Override
public
Mono
<
Void
>
writeWith
(
Publisher
<?
extends
DataBuffer
>
body
)
{
if
(
getStatusCode
()
!=
null
&&
getStatusCode
().
equals
(
HttpStatus
.
OK
)
&&
body
instanceof
Flux
)
{
Flux
<?
extends
DataBuffer
>
fluxBody
=
Flux
.
from
(
body
);
return
super
.
writeWith
(
fluxBody
.
buffer
().
map
(
dataBuffers
->
{
long
start
=
System
.
currentTimeMillis
();
List
<
String
>
contentList
=
Lists
.
newArrayList
();
dataBuffers
.
forEach
(
dataBuffer
->
{
byte
[]
content
=
new
byte
[
dataBuffer
.
readableByteCount
()];
dataBuffer
.
read
(
content
);
// 释放缓存
DataBufferUtils
.
release
(
dataBuffer
);
contentList
.
add
(
new
String
(
content
,
StandardCharsets
.
UTF_8
));
});
// 因为返回的数据量大时,获取到的buffer是不完整的,所以需要连接多个buffer
String
accessTokenContent
=
joiner
.
join
(
contentList
);
AccessToken
accessToken
=
JsonMapper
.
getInstance
().
fromJson
(
accessTokenContent
,
AccessToken
.
class
);
if
(
accessToken
==
null
||
StringUtils
.
isBlank
(
accessToken
.
getJti
()))
throw
new
InvalidAccessTokenException
(
"token转换失败!"
);
// 真正的access_token和refresh_token
String
realAccessToken
=
accessToken
.
getAccessToken
(),
realRefreshToken
=
accessToken
.
getRefreshToken
();
// 转换token
String
converted
=
JsonMapper
.
getInstance
().
toJson
(
accessToken
);
// 将真正的access_token,refresh_token存入Redis,建立jti->access_token的映射关系,失效时间为token的失效时间
// 暂时用Redis
redisTemplate
.
opsForValue
().
set
(
GatewayConstant
.
GATEWAY_ACCESS_TOKENS
+
accessToken
.
getJti
(),
realAccessToken
,
accessToken
.
getExpiresIn
(),
TimeUnit
.
SECONDS
);
redisTemplate
.
opsForValue
().
set
(
GatewayConstant
.
GATEWAY_REFRESH_TOKENS
+
accessToken
.
getJti
(),
realRefreshToken
,
REFRESH_TOKEN_EXPIRE
,
TimeUnit
.
SECONDS
);
log
.
debug
(
"转换token和建立映射关系成功,耗时:{}ms"
,
System
.
currentTimeMillis
()
-
start
);
return
bufferFactory
().
wrap
(
converted
.
getBytes
());
}));
}
return
super
.
writeWith
(
body
);
}
};
}
/**
* 是否过滤
*
* @param request request
* @return boolean
*/
private
boolean
match
(
ServerHttpRequest
request
)
{
return
HttpMethod
.
POST
.
matches
(
request
.
getMethodValue
())
&&
StrUtil
.
containsAnyIgnoreCase
(
request
.
getURI
().
getPath
(),
GatewayConstant
.
OAUTH_TOKEN_URL
,
GatewayConstant
.
MOBILE_TOKEN_URL
,
GatewayConstant
.
WX_TOKEN_URL
);
}
/**
* 需要过滤的授权类型
*
* @param grantType grantType
* @return boolean
*/
private
boolean
matchGrantType
(
String
grantType
)
{
return
CommonConstant
.
GRANT_TYPE_PASSWORD
.
equals
(
grantType
)
||
CommonConstant
.
GRANT_TYPE_MOBILE
.
equals
(
grantType
)
||
CommonConstant
.
GRANT_TYPE_WX
.
equals
(
grantType
)
||
GatewayConstant
.
GRANT_TYPE_REFRESH_TOKEN
.
equals
(
grantType
);
}
}
gateway-service/src/main/java/com/github/tangyi/gateway/filters/TokenResponseGlobalFilter.java
View file @
e9194a2d
...
...
@@ -47,7 +47,7 @@ public class TokenResponseGlobalFilter implements GlobalFilter, Ordered {
// 获取Authorization请求头
String
authorization
=
request
.
getHeaders
().
getFirst
(
CommonConstant
.
REQ_HEADER
);
// 先判断是否为刷新token请求
if
(
StrUtil
.
containsAnyIgnoreCase
(
uri
.
getPath
(),
GatewayConstant
.
OAUTH_TOKEN_URL
,
GatewayConstant
.
MOBILE_TOKEN_URL
))
{
if
(
StrUtil
.
containsAnyIgnoreCase
(
uri
.
getPath
(),
GatewayConstant
.
OAUTH_TOKEN_URL
,
GatewayConstant
.
MOBILE_TOKEN_URL
,
GatewayConstant
.
WX_TOKEN_URL
))
{
String
grantType
=
request
.
getQueryParams
().
getFirst
(
GatewayConstant
.
GRANT_TYPE
);
// 授权类型为refresh_token
if
(
GatewayConstant
.
GRANT_TYPE_REFRESH_TOKEN
.
equals
(
grantType
))
{
...
...
@@ -56,16 +56,13 @@ public class TokenResponseGlobalFilter implements GlobalFilter, Ordered {
// 根据jti从Redis里获取真正的refresh_token
Object
object
=
redisTemplate
.
opsForValue
().
get
(
GatewayConstant
.
GATEWAY_REFRESH_TOKENS
+
refreshToken
);
refreshToken
=
object
==
null
?
refreshToken
:
object
.
toString
();
log
.
trace
(
"refreshToken:{}"
,
refreshToken
);
// 替换refresh_token参数
URI
newUri
=
UriComponentsBuilder
.
fromUri
(
uri
).
replaceQueryParam
(
GatewayConstant
.
GRANT_TYPE_REFRESH_TOKEN
,
refreshToken
).
build
(
true
).
toUri
();
log
.
trace
(
"newUri: {}"
,
newUri
);
ServerHttpRequest
newRequest
=
exchange
.
getRequest
().
mutate
().
uri
(
newUri
).
build
();
return
chain
.
filter
(
exchange
.
mutate
().
request
(
newRequest
).
build
());
}
}
else
if
(
StringUtils
.
isNotBlank
(
authorization
)
&&
authorization
.
startsWith
(
CommonConstant
.
TOKEN_SPLIT
))
{
authorization
=
authorization
.
replace
(
CommonConstant
.
TOKEN_SPLIT
,
""
);
log
.
trace
(
"jti authorization: {}"
,
authorization
);
// 从Redis里获取实际的access_token
Object
object
=
redisTemplate
.
opsForValue
().
get
(
GatewayConstant
.
GATEWAY_ACCESS_TOKENS
+
authorization
);
// 缓存里没有access_token,抛异常,统一异常处理会返回403,前端自动重新获取access_token
...
...
@@ -73,10 +70,8 @@ public class TokenResponseGlobalFilter implements GlobalFilter, Ordered {
throw
new
InvalidAccessTokenException
(
"access_token已失效."
);
authorization
=
CommonConstant
.
TOKEN_SPLIT
+
object
.
toString
();
String
realAuthorization
=
authorization
;
log
.
trace
(
"jti->token:{}"
,
realAuthorization
);
// 更新请求头,参考源码:SetRequestHeaderGatewayFilterFactory
ServerHttpRequest
newRequest
=
request
.
mutate
().
headers
(
httpHeaders
->
httpHeaders
.
set
(
CommonConstant
.
REQ_HEADER
,
realAuthorization
)).
build
();
log
.
trace
(
"newRequestHeader:{}"
,
newRequest
.
getHeaders
().
getFirst
(
CommonConstant
.
REQ_HEADER
));
return
chain
.
filter
(
exchange
.
mutate
().
request
(
newRequest
).
build
());
}
return
chain
.
filter
(
exchange
);
...
...
gateway-service/src/main/java/com/github/tangyi/gateway/model/AccessToken.java
View file @
e9194a2d
...
...
@@ -26,11 +26,6 @@ public class AccessToken implements Serializable {
private
String
accessToken
;
/**
* 创建时间
*/
private
Integer
createTime
;
/**
* 超时时间
*/
@JsonProperty
(
"expires_in"
)
...
...
gateway-service/src/main/java/com/github/tangyi/gateway/serializer/AccessTokenJacksonSerializer.java
View file @
e9194a2d
...
...
@@ -25,7 +25,8 @@ public class AccessTokenJacksonSerializer extends StdSerializer<AccessToken> {
gen
.
writeStringField
(
"refresh_token"
,
accessToken
.
getJti
());
gen
.
writeStringField
(
"scope"
,
accessToken
.
getScope
());
gen
.
writeStringField
(
"token_type"
,
accessToken
.
getTokenType
());
gen
.
writeStringField
(
"tenant_code"
,
accessToken
.
getTenantCode
());
gen
.
writeStringField
(
"tenantCode"
,
accessToken
.
getTenantCode
());
gen
.
writeStringField
(
"loginType"
,
accessToken
.
getLoginType
());
gen
.
writeEndObject
();
}
}
pom.xml
View file @
e9194a2d
...
...
@@ -75,6 +75,7 @@
<json.version>
20140107
</json.version>
<okhttp.version>
3.8.1
</okhttp.version>
<aliyun.version>
4.1.0
</aliyun.version>
<weixin.version>
3.4.0
</weixin.version>
<!-- docker -->
<docker.maven.verion>
1.4.3
</docker.maven.verion>
...
...
@@ -138,6 +139,17 @@
<groupId>
org.projectlombok
</groupId>
<artifactId>
lombok
</artifactId>
</dependency>
<!-- swagger -->
<dependency>
<groupId>
io.springfox
</groupId>
<artifactId>
springfox-swagger2
</artifactId>
</dependency>
<dependency>
<groupId>
io.springfox
</groupId>
<artifactId>
springfox-swagger-ui
</artifactId>
</dependency>
</dependencies>
<!-- spring cloud base -->
...
...
@@ -268,6 +280,20 @@
<artifactId>
kaptcha
</artifactId>
<version>
${kaptcha.version}
</version>
</dependency>
<!-- 微信小程序 -->
<dependency>
<groupId>
com.github.binarywang
</groupId>
<artifactId>
weixin-java-miniapp
</artifactId>
<version>
${weixin.version}
</version>
</dependency>
<!-- 微信支付 -->
<dependency>
<groupId>
com.github.binarywang
</groupId>
<artifactId>
weixin-java-pay
</artifactId>
<version>
${weixin.version}
</version>
</dependency>
</dependencies>
</dependencyManagement>
...
...
service-api-impl/auth-service/README.md
0 → 100644
View file @
e9194a2d
Auth Service
=============
### 登录认证接口说明
支持三种方式登录:
1.
账号密码+图片验证码
2.
手机号+短信验证码
3.
微信小程序code
#### 账号密码+图片验证码登录
POST:
`/api/auth/oauth/token?grant_type=password&scope=read&username=admin&credential=lBTqrKS0kZixOFXeZ0HRng==&randomStr=86111562225179514&code=mf3f`
url参数:
```
{
grant_type: password, // 固定为password
scope: read, // 固定为read
username: '', // 账号
credential: '', // 加密后的密码,加密算法在下面的密码加密部分
randomStr: '', // 随机数,生成算法在下面的随机数生成部分
code: '' // 验证码
}
```
1.
先生成随机数:randomStr
通过:
`/api/user/v1/code/${randomStr}`
获取验证码
2.
获取token
登录示例代码:
```
/**
* 登录
* @param identifier 账号
* @param credential 密码
* @param code 验证码
* @param randomStr 随机数
*/
export function loginByUsername (identifier, credential, code, randomStr) {
const grantType = 'password'
const scope = 'read'
return request({
url: '/api/auth/oauth/token',
headers: {
'Authorization': basicAuthorization
},
method: 'post',
params: {username: identifier, credential, randomStr, code, grant_type: grantType, scope}
})
}
```
其中:
1.
`const basicAuthorization = 'Basic ' + btoa('web_app:spring-microservice-exam-secret')`
2.
密码需要加密,具体看
**密码加密**
部分
3.
请求头要带
`Tenant-Code`
,即租户标识
#### 二 手机号+验证码登录
接口URL:
`/api/auth/mobile/token`
grant_type: mobile
#### 三 微信小程序+code登录
POST:
`/api/auth/wx/token?grant_type=wx&scope=read&code=`
+ code
其中grant_type、scope固定,code为wx.login返回的code
1.
请求头参数:
```
{
'Authorization': 'Basic d2ViX2FwcDpzcHJpbmctbWljcm9zZXJ2aWNlLWV4YW0tc2VjcmV0',
'Tenant-Code': 'gitee' // 租户标识,目前固定为gitee
}
```
Authorization为
`clientId:clientSecret`
的base64编码,即:
`'Basic ' + btoa('web_app:spring-microservice-exam-secret')`
2.
请求体参数:
```
{
name: userInfo.nickName,
sex: userInfo.gender, // 男:0,女:1
avatarUrl: userInfo.avatarUrl
}
```
3.
响应体:
```
{
access_token: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb2dpblR5cGUiOiJXWCIsInVzZXJfbmFtZSI6Im92TGw0NUluUm40SHpfanJwRWstZ0Yta0VGZjgiLCJzY29wZSI6WyJyZWFkIiwid3JpdGUiXSwidGVuYW50Q29kZSI6ImdpdGVlIiwiZXhwIjoxNTYyNDE1ODUxLCJhdXRob3JpdGllcyI6WyJyb2xlX3VzZXIiXSwianRpIjoiOWE4MzUxNzAtMDA4NS00MGU3LWEzZWQtNTkyODFmZThlYWVmIiwiY2xpZW50X2lkIjoid2ViX2FwcCJ9.WsL4fW4ZsiJqlb-Nvj9RMAgdimOFpR4925OtZDPw2AAKG8daIkRIH5HXb91mS6mdI7ldhtiwEV1Lo5Glka1T3DYYeWaZdLsuHt66JyzGTrunuIP7msXfHEfO5QmvoytX2RwbqaS4riBqcc5Oh-Fry8Negb1wc3nV0-zjVqepPFmdDyU0eGL3g6lZMSpi4QPZUlBV2VHqjHw4bf9M1Z1PbZZmJrEWiY48Zdsm-kaW-uwPo7FGi7jXHrnUI7dJgKXsuVyWi04LdwWy2vhohjl7tZd29q5Wr3kmj8nQf3EYiub_Tx9ielVEApgnNqMwLNnWgcX1YNd5nQcs0Ahf785p0w",
expires_in: 2287,
jti: "9a835170-0085-40e7-a3ed-59281fe8eaef",
loginType: "WX",
refresh_token: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb2dpblR5cGUiOiJXWCIsInVzZXJfbmFtZSI6Im92TGw0NUluUm40SHpfanJwRWstZ0Yta0VGZjgiLCJzY29wZSI6WyJyZWFkIiwid3JpdGUiXSwiYXRpIjoiOWE4MzUxNzAtMDA4NS00MGU3LWEzZWQtNTkyODFmZThlYWVmIiwidGVuYW50Q29kZSI6ImdpdGVlIiwiZXhwIjoxNTYyNDMzODUxLCJhdXRob3JpdGllcyI6WyJyb2xlX3VzZXIiXSwianRpIjoiNzQ4ZjFhNTMtZGRhYi00OGNjLWFhYzYtZWU5MzMzYzI0NWUyIiwiY2xpZW50X2lkIjoid2ViX2FwcCJ9.WRdOKI0Z2PX9IwxthEf_LSOWAyaz1AoM7T_ytkzlDuislSgMI6cZ7rJozMJdozfXa7xWl1swJ_r6-t2EoDC0gqDFnrIjmhgfJH6yIZSgWUQMTzXP29iHtkgRBvvDwPbDmHHRZjwV3eQvL6tFNJguBoywcCv81Ycy8tPBIWgbkbg98Fs--vbs0HznDHldf_Kzu_0_1Us0UkYPhN6YNJdlNfCxzSbXOrwuem-VIcw-yulw1s5-s_5sjqSRJ6HjVbwRyQrJizAmKkDN5YiSxf61fJDO2quUhc0DXY0OmKphL5EqlrgTCoQYCVoeYOLvcnUX5wIB3YdbP2WJiiYRrtx57g",
scope: "read write",
tenantCode: "gitee", // 租户标识
token_type: "bearer"
}
```
4.
登录示例代码:
```
// 登录
wx.login({
success: res => {
// 发送 res.code 到后台换取 openId, sessionKey, unionId
wx.request({
url: 'http://localhost:8000/api/auth/wx/token?grant_type=wx&scope=read&code=' + res.code,
header: {
'Authorization': 'Basic d2ViX2FwcDpzcHJpbmctbWljcm9zZXJ2aWNlLWV4YW0tc2VjcmV0',
'Tenant-Code': 'gitee'
},
method: 'POST',
data: {
name: userInfo.nickName,
sex: userInfo.gender,
avatarUrl: userInfo.avatarUrl
},
success (res) {
console.log(res.data)
}
})
}
})
```
#### 随机数生成
```
/**
* 生成随机len位数字
*/
export const randomLenNum = (len, date) => {
let random = ''
random = Math.ceil(Math.random() * 100000000000000).toString().substr(0, typeof len === 'number' ? len : 4)
if (date) random = random + Date.now()
return random
}
```
如生成4位长度的随机数: let randomStr = randomLenNum(4)
#### 密码加密
```
const user = encryption({
data: userInfo,
key: '1234567887654321',
param: ['credential']
})
```
```
/**
* 加密处理
*/
export const encryption = (params) => {
var {
data,
type,
param,
key
} = params
const result = JSON.parse(JSON.stringify(data))
if (type === 'Base64') {
param.forEach(ele => {
result[ele] = btoa(result[ele])
})
} else {
param.forEach(ele => {
var data = result[ele]
key = CryptoJS.enc.Latin1.parse(key)
var iv = key
var encrypted = CryptoJS.AES.encrypt(
data,
key,
{
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.ZeroPadding
})
result[ele] = encrypted.toString()
})
}
return result
}
```
\ No newline at end of file
service-api-impl/auth-service/pom.xml
View file @
e9194a2d
...
...
@@ -83,15 +83,10 @@
<artifactId>
mybatis-spring-boot-starter
</artifactId>
</dependency>
<!--
swagger
-->
<!--
微信小程序
-->
<dependency>
<groupId>
io.springfox
</groupId>
<artifactId>
springfox-swagger2
</artifactId>
</dependency>
<dependency>
<groupId>
io.springfox
</groupId>
<artifactId>
springfox-swagger-ui
</artifactId>
<groupId>
com.github.binarywang
</groupId>
<artifactId>
weixin-java-miniapp
</artifactId>
</dependency>
</dependencies>
...
...
service-api-impl/auth-service/src/main/java/com/github/tangyi/auth/config/SwaggerConfig.java
View file @
e9194a2d
package
com
.
github
.
tangyi
.
auth
.
config
;
import
com.github.tangyi.common.security.constant.SecurityConstant
;
import
io.swagger.annotations.ApiOperation
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
...
...
@@ -48,31 +49,32 @@ public class SwaggerConfig implements WebMvcConfigurer {
/**
* Authorization 请求头
*
* @return Parameter
*/
private
Parameter
authorizationParameter
()
{
ParameterBuilder
tokenBuilder
=
new
ParameterBuilder
();
tokenBuilder
.
name
(
"Authorization"
)
.
defaultValue
(
"bearer authorization参数"
)
.
description
(
"令牌"
)
.
description
(
"access_token"
)
.
modelRef
(
new
ModelRef
(
"string"
))
.
parameterType
(
"header"
)
.
required
(
tru
e
).
build
();
.
required
(
fals
e
).
build
();
return
tokenBuilder
.
build
();
}
/**
* Tenant-Code 请求头
*
* @return Parameter
*/
private
Parameter
tenantCodeParameter
()
{
ParameterBuilder
tokenBuilder
=
new
ParameterBuilder
();
tokenBuilder
.
name
(
"Tenant-Code"
)
.
defaultValue
(
"租户标识"
)
.
defaultValue
(
SecurityConstant
.
DEFAULT_TENANT_CODE
)
.
description
(
"租户标识"
)
.
modelRef
(
new
ModelRef
(
"string"
))
.
parameterType
(
"header"
)
.
required
(
tru
e
).
build
();
.
required
(
fals
e
).
build
();
return
tokenBuilder
.
build
();
}
...
...
service-api-impl/auth-service/src/main/java/com/github/tangyi/auth/config/WxConfig.java
0 → 100644
View file @
e9194a2d
package
com
.
github
.
tangyi
.
auth
.
config
;
import
cn.binarywang.wx.miniapp.api.WxMaService
;
import
cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl
;
import
cn.binarywang.wx.miniapp.config.WxMaConfig
;
import
cn.binarywang.wx.miniapp.config.WxMaInMemoryConfig
;
import
com.github.tangyi.auth.properties.WxProperties
;
import
lombok.AllArgsConstructor
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
/**
* 微信相关配置
*
* @author tangyi
* @date 2019/07/05 20:29
*/
@Configuration
@AllArgsConstructor
public
class
WxConfig
{
/**
* 微信的配置,如appId,appSecret,sessionHost
*/
private
final
WxProperties
wxProperties
;
@Bean
public
WxMaConfig
wxMaConfig
()
{
WxMaInMemoryConfig
config
=
new
WxMaInMemoryConfig
();
config
.
setAppid
(
wxProperties
.
getAppId
());
config
.
setSecret
(
wxProperties
.
getAppSecret
());
return
config
;
}
@Bean
public
WxMaService
wxMaService
(
WxMaConfig
maConfig
)
{
WxMaService
service
=
new
WxMaServiceImpl
();
service
.
setWxMaConfig
(
maConfig
);
return
service
;
}
}
service-api-impl/auth-service/src/main/java/com/github/tangyi/auth/controller/OauthClientDetailsController.java
View file @
e9194a2d
...
...
@@ -72,7 +72,7 @@ public class OauthClientDetailsController extends BaseController {
* @author tangyi
* @date 2019/03/30 16:54
*/
@
Reques
tMapping
(
"clientList"
)
@
Ge
tMapping
(
"clientList"
)
@ApiOperation
(
value
=
"获取客户端列表"
)
@ApiImplicitParams
({
@ApiImplicitParam
(
name
=
CommonConstant
.
PAGE_NUM
,
value
=
"分页页码"
,
defaultValue
=
CommonConstant
.
PAGE_NUM_DEFAULT
,
dataType
=
"String"
),
...
...
@@ -97,7 +97,7 @@ public class OauthClientDetailsController extends BaseController {
* @author tangyi
* @date 2019/03/30 23:17
*/
@
Reques
tMapping
(
"clients"
)
@
Ge
tMapping
(
"clients"
)
@ApiOperation
(
value
=
"查询客户端列表"
,
notes
=
"查询客户端列表"
)
@ApiImplicitParam
(
name
=
"oauthClient"
,
value
=
"客户端实体oauthClient"
,
required
=
true
,
dataType
=
"OauthClientDetails"
)
public
ResponseBean
<
List
<
OauthClientDetails
>>
findOauthClientList
(
@RequestBody
OauthClientDetails
oauthClientDetails
)
{
...
...
service-api-impl/auth-service/src/main/java/com/github/tangyi/auth/properties/WxProperties.java
0 → 100644
View file @
e9194a2d
package
com
.
github
.
tangyi
.
auth
.
properties
;
import
lombok.Data
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
org.springframework.context.annotation.Configuration
;
/**
* 微信配置
*
* @author tangyi
* @date 2019/07/04 20:25
*/
@Data
@Configuration
@ConfigurationProperties
(
prefix
=
"wx"
)
public
class
WxProperties
{
private
String
appId
;
private
String
appSecret
;
private
String
grantType
;
}
service-api-impl/auth-service/src/main/java/com/github/tangyi/auth/security/CustomTokenConverter.java
View file @
e9194a2d
...
...
@@ -30,6 +30,8 @@ public class CustomTokenConverter extends JwtAccessTokenConverter {
additionalInfo
.
put
(
"loginType"
,
LoginType
.
PWD
.
getType
());
}
else
if
(
grantType
.
equalsIgnoreCase
(
CommonConstant
.
GRANT_TYPE_MOBILE
))
{
additionalInfo
.
put
(
"loginType"
,
LoginType
.
SMS
.
getType
());
}
else
if
(
grantType
.
equalsIgnoreCase
(
LoginType
.
WECHAT
.
getType
()))
{
additionalInfo
.
put
(
"loginType"
,
LoginType
.
WECHAT
.
getType
());
}
((
DefaultOAuth2AccessToken
)
accessToken
).
setAdditionalInformation
(
additionalInfo
);
return
super
.
enhance
(
accessToken
,
authentication
);
...
...
service-api-impl/auth-service/src/main/java/com/github/tangyi/auth/security/CustomUserDetailsAuthenticationProvider.java
View file @
e9194a2d
...
...
@@ -70,7 +70,7 @@ public class CustomUserDetailsAuthenticationProvider extends AbstractUserDetails
UserDetails
loadedUser
;
try
{
// 加载用户信息
loadedUser
=
this
.
userDetailsService
.
loadUserBy
Username
AndTenantCode
(
authentication
.
getPrincipal
().
toString
(),
TenantContextHolder
.
getTenantCode
());
loadedUser
=
this
.
userDetailsService
.
loadUserBy
Identifier
AndTenantCode
(
authentication
.
getPrincipal
().
toString
(),
TenantContextHolder
.
getTenantCode
());
}
catch
(
TenantNotFoundException
tenantNotFound
)
{
throw
tenantNotFound
;
}
catch
(
UsernameNotFoundException
notFound
)
{
...
...
service-api-impl/auth-service/src/main/java/com/github/tangyi/auth/security/CustomUserDetailsServiceImpl.java
View file @
e9194a2d
package
com
.
github
.
tangyi
.
auth
.
security
;
import
com.github.tangyi.auth.api.module.WxSession
;
import
com.github.tangyi.auth.model.CustomUserDetails
;
import
com.github.tangyi.auth.
properties.SysProperties
;
import
com.github.tangyi.auth.
service.WxSessionService
;
import
com.github.tangyi.common.core.constant.CommonConstant
;
import
com.github.tangyi.common.core.exceptions.CommonException
;
import
com.github.tangyi.common.core.exceptions.TenantNotFoundException
;
import
com.github.tangyi.common.core.model.ResponseBean
;
import
com.github.tangyi.common.core.properties.SysProperties
;
import
com.github.tangyi.common.core.utils.DateUtils
;
import
com.github.tangyi.common.core.vo.RoleVo
;
import
com.github.tangyi.common.core.vo.UserVo
;
import
com.github.tangyi.common.security.core.CustomUserDetailsService
;
import
com.github.tangyi.common.security.core.GrantedAuthorityImpl
;
import
com.github.tangyi.common.security.wx.WxUser
;
import
com.github.tangyi.user.api.constant.MenuConstant
;
import
com.github.tangyi.user.api.dto.UserDto
;
import
com.github.tangyi.user.api.enums.IdentityType
;
import
com.github.tangyi.user.api.feign.UserServiceClient
;
import
com.github.tangyi.user.api.module.Menu
;
import
com.github.tangyi.user.api.module.Tenant
;
...
...
@@ -16,11 +24,13 @@ import com.google.common.collect.Lists;
import
lombok.AllArgsConstructor
;
import
org.apache.commons.collections4.CollectionUtils
;
import
org.apache.commons.lang.StringUtils
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.security.core.GrantedAuthority
;
import
org.springframework.security.core.userdetails.UserDetails
;
import
org.springframework.security.core.userdetails.UsernameNotFoundException
;
import
org.springframework.stereotype.Service
;
import
java.time.LocalDateTime
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Set
;
...
...
@@ -40,6 +50,8 @@ public class CustomUserDetailsServiceImpl implements CustomUserDetailsService {
private
final
SysProperties
sysProperties
;
private
final
WxSessionService
wxService
;
/**
* 加载用户信息
*
...
...
@@ -48,7 +60,7 @@ public class CustomUserDetailsServiceImpl implements CustomUserDetailsService {
* @throws UsernameNotFoundException,TenantNotFoundException
*/
@Override
public
UserDetails
loadUserBy
Username
AndTenantCode
(
String
username
,
String
tenantCode
)
throws
UsernameNotFoundException
,
TenantNotFoundException
{
public
UserDetails
loadUserBy
Identifier
AndTenantCode
(
String
username
,
String
tenantCode
)
throws
UsernameNotFoundException
,
TenantNotFoundException
{
Tenant
tenant
=
this
.
validateTenantCode
(
tenantCode
);
UserVo
userVo
=
userServiceClient
.
findUserByIdentifier
(
username
,
tenantCode
);
if
(
userVo
==
null
)
...
...
@@ -71,7 +83,54 @@ public class CustomUserDetailsServiceImpl implements CustomUserDetailsService {
UserVo
userVo
=
userServiceClient
.
findUserBySocial
(
social
,
tenantCode
);
if
(
userVo
==
null
)
throw
new
UsernameNotFoundException
(
"用户手机号未注册."
);
return
new
CustomUserDetails
(
social
,
userVo
.
getCredential
(),
CommonConstant
.
STATUS_NORMAL
.
equals
(
userVo
.
getStatus
()),
getAuthority
(
userVo
),
userVo
.
getTenantCode
());
return
new
CustomUserDetails
(
userVo
.
getIdentifier
(),
userVo
.
getCredential
(),
CommonConstant
.
STATUS_NORMAL
.
equals
(
userVo
.
getStatus
()),
getAuthority
(
userVo
),
userVo
.
getTenantCode
());
}
/**
* 根据微信code和租户标识查询
* 将code换成openId和sessionKey
*
* @param code code
* @param tenantCode tenantCode
* @param wxUser wxUser
* @return UserDetails
* @author tangyi
* @date 2019/07/05 20:05:36
*/
@Override
public
UserDetails
loadUserByWxCodeAndTenantCode
(
String
code
,
String
tenantCode
,
WxUser
wxUser
)
throws
UsernameNotFoundException
{
Tenant
tenant
=
this
.
validateTenantCode
(
tenantCode
);
// 根据code获取openId和sessionKey
WxSession
wxSession
=
wxService
.
code2Session
(
code
);
if
(
wxSession
==
null
)
throw
new
CommonException
(
"获取openId失败."
);
// 获取用户信息
UserVo
userVo
=
userServiceClient
.
findUserByIdentifier
(
wxSession
.
getOpenId
(),
IdentityType
.
WE_CHAT
.
getValue
(),
tenantCode
);
// 为空说明是第一次登录,需要将用户信息增加到数据库里
if
(
userVo
==
null
)
{
UserDto
userDto
=
new
UserDto
();
// 用户的基本信息
if
(
wxUser
!=
null
)
BeanUtils
.
copyProperties
(
wxUser
,
userDto
);
userDto
.
setIdentifier
(
wxSession
.
getOpenId
());
userDto
.
setCredential
(
wxSession
.
getOpenId
());
userDto
.
setIdentityType
(
IdentityType
.
WE_CHAT
.
getValue
());
userDto
.
setLoginTime
(
DateUtils
.
asDate
(
LocalDateTime
.
now
()));
// 注册账号
ResponseBean
<
Boolean
>
response
=
userServiceClient
.
registerUser
(
userDto
);
if
(
response
==
null
||
!
response
.
getData
())
throw
new
CommonException
(
"自动注册用户失败."
);
// 重新获取用户信息
userVo
=
userServiceClient
.
findUserByIdentifier
(
wxSession
.
getOpenId
(),
IdentityType
.
WE_CHAT
.
getValue
(),
tenantCode
);
}
else
{
// TODO 更新sessionKey,记录登录时间,IP等信息
UserDto
userDto
=
new
UserDto
();
BeanUtils
.
copyProperties
(
userVo
,
userDto
);
//userDto.setCredential(wxSession.getSessionKey());
userDto
.
setLoginTime
(
DateUtils
.
asDate
(
LocalDateTime
.
now
()));
//userServiceClient.updateUser(userDto);
}
return
new
CustomUserDetails
(
userVo
.
getIdentifier
(),
userVo
.
getCredential
(),
CommonConstant
.
STATUS_NORMAL
.
equals
(
userVo
.
getStatus
()),
getAuthority
(
userVo
),
userVo
.
getTenantCode
());
}
/**
...
...
service-api-impl/auth-service/src/main/java/com/github/tangyi/auth/service/WxSessionService.java
0 → 100644
View file @
e9194a2d
package
com
.
github
.
tangyi
.
auth
.
service
;
import
cn.binarywang.wx.miniapp.api.WxMaService
;
import
cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult
;
import
com.github.tangyi.auth.api.module.WxSession
;
import
lombok.AllArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.stereotype.Service
;
/**
* 微信Service
*
* @author tangyi
* @date 2019/07/05 20:33
*/
@Slf4j
@AllArgsConstructor
@Service
public
class
WxSessionService
{
private
final
WxMaService
wxMaService
;
/**
* 根据code获取WxSession
*
* @param code code
* @return WxSession
* @author tangyi
* @date 2019/07/05 20:37:02
*/
public
WxSession
getSession
(
String
code
)
{
WxSession
session
=
null
;
try
{
WxMaJscode2SessionResult
result
=
wxMaService
.
getUserService
().
getSessionInfo
(
code
);
session
=
new
WxSession
(
result
.
getOpenid
(),
result
.
getSessionKey
());
log
.
info
(
"获取wx session成功,openId: {}, sessionKey: {}"
,
session
.
getOpenId
(),
session
.
getSessionKey
());
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
}
return
session
;
}
/**
* 根据code获取WxSession
*
* @param code code
* @return WxSession
* @author tangyi
* @date 2019/07/06 14:01:13
*/
public
WxSession
code2Session
(
String
code
)
{
WxSession
session
=
null
;
try
{
WxMaJscode2SessionResult
result
=
wxMaService
.
jsCode2SessionInfo
(
code
);
session
=
new
WxSession
(
result
.
getOpenid
(),
result
.
getSessionKey
());
log
.
info
(
"获取wx session成功,openId: {}, sessionKey: {}"
,
session
.
getOpenId
(),
session
.
getSessionKey
());
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
}
return
session
;
}
}
service-api-impl/exam-service/pom.xml
View file @
e9194a2d
...
...
@@ -77,17 +77,6 @@
<groupId>
org.mybatis.spring.boot
</groupId>
<artifactId>
mybatis-spring-boot-starter
</artifactId>
</dependency>
<!-- swagger -->
<dependency>
<groupId>
io.springfox
</groupId>
<artifactId>
springfox-swagger2
</artifactId>
</dependency>
<dependency>
<groupId>
io.springfox
</groupId>
<artifactId>
springfox-swagger-ui
</artifactId>
</dependency>
</dependencies>
<build>
...
...
service-api-impl/exam-service/src/main/java/com/github/tangyi/exam/config/SwaggerConfig.java
View file @
e9194a2d
package
com
.
github
.
tangyi
.
exam
.
config
;
import
com.github.tangyi.common.security.constant.SecurityConstant
;
import
io.swagger.annotations.ApiOperation
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
...
...
@@ -48,31 +49,32 @@ public class SwaggerConfig implements WebMvcConfigurer {
/**
* Authorization 请求头
*
* @return Parameter
*/
private
Parameter
authorizationParameter
()
{
ParameterBuilder
tokenBuilder
=
new
ParameterBuilder
();
tokenBuilder
.
name
(
"Authorization"
)
.
defaultValue
(
"bearer authorization参数"
)
.
description
(
"令牌"
)
.
description
(
"access_token"
)
.
modelRef
(
new
ModelRef
(
"string"
))
.
parameterType
(
"header"
)
.
required
(
tru
e
).
build
();
.
required
(
fals
e
).
build
();
return
tokenBuilder
.
build
();
}
/**
* Tenant-Code 请求头
*
* @return Parameter
*/
private
Parameter
tenantCodeParameter
()
{
ParameterBuilder
tokenBuilder
=
new
ParameterBuilder
();
tokenBuilder
.
name
(
"Tenant-Code"
)
.
defaultValue
(
"租户标识"
)
.
defaultValue
(
SecurityConstant
.
DEFAULT_TENANT_CODE
)
.
description
(
"租户标识"
)
.
modelRef
(
new
ModelRef
(
"string"
))
.
parameterType
(
"header"
)
.
required
(
tru
e
).
build
();
.
required
(
fals
e
).
build
();
return
tokenBuilder
.
build
();
}
...
...
service-api-impl/exam-service/src/main/java/com/github/tangyi/exam/controller/AnswerController.java
View file @
e9194a2d
...
...
@@ -73,7 +73,7 @@ public class AnswerController extends BaseController {
* @author tangyi
* @date 2018/11/10 21:25
*/
@
Reques
tMapping
(
"answerList"
)
@
Ge
tMapping
(
"answerList"
)
@ApiOperation
(
value
=
"获取答题列表"
)
@ApiImplicitParams
({
@ApiImplicitParam
(
name
=
CommonConstant
.
PAGE_NUM
,
value
=
"分页页码"
,
defaultValue
=
CommonConstant
.
PAGE_NUM_DEFAULT
,
dataType
=
"String"
),
...
...
service-api-impl/exam-service/src/main/java/com/github/tangyi/exam/controller/CourseController.java
View file @
e9194a2d
...
...
@@ -66,7 +66,7 @@ public class CourseController extends BaseController {
* @author tangyi
* @date 2018/11/10 21:30
*/
@
Reques
tMapping
(
"courseList"
)
@
Ge
tMapping
(
"courseList"
)
@ApiOperation
(
value
=
"获取课程列表"
)
@ApiImplicitParams
({
@ApiImplicitParam
(
name
=
CommonConstant
.
PAGE_NUM
,
value
=
"分页页码"
,
defaultValue
=
CommonConstant
.
PAGE_NUM_DEFAULT
,
dataType
=
"String"
),
...
...
service-api-impl/exam-service/src/main/java/com/github/tangyi/exam/controller/ExamRecordController.java
View file @
e9194a2d
...
...
@@ -91,7 +91,7 @@ public class ExamRecordController extends BaseController {
* @author tangyi
* @date 2018/11/10 21:33
*/
@
Reques
tMapping
(
"examRecordList"
)
@
Ge
tMapping
(
"examRecordList"
)
@ApiOperation
(
value
=
"获取考试记录列表"
)
@ApiImplicitParams
({
@ApiImplicitParam
(
name
=
CommonConstant
.
PAGE_NUM
,
value
=
"分页页码"
,
defaultValue
=
CommonConstant
.
PAGE_NUM_DEFAULT
,
dataType
=
"String"
),
...
...
service-api-impl/exam-service/src/main/java/com/github/tangyi/exam/controller/ExaminationController.java
View file @
e9194a2d
...
...
@@ -77,7 +77,7 @@ public class ExaminationController extends BaseController {
* @author tangyi
* @date 2018/11/10 21:10
*/
@
Reques
tMapping
(
"examinationList"
)
@
Ge
tMapping
(
"examinationList"
)
@ApiOperation
(
value
=
"获取考试列表"
)
@ApiImplicitParams
({
@ApiImplicitParam
(
name
=
CommonConstant
.
PAGE_NUM
,
value
=
"分页页码"
,
defaultValue
=
CommonConstant
.
PAGE_NUM_DEFAULT
,
dataType
=
"String"
),
...
...
service-api-impl/exam-service/src/main/java/com/github/tangyi/exam/controller/KnowledgeController.java
View file @
e9194a2d
...
...
@@ -75,7 +75,7 @@ public class KnowledgeController extends BaseController {
* @author tangyi
* @date 2019/1/1 15:15
*/
@
Reques
tMapping
(
"knowledgeList"
)
@
Ge
tMapping
(
"knowledgeList"
)
@ApiOperation
(
value
=
"获取知识列表"
)
@ApiImplicitParams
({
@ApiImplicitParam
(
name
=
CommonConstant
.
PAGE_NUM
,
value
=
"分页页码"
,
defaultValue
=
CommonConstant
.
PAGE_NUM_DEFAULT
,
dataType
=
"String"
),
...
...
service-api-impl/exam-service/src/main/java/com/github/tangyi/exam/controller/SubjectController.java
View file @
e9194a2d
...
...
@@ -80,7 +80,7 @@ public class SubjectController extends BaseController {
* @author tangyi
* @date 2018/11/10 21:43
*/
@
Reques
tMapping
(
"subjectList"
)
@
Ge
tMapping
(
"subjectList"
)
@ApiOperation
(
value
=
"获取题目列表"
)
@ApiImplicitParams
({
@ApiImplicitParam
(
name
=
CommonConstant
.
PAGE_NUM
,
value
=
"分页页码"
,
defaultValue
=
CommonConstant
.
PAGE_NUM_DEFAULT
,
dataType
=
"String"
),
...
...
service-api-impl/exam-service/src/main/java/com/github/tangyi/exam/error/CustomGlobalExceptionHandler.java
View file @
e9194a2d
...
...
@@ -56,6 +56,10 @@ public class CustomGlobalExceptionHandler extends ResponseEntityExceptionHandler
*/
@ExceptionHandler
(
CommonException
.
class
)
public
ResponseEntity
<
ResponseBean
<
String
>>
handleCommonException
(
Exception
e
)
{
return
new
ResponseEntity
<>(
new
ResponseBean
<>(
e
.
getMessage
()),
HttpStatus
.
INTERNAL_SERVER_ERROR
);
ResponseBean
<
String
>
responseBean
=
new
ResponseBean
<>();
responseBean
.
setStatus
(
HttpStatus
.
INTERNAL_SERVER_ERROR
.
value
());
responseBean
.
setCode
(
HttpStatus
.
INTERNAL_SERVER_ERROR
.
value
());
responseBean
.
setMsg
(
e
.
getMessage
());
return
new
ResponseEntity
<>(
responseBean
,
HttpStatus
.
INTERNAL_SERVER_ERROR
);
}
}
service-api-impl/msc-service/pom.xml
View file @
e9194a2d
...
...
@@ -42,17 +42,6 @@
<artifactId>
spring-boot-admin-starter-client
</artifactId>
</dependency>
<!-- swagger -->
<dependency>
<groupId>
io.springfox
</groupId>
<artifactId>
springfox-swagger2
</artifactId>
</dependency>
<dependency>
<groupId>
io.springfox
</groupId>
<artifactId>
springfox-swagger-ui
</artifactId>
</dependency>
<!-- aliyun -->
<dependency>
<groupId>
com.aliyun
</groupId>
...
...
service-api-impl/msc-service/src/main/java/com/github/tangyi/msc/config/SwaggerConfig.java
View file @
e9194a2d
package
com
.
github
.
tangyi
.
msc
.
config
;
import
com.github.tangyi.common.security.constant.SecurityConstant
;
import
io.swagger.annotations.ApiOperation
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
...
...
@@ -48,31 +49,32 @@ public class SwaggerConfig implements WebMvcConfigurer {
/**
* Authorization 请求头
*
* @return Parameter
*/
private
Parameter
authorizationParameter
()
{
ParameterBuilder
tokenBuilder
=
new
ParameterBuilder
();
tokenBuilder
.
name
(
"Authorization"
)
.
defaultValue
(
"bearer authorization参数"
)
.
description
(
"令牌"
)
.
description
(
"access_token"
)
.
modelRef
(
new
ModelRef
(
"string"
))
.
parameterType
(
"header"
)
.
required
(
tru
e
).
build
();
.
required
(
fals
e
).
build
();
return
tokenBuilder
.
build
();
}
/**
* Tenant-Code 请求头
*
* @return Parameter
*/
private
Parameter
tenantCodeParameter
()
{
ParameterBuilder
tokenBuilder
=
new
ParameterBuilder
();
tokenBuilder
.
name
(
"Tenant-Code"
)
.
defaultValue
(
"租户标识"
)
.
defaultValue
(
SecurityConstant
.
DEFAULT_TENANT_CODE
)
.
description
(
"租户标识"
)
.
modelRef
(
new
ModelRef
(
"string"
))
.
parameterType
(
"header"
)
.
required
(
tru
e
).
build
();
.
required
(
fals
e
).
build
();
return
tokenBuilder
.
build
();
}
...
...
service-api-impl/user-service/pom.xml
View file @
e9194a2d
...
...
@@ -83,17 +83,6 @@
<groupId>
com.github.axet
</groupId>
<artifactId>
kaptcha
</artifactId>
</dependency>
<!-- swagger -->
<dependency>
<groupId>
io.springfox
</groupId>
<artifactId>
springfox-swagger2
</artifactId>
</dependency>
<dependency>
<groupId>
io.springfox
</groupId>
<artifactId>
springfox-swagger-ui
</artifactId>
</dependency>
</dependencies>
<build>
...
...
service-api-impl/user-service/src/main/java/com/github/tangyi/user/config/SwaggerConfig.java
View file @
e9194a2d
package
com
.
github
.
tangyi
.
user
.
config
;
import
com.github.tangyi.common.security.constant.SecurityConstant
;
import
io.swagger.annotations.ApiOperation
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
...
...
@@ -48,31 +49,32 @@ public class SwaggerConfig implements WebMvcConfigurer {
/**
* Authorization 请求头
*
* @return Parameter
*/
private
Parameter
authorizationParameter
()
{
ParameterBuilder
tokenBuilder
=
new
ParameterBuilder
();
tokenBuilder
.
name
(
"Authorization"
)
.
defaultValue
(
"bearer authorization参数"
)
.
description
(
"令牌"
)
.
description
(
"access_token"
)
.
modelRef
(
new
ModelRef
(
"string"
))
.
parameterType
(
"header"
)
.
required
(
tru
e
).
build
();
.
required
(
fals
e
).
build
();
return
tokenBuilder
.
build
();
}
/**
* Tenant-Code 请求头
*
* @return Parameter
*/
private
Parameter
tenantCodeParameter
()
{
ParameterBuilder
tokenBuilder
=
new
ParameterBuilder
();
tokenBuilder
.
name
(
"Tenant-Code"
)
.
defaultValue
(
"租户标识"
)
.
defaultValue
(
SecurityConstant
.
DEFAULT_TENANT_CODE
)
.
description
(
"租户标识"
)
.
modelRef
(
new
ModelRef
(
"string"
))
.
parameterType
(
"header"
)
.
required
(
tru
e
).
build
();
.
required
(
fals
e
).
build
();
return
tokenBuilder
.
build
();
}
...
...
service-api-impl/user-service/src/main/java/com/github/tangyi/user/controller/AttachmentController.java
View file @
e9194a2d
...
...
@@ -76,7 +76,7 @@ public class AttachmentController extends BaseController {
* @author tangyi
* @date 2018/10/30 21:05
*/
@
Reques
tMapping
(
"attachmentList"
)
@
Ge
tMapping
(
"attachmentList"
)
@ApiOperation
(
value
=
"获取附件列表"
)
@ApiImplicitParams
({
@ApiImplicitParam
(
name
=
CommonConstant
.
PAGE_NUM
,
value
=
"分页页码"
,
defaultValue
=
CommonConstant
.
PAGE_NUM_DEFAULT
,
dataType
=
"String"
),
...
...
@@ -102,7 +102,7 @@ public class AttachmentController extends BaseController {
* @author tangyi
* @date 2018/10/30 21:54
*/
@
Reque
stMapping
(
"upload"
)
@
Po
stMapping
(
"upload"
)
@ApiOperation
(
value
=
"上传文件"
,
notes
=
"上传文件"
)
@ApiImplicitParams
({
@ApiImplicitParam
(
name
=
"busiType"
,
value
=
"业务分类"
,
dataType
=
"String"
),
...
...
@@ -124,7 +124,7 @@ public class AttachmentController extends BaseController {
* @author tangyi
* @date 2018/10/30 22:26
*/
@
Reques
tMapping
(
"download"
)
@
Ge
tMapping
(
"download"
)
@ApiOperation
(
value
=
"下载附件"
,
notes
=
"根据ID下载附件"
)
@ApiImplicitParam
(
name
=
"id"
,
value
=
"附件ID"
,
required
=
true
,
dataType
=
"String"
)
public
void
download
(
@NotBlank
String
id
,
HttpServletRequest
request
,
HttpServletResponse
response
)
{
...
...
@@ -207,7 +207,7 @@ public class AttachmentController extends BaseController {
* @author tangyi
* @date 2019/01/01 22:16
*/
@
RequestMapping
(
value
=
"findById"
,
method
=
RequestMethod
.
POST
)
@
PostMapping
(
value
=
"findById"
)
@ApiOperation
(
value
=
"批量查询附件信息"
,
notes
=
"根据附件ID批量查询附件信息"
)
@ApiImplicitParam
(
name
=
"attachmentVo"
,
value
=
"附件信息"
,
dataType
=
"AttachmentVo"
)
public
ResponseBean
<
List
<
AttachmentVo
>>
findById
(
@RequestBody
AttachmentVo
attachmentVo
)
{
...
...
service-api-impl/user-service/src/main/java/com/github/tangyi/user/controller/LogController.java
View file @
e9194a2d
...
...
@@ -68,7 +68,7 @@ public class LogController extends BaseController {
* @author tangyi
* @date 2018/10/24 0024 22:13
*/
@
Reques
tMapping
(
"logList"
)
@
Ge
tMapping
(
"logList"
)
@ApiOperation
(
value
=
"获取日志列表"
)
@ApiImplicitParams
({
@ApiImplicitParam
(
name
=
CommonConstant
.
PAGE_NUM
,
value
=
"分页页码"
,
defaultValue
=
CommonConstant
.
PAGE_NUM_DEFAULT
,
dataType
=
"String"
),
...
...
service-api-impl/user-service/src/main/java/com/github/tangyi/user/controller/MenuController.java
View file @
e9194a2d
...
...
@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
import
com.github.pagehelper.PageInfo
;
import
com.github.tangyi.common.core.constant.CommonConstant
;
import
com.github.tangyi.common.core.model.ResponseBean
;
import
com.github.tangyi.common.core.properties.SysProperties
;
import
com.github.tangyi.common.core.utils.*
;
import
com.github.tangyi.common.core.vo.MenuVo
;
import
com.github.tangyi.common.core.web.BaseController
;
...
...
@@ -14,7 +15,6 @@ import com.github.tangyi.user.api.constant.MenuConstant;
import
com.github.tangyi.user.api.dto.MenuDto
;
import
com.github.tangyi.user.api.module.Menu
;
import
com.github.tangyi.user.api.module.Role
;
import
com.github.tangyi.user.config.SysConfig
;
import
com.github.tangyi.user.service.MenuService
;
import
com.github.tangyi.user.utils.MenuUtil
;
import
com.google.common.collect.Lists
;
...
...
@@ -55,7 +55,7 @@ public class MenuController extends BaseController {
private
final
MenuService
menuService
;
private
final
Sys
Config
sysConfig
;
private
final
Sys
Properties
sysProperties
;
/**
* 返回当前用户的树形菜单集合
...
...
@@ -69,7 +69,7 @@ public class MenuController extends BaseController {
String
tenantCode
=
SysUtil
.
getTenantCode
(),
identifier
=
SysUtil
.
getUser
();
List
<
Menu
>
userMenus
;
// 超级管理员
if
(
identifier
.
equals
(
sys
Config
.
getAdminUser
()))
{
if
(
identifier
.
equals
(
sys
Properties
.
getAdminUser
()))
{
// 获取角色的菜单
Menu
menu
=
new
Menu
();
menu
.
setTenantCode
(
tenantCode
);
...
...
@@ -209,7 +209,7 @@ public class MenuController extends BaseController {
* @author tangyi
* @date 2018/8/26 23:17
*/
@
Reques
tMapping
(
"menuList"
)
@
Ge
tMapping
(
"menuList"
)
@ApiOperation
(
value
=
"获取菜单列表"
)
@ApiImplicitParams
({
@ApiImplicitParam
(
name
=
CommonConstant
.
PAGE_NUM
,
value
=
"分页页码"
,
defaultValue
=
CommonConstant
.
PAGE_NUM_DEFAULT
,
dataType
=
"String"
),
...
...
@@ -324,7 +324,7 @@ public class MenuController extends BaseController {
* @author tangyi
* @date 2018/11/28 12:51
*/
@
Reque
stMapping
(
"import"
)
@
Po
stMapping
(
"import"
)
@PreAuthorize
(
"hasAuthority('sys:menu:import') or hasAnyRole('"
+
SecurityConstant
.
ROLE_ADMIN
+
"')"
)
@ApiOperation
(
value
=
"导入菜单"
,
notes
=
"导入菜单"
)
@Log
(
"导入菜单"
)
...
...
service-api-impl/user-service/src/main/java/com/github/tangyi/user/controller/MobileController.java
View file @
e9194a2d
...
...
@@ -5,6 +5,8 @@ import com.github.tangyi.common.core.web.BaseController;
import
com.github.tangyi.common.security.constant.SecurityConstant
;
import
com.github.tangyi.user.service.MobileService
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiImplicitParam
;
import
io.swagger.annotations.ApiOperation
;
import
lombok.AllArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.web.bind.annotation.*
;
...
...
@@ -34,6 +36,8 @@ public class MobileController extends BaseController {
* @date 2019/07/02 09:49:05
*/
@GetMapping
(
"sendSms/{mobile}"
)
@ApiOperation
(
value
=
"发送短信"
,
notes
=
"发送短信到指定的手机号"
)
@ApiImplicitParam
(
name
=
"mobile"
,
value
=
"mobile"
,
required
=
true
,
dataType
=
"String"
,
paramType
=
"path"
)
public
ResponseBean
<
Boolean
>
sendSms
(
@PathVariable
String
mobile
,
@RequestHeader
(
SecurityConstant
.
TENANT_CODE_HEADER
)
String
tenantCode
)
{
return
mobileService
.
sendSms
(
mobile
,
tenantCode
);
}
...
...
service-api-impl/user-service/src/main/java/com/github/tangyi/user/controller/RoleController.java
View file @
e9194a2d
...
...
@@ -75,7 +75,7 @@ public class RoleController extends BaseController {
* @author tangyi
* @date 2018/10/24 22:13
*/
@
Reques
tMapping
(
"roleList"
)
@
Ge
tMapping
(
"roleList"
)
@ApiOperation
(
value
=
"获取角色列表"
)
@ApiImplicitParams
({
@ApiImplicitParam
(
name
=
CommonConstant
.
PAGE_NUM
,
value
=
"分页页码"
,
defaultValue
=
CommonConstant
.
PAGE_NUM_DEFAULT
,
dataType
=
"String"
),
...
...
@@ -101,7 +101,7 @@ public class RoleController extends BaseController {
* @author tangyi
* @date 2019/05/15 23:29
*/
@
Reques
tMapping
(
"allRoles"
)
@
Ge
tMapping
(
"allRoles"
)
@ApiOperation
(
value
=
"获取全部角色列表"
)
@ApiImplicitParam
(
name
=
"role"
,
value
=
"角色信息"
,
dataType
=
"RoleVo"
)
public
ResponseBean
<
List
<
Role
>>
allRoles
(
Role
role
)
{
...
...
service-api-impl/user-service/src/main/java/com/github/tangyi/user/controller/RouteController.java
View file @
e9194a2d
...
...
@@ -77,7 +77,7 @@ public class RouteController extends BaseController {
* @author tangyi
* @date 2019/4/2 15:09
*/
@
Reques
tMapping
(
"routeList"
)
@
Ge
tMapping
(
"routeList"
)
@ApiOperation
(
value
=
"获取路由列表"
)
@ApiImplicitParams
({
@ApiImplicitParam
(
name
=
CommonConstant
.
PAGE_NUM
,
value
=
"分页页码"
,
defaultValue
=
CommonConstant
.
PAGE_NUM_DEFAULT
,
dataType
=
"String"
),
...
...
service-api-impl/user-service/src/main/java/com/github/tangyi/user/controller/SysConfigController.java
View file @
e9194a2d
package
com
.
github
.
tangyi
.
user
.
controller
;
import
com.github.tangyi.common.core.dto.SysConfigDto
;
import
com.github.tangyi.common.core.model.ResponseBean
;
import
com.github.tangyi.common.core.properties.SysProperties
;
import
com.github.tangyi.common.core.web.BaseController
;
import
com.github.tangyi.user.config.SysConfig
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
lombok.AllArgsConstructor
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
...
...
@@ -22,7 +24,7 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping
(
"/v1/sysConfig"
)
public
class
SysConfigController
extends
BaseController
{
private
final
Sys
Config
sysConfig
;
private
final
Sys
Properties
sysProperties
;
/**
* 获取系统配置
...
...
@@ -33,7 +35,9 @@ public class SysConfigController extends BaseController {
*/
@GetMapping
@ApiOperation
(
value
=
"获取系统配置"
,
notes
=
"获取系统配置"
)
public
ResponseBean
<
SysConfig
>
getSysConfig
()
{
return
new
ResponseBean
<>(
sysConfig
);
public
ResponseBean
<
SysConfigDto
>
getSysConfig
()
{
SysConfigDto
sysConfigDto
=
new
SysConfigDto
();
BeanUtils
.
copyProperties
(
sysProperties
,
sysConfigDto
);
return
new
ResponseBean
<>(
sysConfigDto
);
}
}
service-api-impl/user-service/src/main/java/com/github/tangyi/user/controller/TenantController.java
View file @
e9194a2d
...
...
@@ -80,7 +80,7 @@ public class TenantController extends BaseController {
* @author tangyi
* @date 2019/05/22 23:29
*/
@
Reques
tMapping
(
"tenantList"
)
@
Ge
tMapping
(
"tenantList"
)
@ApiOperation
(
value
=
"获取租户列表"
)
@ApiImplicitParams
({
@ApiImplicitParam
(
name
=
CommonConstant
.
PAGE_NUM
,
value
=
"分页页码"
,
defaultValue
=
CommonConstant
.
PAGE_NUM_DEFAULT
,
dataType
=
"String"
),
...
...
service-api-impl/user-service/src/main/java/com/github/tangyi/user/controller/UserController.java
View file @
e9194a2d
...
...
@@ -118,7 +118,7 @@ public class UserController extends BaseController {
* @author tangyi
* @date 2018/8/26 22:56
*/
@
Reques
tMapping
(
"userList"
)
@
Ge
tMapping
(
"userList"
)
@ApiOperation
(
value
=
"获取用户列表"
)
@ApiImplicitParams
({
@ApiImplicitParam
(
name
=
CommonConstant
.
PAGE_NUM
,
value
=
"分页页码"
,
defaultValue
=
CommonConstant
.
PAGE_NUM_DEFAULT
,
dataType
=
"String"
),
...
...
@@ -331,7 +331,7 @@ public class UserController extends BaseController {
* @author tangyi
* @date 2018/11/28 12:44
*/
@
Reque
stMapping
(
"import"
)
@
Po
stMapping
(
"import"
)
@PreAuthorize
(
"hasAuthority('sys:user:import') or hasAnyRole('"
+
SecurityConstant
.
ROLE_ADMIN
+
"')"
)
@ApiOperation
(
value
=
"导入数据"
,
notes
=
"导入数据"
)
@Log
(
"导入用户"
)
...
...
@@ -382,7 +382,7 @@ public class UserController extends BaseController {
* @author tangyi
* @date 2018/12/31 21:16
*/
@
RequestMapping
(
value
=
"findById"
,
method
=
RequestMethod
.
POST
)
@
PostMapping
(
value
=
"findById"
)
@ApiOperation
(
value
=
"根据ID查询用户"
,
notes
=
"根据ID查询用户"
)
@ApiImplicitParam
(
name
=
"userVo"
,
value
=
"用户信息"
,
required
=
true
,
paramType
=
"UserVo"
)
public
ResponseBean
<
List
<
UserVo
>>
findById
(
@RequestBody
UserVo
userVo
)
{
...
...
@@ -398,10 +398,15 @@ public class UserController extends BaseController {
* @date 2019/01/10 22:35
*/
@ApiOperation
(
value
=
"注册"
,
notes
=
"注册"
)
@ApiImplicitParam
(
name
=
"userDto"
,
value
=
"用户实体user"
,
required
=
true
,
dataType
=
"UserDto"
)
@ApiImplicitParams
({
@ApiImplicitParam
(
name
=
"grant_type"
,
value
=
"授权类型(password、mobile)"
,
required
=
true
,
defaultValue
=
"password"
,
dataType
=
"String"
,
paramType
=
"query"
),
@ApiImplicitParam
(
name
=
"code"
,
value
=
"验证码"
,
required
=
true
,
dataType
=
"String"
,
paramType
=
"query"
),
@ApiImplicitParam
(
name
=
"randomStr"
,
value
=
"随机数"
,
dataType
=
"String"
,
paramType
=
"query"
),
@ApiImplicitParam
(
name
=
"mobile"
,
value
=
"手机号"
,
dataType
=
"String"
,
paramType
=
"query"
)
})
@PostMapping
(
"register"
)
@Log
(
"注册用户"
)
public
ResponseBean
<
Boolean
>
register
(
@Valid
UserDto
userDto
)
{
public
ResponseBean
<
Boolean
>
register
(
@
RequestBody
@
Valid
UserDto
userDto
)
{
return
new
ResponseBean
<>(
userService
.
register
(
userDto
));
}
...
...
service-api-impl/user-service/src/main/java/com/github/tangyi/user/controller/ValidateCodeController.java
View file @
e9194a2d
...
...
@@ -42,8 +42,7 @@ public class ValidateCodeController extends BaseController {
*/
@ApiOperation
(
value
=
"生成验证码"
,
notes
=
"生成验证码"
)
@ApiImplicitParams
({
@ApiImplicitParam
(
name
=
"random"
,
value
=
"随机数"
,
required
=
true
,
dataType
=
"String"
,
paramType
=
"path"
),
@ApiImplicitParam
(
name
=
"tenantCode"
,
value
=
"租户标识"
,
required
=
true
,
dataType
=
"String"
)
@ApiImplicitParam
(
name
=
"random"
,
value
=
"随机数"
,
required
=
true
,
dataType
=
"String"
,
paramType
=
"path"
)
})
@GetMapping
(
"/{random}"
)
public
void
produceCode
(
@PathVariable
String
random
,
@RequestParam
(
required
=
false
,
defaultValue
=
SecurityConstant
.
DEFAULT_TENANT_CODE
)
String
tenantCode
,
HttpServletResponse
response
)
throws
Exception
{
...
...
service-api-impl/user-service/src/main/java/com/github/tangyi/user/error/CustomGlobalExceptionHandler.java
View file @
e9194a2d
...
...
@@ -56,6 +56,10 @@ public class CustomGlobalExceptionHandler extends ResponseEntityExceptionHandler
*/
@ExceptionHandler
(
CommonException
.
class
)
public
ResponseEntity
<
ResponseBean
<
String
>>
handleCommonException
(
Exception
e
)
{
return
new
ResponseEntity
<>(
new
ResponseBean
<>(
e
.
getMessage
()),
HttpStatus
.
INTERNAL_SERVER_ERROR
);
ResponseBean
<
String
>
responseBean
=
new
ResponseBean
<>();
responseBean
.
setStatus
(
HttpStatus
.
INTERNAL_SERVER_ERROR
.
value
());
responseBean
.
setCode
(
HttpStatus
.
INTERNAL_SERVER_ERROR
.
value
());
responseBean
.
setMsg
(
e
.
getMessage
());
return
new
ResponseEntity
<>(
responseBean
,
HttpStatus
.
INTERNAL_SERVER_ERROR
);
}
}
service-api-impl/user-service/src/main/java/com/github/tangyi/user/service/AttachmentService.java
View file @
e9194a2d
package
com
.
github
.
tangyi
.
user
.
service
;
import
com.github.tangyi.common.core.exceptions.CommonException
;
import
com.github.tangyi.common.core.properties.SysProperties
;
import
com.github.tangyi.common.core.service.CrudService
;
import
com.github.tangyi.common.core.utils.FileUtil
;
import
com.github.tangyi.common.core.utils.SysUtil
;
import
com.github.tangyi.user.api.module.Attachment
;
import
com.github.tangyi.user.config.SysConfig
;
import
com.github.tangyi.user.mapper.AttachmentMapper
;
import
lombok.AllArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
...
...
@@ -31,7 +31,7 @@ public class AttachmentService extends CrudService<AttachmentMapper, Attachment>
private
final
FastDfsService
fastDfsService
;
private
final
Sys
Config
sysConfig
;
private
final
Sys
Properties
sysProperties
;
/**
* 根据id查询
...
...
@@ -147,7 +147,7 @@ public class AttachmentService extends CrudService<AttachmentMapper, Attachment>
throw
new
CommonException
(
"附件不存在."
);
String
preview
=
attachment
.
getPreviewUrl
();
if
(
StringUtils
.
isBlank
(
preview
))
preview
=
sys
Config
.
getFdfsHttpHost
()
+
"/"
+
attachment
.
getFastFileId
();
preview
=
sys
Properties
.
getFdfsHttpHost
()
+
"/"
+
attachment
.
getFastFileId
();
log
.
debug
(
"id为:{}的附件的预览地址:{}"
,
attachment
.
getId
(),
preview
);
return
preview
;
}
...
...
service-api-impl/user-service/src/main/java/com/github/tangyi/user/service/MobileService.java
View file @
e9194a2d
...
...
@@ -3,13 +3,12 @@ package com.github.tangyi.user.service;
import
cn.hutool.core.util.RandomUtil
;
import
com.github.tangyi.common.core.constant.CommonConstant
;
import
com.github.tangyi.common.core.enums.LoginType
;
import
com.github.tangyi.common.core.exceptions.CommonException
;
import
com.github.tangyi.common.core.model.ResponseBean
;
import
com.github.tangyi.common.core.vo.UserVo
;
import
com.github.tangyi.common.security.constant.SecurityConstant
;
import
com.github.tangyi.msc.api.constant.SmsConstant
;
import
com.github.tangyi.msc.api.dto.SmsDto
;
import
com.github.tangyi.msc.api.feign.MscServiceClient
;
import
com.github.tangyi.user.api.enums.IdentityType
;
import
lombok.AllArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.data.redis.core.RedisTemplate
;
...
...
@@ -44,11 +43,6 @@ public class MobileService {
* @date 2019/07/02 09:36:52
*/
public
ResponseBean
<
Boolean
>
sendSms
(
String
mobile
,
String
tenantCode
)
{
UserVo
userVo
=
userService
.
findUserByIdentifier
(
IdentityType
.
PHONE_NUMBER
.
getValue
(),
mobile
,
tenantCode
);
if
(
userVo
==
null
)
{
log
.
info
(
"手机号未注册:{}"
,
mobile
);
return
new
ResponseBean
<>(
Boolean
.
FALSE
,
"手机号未注册."
);
}
Object
codeObj
=
redisTemplate
.
opsForValue
().
get
(
CommonConstant
.
DEFAULT_CODE_KEY
+
mobile
);
if
(
codeObj
!=
null
)
{
log
.
info
(
"手机号验证码未过期:{},{}"
,
mobile
,
codeObj
);
...
...
@@ -62,7 +56,10 @@ public class MobileService {
SmsDto
smsDto
=
new
SmsDto
();
smsDto
.
setReceiver
(
mobile
);
smsDto
.
setContent
(
String
.
format
(
SmsConstant
.
SMS_TEMPLATE
,
code
));
mscServiceClient
.
sendSms
(
smsDto
);
// ResponseBean<?> result = mscServiceClient.sendSms(smsDto);
// if (result == null)
// throw new CommonException("发送失败.");
// log.info("发送验证码结果:{}", result.getData());
return
new
ResponseBean
<>(
Boolean
.
TRUE
,
code
);
}
}
service-api-impl/user-service/src/main/java/com/github/tangyi/user/service/UserService.java
View file @
e9194a2d
...
...
@@ -3,19 +3,20 @@ package com.github.tangyi.user.service;
import
com.github.tangyi.common.core.constant.CommonConstant
;
import
com.github.tangyi.common.core.enums.LoginType
;
import
com.github.tangyi.common.core.exceptions.CommonException
;
import
com.github.tangyi.common.core.properties.SysProperties
;
import
com.github.tangyi.common.core.service.CrudService
;
import
com.github.tangyi.common.core.utils.DateUtils
;
import
com.github.tangyi.common.core.utils.IdGen
;
import
com.github.tangyi.common.core.utils.SysUtil
;
import
com.github.tangyi.common.core.vo.UserVo
;
import
com.github.tangyi.common.security.constant.SecurityConstant
;
import
com.github.tangyi.user.api.constant.AttachmentConstant
;
import
com.github.tangyi.user.api.constant.MenuConstant
;
import
com.github.tangyi.user.api.constant.RoleConstant
;
import
com.github.tangyi.user.api.dto.UserDto
;
import
com.github.tangyi.user.api.dto.UserInfoDto
;
import
com.github.tangyi.user.api.enums.IdentityType
;
import
com.github.tangyi.user.api.module.*
;
import
com.github.tangyi.user.config.SysConfig
;
import
com.github.tangyi.user.mapper.RoleMapper
;
import
com.github.tangyi.user.mapper.UserMapper
;
import
com.github.tangyi.user.mapper.UserRoleMapper
;
...
...
@@ -66,7 +67,7 @@ public class UserService extends CrudService<UserMapper, User> {
private
final
AttachmentService
attachmentService
;
private
final
Sys
Config
sysConfig
;
private
final
Sys
Properties
sysProperties
;
private
final
UserAuthsService
userAuthsService
;
...
...
@@ -503,7 +504,7 @@ public class UserService extends CrudService<UserMapper, User> {
attachment
.
setId
(
user
.
getAvatarId
());
userInfoDto
.
setAvatarUrl
(
attachmentService
.
getPreviewUrl
(
attachment
));
}
else
{
userInfoDto
.
setAvatarUrl
(
sys
Config
.
getDefaultAvatar
());
userInfoDto
.
setAvatarUrl
(
sys
Properties
.
getDefaultAvatar
());
}
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
...
...
@@ -521,7 +522,6 @@ public class UserService extends CrudService<UserMapper, User> {
@Transactional
@CacheEvict
(
value
=
"user"
,
key
=
"#userDto.identifier"
)
public
boolean
resetPassword
(
UserDto
userDto
)
{
userDto
.
setCommonValue
(
SysUtil
.
getUser
(),
SysUtil
.
getSysCode
());
UserAuths
userAuths
=
new
UserAuths
();
userAuths
.
setIdentifier
(
userDto
.
getIdentifier
());
userAuths
=
userAuthsService
.
getByIdentifier
(
userAuths
);
...
...
@@ -533,7 +533,7 @@ public class UserService extends CrudService<UserMapper, User> {
}
/**
* 注册
* 注册
,注意要清除缓存
*
* @param userDto userDto
* @return boolean
...
...
@@ -541,16 +541,25 @@ public class UserService extends CrudService<UserMapper, User> {
* @date 2019/07/03 13:30:03
*/
@Transactional
@CacheEvict
(
value
=
"user"
,
key
=
"#userDto.identifier"
)
public
boolean
register
(
UserDto
userDto
)
{
boolean
success
=
false
;
// 解密
String
password
=
this
.
decryptCredential
(
userDto
.
getCredential
(),
userDto
.
getIdentityType
());
User
user
=
new
User
();
BeanUtils
.
copyProperties
(
userDto
,
user
);
// 初始化用户名,系统编号,租户编号
user
.
setCommonValue
(
userDto
.
getIdentifier
(),
SysUtil
.
getSysCode
(),
SysUtil
.
getTenantCode
());
// 设置默认密码
if
(
StringUtils
.
isEmpty
(
userDto
.
getCredential
()))
userDto
.
setCredential
(
CommonConstant
.
DEFAULT_PASSWORD
);
user
.
setStatus
(
CommonConstant
.
DEL_FLAG_NORMAL
);
// 初始化头像
if
(
StringUtils
.
isNotBlank
(
userDto
.
getAvatarUrl
()))
{
Attachment
attachment
=
new
Attachment
();
attachment
.
setCommonValue
(
userDto
.
getIdentifier
(),
SysUtil
.
getSysCode
(),
SysUtil
.
getTenantCode
());
attachment
.
setBusiType
(
AttachmentConstant
.
BUSI_TYPE_USER_AVATAR
);
attachment
.
setPreviewUrl
(
userDto
.
getAvatarUrl
());
if
(
attachmentService
.
insert
(
attachment
)
>
0
)
user
.
setAvatarId
(
attachment
.
getId
());
}
// 保存用户基本信息
if
(
this
.
insert
(
user
)
>
0
)
{
// 保存账号信息
...
...
@@ -558,10 +567,10 @@ public class UserService extends CrudService<UserMapper, User> {
userAuths
.
setCommonValue
(
userDto
.
getIdentifier
(),
user
.
getApplicationCode
(),
user
.
getTenantCode
());
userAuths
.
setUserId
(
user
.
getId
());
userAuths
.
setIdentifier
(
userDto
.
getIdentifier
());
if
(
userDto
.
getIdentityType
()
=
=
null
)
userAuths
.
setIdentityType
(
IdentityType
.
PASSWORD
.
getValu
e
());
// 设置密码
,授权类型默认
userAuths
.
setCredential
(
encoder
.
encode
(
userDto
.
getCredential
()
));
if
(
userDto
.
getIdentityType
()
!
=
null
)
userAuths
.
setIdentityType
(
userDto
.
getIdentityTyp
e
());
// 设置密码
userAuths
.
setCredential
(
encoder
.
encode
(
password
));
userAuthsService
.
insert
(
userAuths
);
// 分配默认角色
success
=
this
.
defaultRole
(
user
,
userDto
.
getTenantCode
(),
userDto
.
getIdentifier
());
...
...
@@ -570,6 +579,32 @@ public class UserService extends CrudService<UserMapper, User> {
}
/**
* 解密密码
*
* @param encoded encoded
* @return String
* @author tangyi
* @date 2019/07/05 12:39:13
*/
private
String
decryptCredential
(
String
encoded
,
Integer
identityType
)
{
// 返回默认密码
if
(
StringUtils
.
isBlank
(
encoded
))
return
CommonConstant
.
DEFAULT_PASSWORD
;
// 微信注册不需要解密
if
(
IdentityType
.
WE_CHAT
.
getValue
().
equals
(
identityType
))
return
encoded
;
// 解密密码
try
{
encoded
=
SysUtil
.
decryptAES
(
encoded
,
sysProperties
.
getKey
()).
trim
();
log
.
info
(
"密码解密结果:{}"
,
encoded
);
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
throw
new
CommonException
(
"注册失败,密码非法."
);
}
return
encoded
;
}
/**
* 分配默认角色
*
* @param user user
...
...
service-api-impl/user-service/src/main/java/com/github/tangyi/user/utils/UserUtils.java
View file @
e9194a2d
package
com
.
github
.
tangyi
.
user
.
utils
;
import
com.github.tangyi.common.core.properties.SysProperties
;
import
com.github.tangyi.common.core.utils.SpringContextHolder
;
import
com.github.tangyi.common.core.utils.SysUtil
;
import
com.github.tangyi.common.core.vo.RoleVo
;
...
...
@@ -7,7 +8,6 @@ import com.github.tangyi.user.api.dto.UserInfoDto;
import
com.github.tangyi.user.api.module.Role
;
import
com.github.tangyi.user.api.module.User
;
import
com.github.tangyi.user.api.module.UserAuths
;
import
com.github.tangyi.user.config.SysConfig
;
import
org.springframework.beans.BeanUtils
;
import
java.util.LinkedHashMap
;
...
...
@@ -89,8 +89,8 @@ public class UserUtils {
* @date 2019/07/04 00:25:11
*/
public
static
boolean
isAdmin
(
String
identifier
)
{
Sys
Config
sysConfig
=
SpringContextHolder
.
getApplicationContext
().
getBean
(
SysConfig
.
class
);
return
identifier
.
equals
(
sys
Config
.
getAdminUser
());
Sys
Properties
sysProperties
=
SpringContextHolder
.
getApplicationContext
().
getBean
(
SysProperties
.
class
);
return
identifier
.
equals
(
sys
Properties
.
getAdminUser
());
}
/**
...
...
service-api-impl/user-service/src/main/resources/mapper/UserAuthsMapper.xml
View file @
e9194a2d
...
...
@@ -4,7 +4,7 @@
<resultMap
id=
"userAuthResultMap"
type=
"com.github.tangyi.user.api.module.UserAuths"
>
<id
column=
"id"
property=
"id"
/>
<result
column=
"user_id"
property=
"userId"
/>
<result
column=
"identity_type"
property=
"identityType"
/>
<result
column=
"identity_type"
property=
"identityType"
jdbcType=
"INTEGER"
/>
<result
column=
"identifier"
property=
"identifier"
/>
<result
column=
"credential"
property=
"credential"
/>
<result
column=
"creator"
property=
"creator"
/>
...
...
@@ -33,8 +33,8 @@
<!-- where 条件 -->
<sql
id=
"whereColumnList"
>
<if
test=
"identityType != null
and identityType != ''
"
>
and a.identity_type = #{identityType}
<if
test=
"identityType != null"
>
and a.identity_type = #{identityType
, jdbcType=INTEGER
}
</if>
<if
test=
"tenantCode != null and tenantCode != ''"
>
and a.tenant_code = #{tenantCode}
...
...
@@ -102,7 +102,7 @@
) values (
#{id},
#{userId},
#{identityType},
#{identityType
, jdbcType=INTEGER
},
#{identifier},
#{credential},
#{creator},
...
...
@@ -122,7 +122,7 @@
user_id = #{userId} ,
</if>
<if
test=
"identityType != null"
>
identity_type = #{identityType} ,
identity_type = #{identityType
, jdbcType=INTEGER
} ,
</if>
<if
test=
"identifier != null"
>
identifier = #{identifier} ,
...
...
service-api-impl/user-service/src/main/resources/mapper/UserMapper.xml
View file @
e9194a2d
...
...
@@ -12,6 +12,14 @@
<result
column=
"user_desc"
property=
"userDesc"
/>
<result
column=
"dept_id"
property=
"deptId"
/>
<result
column=
"status"
property=
"status"
/>
<result
column=
"parent_uid"
property=
"parentUid"
/>
<result
column=
"street_id"
property=
"streetId"
/>
<result
column=
"county_id"
property=
"countyId"
/>
<result
column=
"city_id"
property=
"cityId"
/>
<result
column=
"province_id"
property=
"provinceId"
/>
<result
column=
"login_time"
property=
"loginTime"
javaType=
"java.util.Date"
jdbcType=
"TIMESTAMP"
/>
<result
column=
"lock_time"
property=
"lockTime"
javaType=
"java.util.Date"
jdbcType=
"TIMESTAMP"
/>
<result
column=
"wechat"
property=
"wechat"
/>
<result
column=
"creator"
property=
"creator"
/>
<result
column=
"create_date"
property=
"createDate"
javaType=
"java.util.Date"
jdbcType=
"TIMESTAMP"
/>
<result
column=
"modifier"
property=
"modifier"
/>
...
...
@@ -32,6 +40,14 @@
a.user_desc,
a.dept_id,
a.status,
a.parent_uid,
a.street_id,
a.county_id,
a.city_id,
a.province_id,
a.login_time,
a.lock_time,
a.wechat,
a.creator,
a.create_date,
a.modifier,
...
...
@@ -106,6 +122,14 @@
user_desc,
dept_id,
status,
parent_uid,
street_id,
county_id,
city_id,
province_id,
login_time,
lock_time,
wechat,
creator,
create_date,
modifier,
...
...
@@ -124,6 +148,14 @@
#{userDesc},
#{deptId},
#{status},
#{parentUid},
#{streetId},
#{countyId},
#{cityId},
#{provinceId},
#{loginTime, jdbcType=TIMESTAMP, javaType=java.util.Date},
#{lockTime, jdbcType=TIMESTAMP, javaType=java.util.Date},
#{wechat},
#{creator},
#{createDate, jdbcType=TIMESTAMP, javaType=java.util.Date},
#{modifier},
...
...
@@ -164,6 +196,30 @@
<if
test=
"status != null"
>
status = #{status} ,
</if>
<if
test=
"parentUid != null"
>
parent_uid = #{parentUid} ,
</if>
<if
test=
"streetId != null"
>
street_id = #{streetId} ,
</if>
<if
test=
"countyId != null"
>
county_id = #{countyId} ,
</if>
<if
test=
"cityId != null"
>
city_id = #{cityId} ,
</if>
<if
test=
"provinceId != null"
>
province_id = #{provinceId} ,
</if>
<if
test=
"loginTime != null"
>
login_time = #{loginTime, jdbcType=TIMESTAMP, javaType=java.util.Date} ,
</if>
<if
test=
"lockTime != null"
>
lock_time = #{lockTime, jdbcType=TIMESTAMP, javaType=java.util.Date} ,
</if>
<if
test=
"wechat != null"
>
wechat = #{wechat} ,
</if>
<if
test=
"creator != null"
>
creator = #{creator} ,
</if>
...
...
@@ -182,17 +238,12 @@
</update>
<update
id=
"delete"
>
update sys_user set
del_flag = 1,
modifier = #{modifier} ,
modify_date = #{modifyDate, jdbcType=TIMESTAMP, javaType=java.util.Date}
where id = #{id}
DELETE FROM sys_user WHERE id = #{id}
</update>
<delete
id=
"deleteAll"
>
update sys_user SET
del_flag = 1
where id in
DELETE FROM sys_user
WHERE id in
<foreach
item=
"item"
index=
"index"
collection=
"array"
open=
"("
separator=
","
close=
")"
>
#{item}
</foreach>
...
...
service-api/auth-api/src/main/java/com/github/tangyi/auth/api/module/WxSession.java
0 → 100644
View file @
e9194a2d
package
com
.
github
.
tangyi
.
auth
.
api
.
module
;
import
lombok.AllArgsConstructor
;
import
lombok.Data
;
import
java.io.Serializable
;
/**
* 封装微信登录状态
*
* @author tangyi
* @date 2019/07/05 20:35
*/
@Data
@AllArgsConstructor
public
class
WxSession
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
private
String
openId
;
private
String
sessionKey
;
}
service-api/user-api/src/main/java/com/github/tangyi/user/api/constant/AttachmentConstant.java
0 → 100644
View file @
e9194a2d
package
com
.
github
.
tangyi
.
user
.
api
.
constant
;
/**
* @author tangyi
* @date 2019/07/06 16:16
*/
public
class
AttachmentConstant
{
/**
* 普通附件
*/
public
static
final
String
BUSI_TYPE_NORMAL_ATTACHMENT
=
"0"
;
/**
* 用户头像
*/
public
static
final
String
BUSI_TYPE_USER_AVATAR
=
"1"
;
/**
* 知识库附件
*/
public
static
final
String
BUSI_TYPE_KNOWLEDGE_ATTACHMENT
=
"2"
;
}
service-api/user-api/src/main/java/com/github/tangyi/user/api/dto/UserDto.java
View file @
e9194a2d
package
com
.
github
.
tangyi
.
user
.
api
.
dto
;
import
com.github.tangyi.common.core.
persistence.BaseEntity
;
import
com.github.tangyi.common.core.
constant.CommonConstant
;
import
com.github.tangyi.user.api.module.Role
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Data
;
import
javax.validation.constraints.Email
;
import
javax.validation.constraints.Pattern
;
import
java.io.Serializable
;
import
java.util.Date
;
import
java.util.List
;
...
...
@@ -17,92 +19,183 @@ import java.util.List;
* @date 2018/8/26 14:36
*/
@Data
public
class
UserDto
extends
BaseEntity
<
UserDto
>
{
public
class
UserDto
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* id
*/
@ApiModelProperty
(
value
=
"id"
,
hidden
=
true
)
private
String
id
;
/**
* 授权类型,1:用户名密码,2:手机号,3:邮箱,4:微信,5:QQ
*/
@ApiModelProperty
(
value
=
"授权类型,1:用户名密码,2:手机号,3:邮箱,4:微信,5:QQ"
,
dataType
=
"Integer"
,
example
=
"1"
)
private
Integer
identityType
;
/**
* 唯一标识,如用户名、手机号
*/
@ApiModelProperty
(
value
=
"账号唯一标识,如用户名、手机号"
,
example
=
"git"
)
private
String
identifier
;
/**
* 密码凭证,跟授权类型有关,如密码、第三方系统的token等
*/
@ApiModelProperty
(
value
=
"密码,需要使用AES加密"
,
example
=
"lBTqrKS0kZixOFXeZ0HRng=="
)
private
String
credential
;
/**
* 角色
*/
@ApiModelProperty
(
value
=
"角色"
,
hidden
=
true
)
private
List
<
String
>
role
;
/**
* 部门ID
*/
@ApiModelProperty
(
value
=
"部门ID"
)
private
String
deptId
;
/**
* 部门名称
*/
@ApiModelProperty
(
value
=
"部门名称"
,
hidden
=
true
)
private
String
deptName
;
/**
* 旧密码
*/
@ApiModelProperty
(
value
=
"旧密码"
,
hidden
=
true
)
private
String
oldPassword
;
/**
* 新密码
*/
@ApiModelProperty
(
value
=
"新密码"
,
hidden
=
true
)
private
String
newPassword
;
/**
* 姓名
*/
@ApiModelProperty
(
value
=
"姓名"
,
example
=
"git"
)
private
String
name
;
/**
* 电话
*/
@ApiModelProperty
(
value
=
"电话"
,
example
=
"15521089184"
)
@Pattern
(
regexp
=
"^\\d{11}$"
,
message
=
"请输入11位手机号"
)
private
String
phone
;
/**
* 头像id
*/
@ApiModelProperty
(
value
=
"头像id"
,
hidden
=
true
)
private
String
avatarId
;
/**
* 头像URL
*/
@ApiModelProperty
(
value
=
"头像URL"
,
hidden
=
true
)
private
String
avatarUrl
;
/**
* 邮箱
*/
@ApiModelProperty
(
value
=
"邮箱"
,
example
=
"1633736729@qq.com"
)
@Email
(
message
=
"邮箱格式不正确"
)
private
String
email
;
/**
* 性别
*/
@ApiModelProperty
(
value
=
"性别,0:男,1:女"
,
dataType
=
"Integer"
,
example
=
"0"
)
private
Integer
sex
;
/**
* 出生日期
*/
@ApiModelProperty
(
value
=
"出生日期"
,
dataType
=
"Date"
)
private
Date
born
;
/**
* 描述
*/
@ApiModelProperty
(
value
=
"描述"
,
example
=
"git"
)
private
String
userDesc
;
/**
* 状态
*/
@ApiModelProperty
(
value
=
"状态,0:启用,1:禁用"
,
example
=
"0"
)
private
Integer
status
;
/**
* 角色列表
*/
@ApiModelProperty
(
value
=
"角色列表"
,
hidden
=
true
)
private
List
<
Role
>
roleList
;
/**
* 系统编号
*/
@ApiModelProperty
(
value
=
"系统编号"
,
example
=
"EXAM"
)
private
String
applicationCode
;
/**
* 租户标识
*/
@ApiModelProperty
(
value
=
"租户标识"
,
example
=
"gitee"
)
private
String
tenantCode
;
/**
* 引导注册人
*/
@ApiModelProperty
(
value
=
"引导注册人"
)
private
String
parentUid
;
/**
* 乡/镇
*/
@ApiModelProperty
(
value
=
"乡/镇"
)
private
String
streetId
;
/**
* 县
*/
@ApiModelProperty
(
value
=
"县"
)
private
String
countyId
;
/**
* 城市
*/
@ApiModelProperty
(
value
=
"城市"
)
private
String
cityId
;
/**
* 省份
*/
@ApiModelProperty
(
value
=
"省份"
)
private
String
provinceId
;
/**
* 最近登录时间
*/
@ApiModelProperty
(
value
=
"最近登录时间"
,
hidden
=
true
)
private
Date
loginTime
;
/**
* 用户归档时间
*/
@ApiModelProperty
(
value
=
"用户归档时间"
,
hidden
=
true
)
private
Date
lockTime
;
/**
* 微信
*/
@ApiModelProperty
(
value
=
"微信"
)
private
String
wechat
;
}
service-api/user-api/src/main/java/com/github/tangyi/user/api/dto/UserInfoDto.java
View file @
e9194a2d
...
...
@@ -107,4 +107,44 @@ public class UserInfoDto implements Serializable {
* 租户标识
*/
private
String
tenantCode
;
/**
* 引导注册人
*/
private
String
parentUid
;
/**
* 乡/镇
*/
private
String
streetId
;
/**
* 县
*/
private
String
countyId
;
/**
* 城市
*/
private
String
cityId
;
/**
* 省份
*/
private
String
provinceId
;
/**
* 最近登录时间
*/
private
Date
loginTime
;
/**
* 用户归档时间
*/
private
Date
lockTime
;
/**
* 微信
*/
private
String
wechat
;
}
service-api/user-api/src/main/java/com/github/tangyi/user/api/feign/UserServiceClient.java
View file @
e9194a2d
...
...
@@ -7,6 +7,7 @@ import com.github.tangyi.common.core.vo.AttachmentVo;
import
com.github.tangyi.common.core.vo.DeptVo
;
import
com.github.tangyi.common.core.vo.UserVo
;
import
com.github.tangyi.common.feign.config.CustomFeignConfig
;
import
com.github.tangyi.user.api.dto.UserDto
;
import
com.github.tangyi.user.api.dto.UserInfoDto
;
import
com.github.tangyi.user.api.feign.factory.UserServiceClientFallbackFactory
;
import
com.github.tangyi.user.api.module.Menu
;
...
...
@@ -38,6 +39,20 @@ public interface UserServiceClient {
UserVo
findUserByIdentifier
(
@PathVariable
(
"identifier"
)
String
identifier
,
@RequestParam
(
"tenantCode"
)
String
tenantCode
);
/**
* 根据用户名获取用户详细信息
*
* @param identifier identifier
* @param identityType identityType
* @param tenantCode 租户标识
* @return UserVo
* @author tangyi
* @date 2019/07/06 14:14:11
*/
@GetMapping
(
"/v1/user/findUserByIdentifier/{identifier}"
)
UserVo
findUserByIdentifier
(
@PathVariable
(
"identifier"
)
String
identifier
,
@RequestParam
(
required
=
false
)
Integer
identityType
,
@RequestParam
(
"tenantCode"
)
String
tenantCode
);
/**
* 获取当前用户的信息
*
* @return ResponseBean
...
...
@@ -152,4 +167,26 @@ public interface UserServiceClient {
*/
@GetMapping
(
"/v1/user/findUserBySocial/{social}"
)
UserVo
findUserBySocial
(
@PathVariable
(
"social"
)
String
social
,
@RequestParam
(
"tenantCode"
)
String
tenantCode
);
/**
* 注册用户
*
* @param userDto userDto
* @return ResponseBean
* @author tangyi
* @date 2019/07/05 20:57:31
*/
@PostMapping
(
"/v1/user/register"
)
ResponseBean
<
Boolean
>
registerUser
(
@RequestBody
UserDto
userDto
);
/**
* 更新用户
*
* @param userDto userDto
* @return ResponseBean
* @author tangyi
* @date 2019/07/05 20:59:06
*/
@PutMapping
(
"/v1/user"
)
ResponseBean
<
Boolean
>
updateUser
(
UserDto
userDto
);
}
service-api/user-api/src/main/java/com/github/tangyi/user/api/feign/fallback/UserServiceClientFallbackImpl.java
View file @
e9194a2d
...
...
@@ -5,6 +5,7 @@ import com.github.tangyi.common.core.model.ResponseBean;
import
com.github.tangyi.common.core.vo.AttachmentVo
;
import
com.github.tangyi.common.core.vo.DeptVo
;
import
com.github.tangyi.common.core.vo.UserVo
;
import
com.github.tangyi.user.api.dto.UserDto
;
import
com.github.tangyi.user.api.dto.UserInfoDto
;
import
com.github.tangyi.user.api.feign.UserServiceClient
;
import
com.github.tangyi.user.api.module.Menu
;
...
...
@@ -43,6 +44,20 @@ public class UserServiceClientFallbackImpl implements UserServiceClient {
}
/**
* 根据用户名查询用户信息
*
* @param identifier identifier
* @param identityType identityType
* @param tenantCode 租户标识
* @return UserVo
*/
@Override
public
UserVo
findUserByIdentifier
(
String
identifier
,
Integer
identityType
,
String
tenantCode
)
{
log
.
error
(
"feign 查询用户信息失败:{}, {}, {}, {}"
,
tenantCode
,
identityType
,
identifier
,
throwable
);
return
null
;
}
/**
* 查询当前登录的用户信息
*
* @return ResponseBean
...
...
@@ -175,6 +190,30 @@ public class UserServiceClientFallbackImpl implements UserServiceClient {
return
null
;
}
/**
* 注册用户
*
* @param userDto userDto
* @return ResponseBean
*/
@Override
public
ResponseBean
<
Boolean
>
registerUser
(
UserDto
userDto
)
{
log
.
error
(
"feign 注册用户失败, {}, {}, {}"
,
userDto
.
getIdentityType
(),
userDto
.
getIdentifier
(),
throwable
);
return
null
;
}
/**
* 更新用户
*
* @param userDto userDto
* @return ResponseBean
*/
@Override
public
ResponseBean
<
Boolean
>
updateUser
(
UserDto
userDto
)
{
log
.
error
(
"feign 更新用户失败, {}, {}, {}"
,
userDto
.
getIdentityType
(),
userDto
.
getIdentifier
(),
throwable
);
return
null
;
}
public
Throwable
getThrowable
()
{
return
throwable
;
}
...
...
service-api/user-api/src/main/java/com/github/tangyi/user/api/module/Attachment.java
View file @
e9194a2d
package
com
.
github
.
tangyi
.
user
.
api
.
module
;
import
com.github.tangyi.common.core.persistence.BaseEntity
;
import
com.github.tangyi.user.api.constant.AttachmentConstant
;
import
lombok.Data
;
import
javax.validation.constraints.NotBlank
;
...
...
@@ -45,7 +46,7 @@ public class Attachment extends BaseEntity<Attachment> {
/**
* 业务类型
*/
private
String
busiType
;
private
String
busiType
=
AttachmentConstant
.
BUSI_TYPE_NORMAL_ATTACHMENT
;
/**
* 业务模块
...
...
service-api/user-api/src/main/java/com/github/tangyi/user/api/module/User.java
View file @
e9194a2d
...
...
@@ -73,4 +73,44 @@ public class User extends BaseEntity<User> {
* 角色
*/
private
List
<
String
>
role
;
/**
* 引导注册人
*/
private
String
parentUid
;
/**
* 乡/镇
*/
private
String
streetId
;
/**
* 县
*/
private
String
countyId
;
/**
* 城市
*/
private
String
cityId
;
/**
* 省份
*/
private
String
provinceId
;
/**
* 最近登录时间
*/
private
Date
loginTime
;
/**
* 用户归档时间
*/
private
Date
lockTime
;
/**
* 微信
*/
private
String
wechat
;
}
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