Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Administrator
mall4cloudNew
Commits
3ab6e756
Commit
3ab6e756
authored
Dec 21, 2023
by
shengnan hu
Browse files
init
parents
Pipeline
#294
passed with stage
in 2 minutes and 13 seconds
Changes
678
Pipelines
3
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
1358 additions
and
0 deletions
+1358
-0
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/controller/CaptchaController.java
...a/com/mall4j/cloud/auth/controller/CaptchaController.java
+38
-0
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/controller/LoginController.java
...ava/com/mall4j/cloud/auth/controller/LoginController.java
+88
-0
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/controller/PasswordController.java
.../com/mall4j/cloud/auth/controller/PasswordController.java
+52
-0
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/controller/TokenController.java
...ava/com/mall4j/cloud/auth/controller/TokenController.java
+40
-0
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/dto/AuthenticationDTO.java
...ain/java/com/mall4j/cloud/auth/dto/AuthenticationDTO.java
+69
-0
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/dto/CaptchaAuthenticationDTO.java
...a/com/mall4j/cloud/auth/dto/CaptchaAuthenticationDTO.java
+31
-0
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/dto/RefreshTokenDTO.java
.../main/java/com/mall4j/cloud/auth/dto/RefreshTokenDTO.java
+35
-0
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/dto/UpdatePasswordDTO.java
...ain/java/com/mall4j/cloud/auth/dto/UpdatePasswordDTO.java
+47
-0
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/feign/AccountFeignController.java
...a/com/mall4j/cloud/auth/feign/AccountFeignController.java
+155
-0
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/feign/TokenFeignController.java
...ava/com/mall4j/cloud/auth/feign/TokenFeignController.java
+34
-0
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/manager/TokenStore.java
...c/main/java/com/mall4j/cloud/auth/manager/TokenStore.java
+317
-0
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/mapper/AuthAccountMapper.java
.../java/com/mall4j/cloud/auth/mapper/AuthAccountMapper.java
+104
-0
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/model/AuthAccount.java
...rc/main/java/com/mall4j/cloud/auth/model/AuthAccount.java
+147
-0
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/service/AuthAccountService.java
...ava/com/mall4j/cloud/auth/service/AuthAccountService.java
+56
-0
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/service/impl/AuthAccountServiceImpl.java
...all4j/cloud/auth/service/impl/AuthAccountServiceImpl.java
+122
-0
mall4cloud-auth/src/main/resources/META-INF/services/com.anji.captcha.service.CaptchaCacheService
...INF/services/com.anji.captcha.service.CaptchaCacheService
+2
-0
mall4cloud-auth/src/main/resources/bootstrap.yml
mall4cloud-auth/src/main/resources/bootstrap.yml
+21
-0
mall4cloud-auth/src/main/resources/captcha/original/1.png
mall4cloud-auth/src/main/resources/captcha/original/1.png
+0
-0
mall4cloud-auth/src/main/resources/captcha/original/2.png
mall4cloud-auth/src/main/resources/captcha/original/2.png
+0
-0
mall4cloud-auth/src/main/resources/captcha/original/3.png
mall4cloud-auth/src/main/resources/captcha/original/3.png
+0
-0
No files found.
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/controller/CaptchaController.java
0 → 100644
View file @
3ab6e756
package
com.mall4j.cloud.auth.controller
;
import
com.anji.captcha.model.common.ResponseModel
;
import
com.anji.captcha.model.vo.CaptchaVO
;
import
com.anji.captcha.service.CaptchaService
;
import
com.mall4j.cloud.common.response.ServerResponseEntity
;
import
io.swagger.v3.oas.annotations.tags.Tag
;
import
org.springframework.web.bind.annotation.PostMapping
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
/**
* @author FrozenWatermelon
* @date 2020/7/30
*/
@RestController
@RequestMapping
(
"/ua/captcha"
)
@Tag
(
name
=
"验证码"
)
public
class
CaptchaController
{
private
final
CaptchaService
captchaService
;
public
CaptchaController
(
CaptchaService
captchaService
)
{
this
.
captchaService
=
captchaService
;
}
@PostMapping
({
"/get"
})
public
ServerResponseEntity
<
ResponseModel
>
get
(
@RequestBody
CaptchaVO
captchaVO
)
{
return
ServerResponseEntity
.
success
(
captchaService
.
get
(
captchaVO
));
}
@PostMapping
({
"/check"
})
public
ServerResponseEntity
<
ResponseModel
>
check
(
@RequestBody
CaptchaVO
captchaVO
)
{
return
ServerResponseEntity
.
success
(
captchaService
.
check
(
captchaVO
));
}
}
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/controller/LoginController.java
0 → 100644
View file @
3ab6e756
package
com.mall4j.cloud.auth.controller
;
import
com.mall4j.cloud.api.auth.bo.UserInfoInTokenBO
;
import
com.mall4j.cloud.api.rbac.dto.ClearUserPermissionsCacheDTO
;
import
com.mall4j.cloud.api.rbac.feign.PermissionFeignClient
;
import
com.mall4j.cloud.auth.dto.AuthenticationDTO
;
import
com.mall4j.cloud.auth.manager.TokenStore
;
import
com.mall4j.cloud.auth.service.AuthAccountService
;
import
com.mall4j.cloud.common.response.ResponseEnum
;
import
com.mall4j.cloud.common.response.ServerResponseEntity
;
import
com.mall4j.cloud.common.security.AuthUserContext
;
import
com.mall4j.cloud.api.auth.vo.TokenInfoVO
;
import
io.swagger.v3.oas.annotations.tags.Tag
;
import
io.swagger.v3.oas.annotations.Operation
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.security.crypto.password.PasswordEncoder
;
import
org.springframework.web.bind.annotation.PostMapping
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RestController
;
import
jakarta.validation.Valid
;
/**
* @author FrozenWatermelon
* @date 2020/6/30
*/
@RestController
@Tag
(
name
=
"登录"
)
public
class
LoginController
{
@Autowired
private
TokenStore
tokenStore
;
@Autowired
private
AuthAccountService
authAccountService
;
@Autowired
private
PermissionFeignClient
permissionFeignClient
;
@Autowired
private
PasswordEncoder
passwordEncoder
;
@PostMapping
(
"/ua/login"
)
@Operation
(
summary
=
"账号密码"
,
description
=
"通过账号登录,还要携带用户的类型,也就是用户所在的系统"
)
public
ServerResponseEntity
<
TokenInfoVO
>
login
(
@Valid
@RequestBody
AuthenticationDTO
authenticationDTO
)
{
// 这边获取了用户的用户信息,那么根据sessionid对应一个user的原则,我应该要把这个东西存起来,然后校验,那么存到哪里呢?
// redis,redis有天然的自动过期的机制,有key value的形式
ServerResponseEntity
<
UserInfoInTokenBO
>
userInfoInTokenResponse
=
authAccountService
.
getUserInfoInTokenByInputUserNameAndPassword
(
authenticationDTO
.
getPrincipal
(),
authenticationDTO
.
getCredentials
(),
authenticationDTO
.
getSysType
());
if
(!
userInfoInTokenResponse
.
isSuccess
())
{
return
ServerResponseEntity
.
transform
(
userInfoInTokenResponse
);
}
UserInfoInTokenBO
data
=
userInfoInTokenResponse
.
getData
();
ClearUserPermissionsCacheDTO
clearUserPermissionsCacheDTO
=
new
ClearUserPermissionsCacheDTO
();
clearUserPermissionsCacheDTO
.
setSysType
(
data
.
getSysType
());
clearUserPermissionsCacheDTO
.
setUserId
(
data
.
getUserId
());
// 将以前的权限清理了,以免权限有缓存
ServerResponseEntity
<
Void
>
clearResponseEntity
=
permissionFeignClient
.
clearUserPermissionsCache
(
clearUserPermissionsCacheDTO
);
if
(!
clearResponseEntity
.
isSuccess
())
{
return
ServerResponseEntity
.
fail
(
ResponseEnum
.
UNAUTHORIZED
);
}
// 保存token,返回token数据给前端,这里是最重要的
return
ServerResponseEntity
.
success
(
tokenStore
.
storeAndGetVo
(
data
));
}
@PostMapping
(
"/login_out"
)
@Operation
(
summary
=
"退出登陆"
,
description
=
"点击退出登陆,清除token,清除菜单缓存"
)
public
ServerResponseEntity
<
TokenInfoVO
>
loginOut
()
{
UserInfoInTokenBO
userInfoInToken
=
AuthUserContext
.
get
();
ClearUserPermissionsCacheDTO
clearUserPermissionsCacheDTO
=
new
ClearUserPermissionsCacheDTO
();
clearUserPermissionsCacheDTO
.
setSysType
(
userInfoInToken
.
getSysType
());
clearUserPermissionsCacheDTO
.
setUserId
(
userInfoInToken
.
getUserId
());
// 将以前的权限清理了,以免权限有缓存
permissionFeignClient
.
clearUserPermissionsCache
(
clearUserPermissionsCacheDTO
);
// 删除该用户在该系统的token
tokenStore
.
deleteAllToken
(
userInfoInToken
.
getSysType
().
toString
(),
userInfoInToken
.
getUid
());
return
ServerResponseEntity
.
success
();
}
}
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/controller/PasswordController.java
0 → 100644
View file @
3ab6e756
package
com.mall4j.cloud.auth.controller
;
import
com.mall4j.cloud.api.auth.bo.UserInfoInTokenBO
;
import
com.mall4j.cloud.api.auth.vo.TokenInfoVO
;
import
com.mall4j.cloud.auth.dto.UpdatePasswordDTO
;
import
com.mall4j.cloud.auth.manager.TokenStore
;
import
com.mall4j.cloud.auth.model.AuthAccount
;
import
com.mall4j.cloud.auth.service.AuthAccountService
;
import
com.mall4j.cloud.common.response.ServerResponseEntity
;
import
com.mall4j.cloud.common.security.AuthUserContext
;
import
io.swagger.v3.oas.annotations.tags.Tag
;
import
io.swagger.v3.oas.annotations.Operation
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.security.crypto.password.PasswordEncoder
;
import
org.springframework.web.bind.annotation.PutMapping
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RestController
;
import
jakarta.validation.Valid
;
/**
* @author FrozenWatermelon
* @date 2021/01/29
*/
@RestController
@Tag
(
name
=
"密码"
)
public
class
PasswordController
{
@Autowired
private
TokenStore
tokenStore
;
@Autowired
private
AuthAccountService
authAccountService
;
@Autowired
private
PasswordEncoder
passwordEncoder
;
@PutMapping
(
"/update_password"
)
@Operation
(
summary
=
"更新密码"
,
description
=
"更新当前用户的密码, 更新密码之后要退出登录,清理token"
)
public
ServerResponseEntity
<
TokenInfoVO
>
updatePassword
(
@Valid
@RequestBody
UpdatePasswordDTO
updatePasswordDTO
)
{
UserInfoInTokenBO
userInfoInToken
=
AuthUserContext
.
get
();
AuthAccount
authAccount
=
authAccountService
.
getByUserIdAndType
(
userInfoInToken
.
getUserId
(),
userInfoInToken
.
getSysType
());
if
(!
passwordEncoder
.
matches
(
updatePasswordDTO
.
getOldPassword
(),
authAccount
.
getPassword
()))
{
return
ServerResponseEntity
.
showFailMsg
(
"旧密码不正确"
);
}
authAccountService
.
updatePassword
(
userInfoInToken
.
getUserId
(),
userInfoInToken
.
getSysType
(),
updatePasswordDTO
.
getNewPassword
());
tokenStore
.
deleteAllToken
(
userInfoInToken
.
getSysType
().
toString
(),
userInfoInToken
.
getUid
());
return
ServerResponseEntity
.
success
();
}
}
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/controller/TokenController.java
0 → 100644
View file @
3ab6e756
package
com.mall4j.cloud.auth.controller
;
import
com.mall4j.cloud.common.security.bo.TokenInfoBO
;
import
com.mall4j.cloud.auth.dto.RefreshTokenDTO
;
import
com.mall4j.cloud.auth.manager.TokenStore
;
import
com.mall4j.cloud.api.auth.vo.TokenInfoVO
;
import
com.mall4j.cloud.common.response.ServerResponseEntity
;
import
io.swagger.v3.oas.annotations.tags.Tag
;
import
com.mall4j.cloud.common.util.BeanUtil
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.PostMapping
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RestController
;
import
jakarta.validation.Valid
;
/**
* @author FrozenWatermelon
* @date 2020/6/30
*/
@RestController
@Tag
(
name
=
"token"
)
public
class
TokenController
{
@Autowired
private
TokenStore
tokenStore
;
@PostMapping
(
"/ua/token/refresh"
)
public
ServerResponseEntity
<
TokenInfoVO
>
refreshToken
(
@Valid
@RequestBody
RefreshTokenDTO
refreshTokenDTO
)
{
ServerResponseEntity
<
TokenInfoBO
>
tokenInfoServerResponseEntity
=
tokenStore
.
refreshToken
(
refreshTokenDTO
.
getRefreshToken
());
if
(!
tokenInfoServerResponseEntity
.
isSuccess
())
{
return
ServerResponseEntity
.
transform
(
tokenInfoServerResponseEntity
);
}
return
ServerResponseEntity
.
success
(
BeanUtil
.
map
(
tokenInfoServerResponseEntity
.
getData
(),
TokenInfoVO
.
class
));
}
}
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/dto/AuthenticationDTO.java
0 → 100644
View file @
3ab6e756
package
com.mall4j.cloud.auth.dto
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
jakarta.validation.constraints.NotBlank
;
import
jakarta.validation.constraints.NotNull
;
/**
* 用于登陆传递账号密码
*
* @author FrozenWatermelon
* @date 2020/7/1
*/
public
class
AuthenticationDTO
{
/**
* 用户名
*/
@NotBlank
(
message
=
"principal不能为空"
)
@Schema
(
description
=
"用户名"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
protected
String
principal
;
/**
* 密码
*/
@NotBlank
(
message
=
"credentials不能为空"
)
@Schema
(
description
=
"一般用作密码"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
protected
String
credentials
;
/**
* sysType 参考SysTypeEnum
*/
@NotNull
(
message
=
"sysType不能为空"
)
@Schema
(
description
=
"系统类型 0.普通用户系统 1.商家端"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
protected
Integer
sysType
;
public
String
getPrincipal
()
{
return
principal
;
}
public
void
setPrincipal
(
String
principal
)
{
this
.
principal
=
principal
;
}
public
String
getCredentials
()
{
return
credentials
;
}
public
void
setCredentials
(
String
credentials
)
{
this
.
credentials
=
credentials
;
}
public
Integer
getSysType
()
{
return
sysType
;
}
public
void
setSysType
(
Integer
sysType
)
{
this
.
sysType
=
sysType
;
}
@Override
public
String
toString
()
{
return
"AuthenticationDTO{"
+
"principal='"
+
principal
+
'\''
+
", credentials='"
+
credentials
+
'\''
+
", sysType="
+
sysType
+
'}'
;
}
}
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/dto/CaptchaAuthenticationDTO.java
0 → 100644
View file @
3ab6e756
package
com.mall4j.cloud.auth.dto
;
import
io.swagger.v3.oas.annotations.media.Schema
;
/**
* 验证码登陆
*
* @author FrozenWatermelon
* @date 2020/7/1
*/
public
class
CaptchaAuthenticationDTO
extends
AuthenticationDTO
{
@Schema
(
description
=
"验证码"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
private
String
captchaVerification
;
public
String
getCaptchaVerification
()
{
return
captchaVerification
;
}
public
void
setCaptchaVerification
(
String
captchaVerification
)
{
this
.
captchaVerification
=
captchaVerification
;
}
@Override
public
String
toString
()
{
return
"CaptchaAuthenticationDTO{"
+
"captchaVerification='"
+
captchaVerification
+
'\''
+
"} "
+
super
.
toString
();
}
}
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/dto/RefreshTokenDTO.java
0 → 100644
View file @
3ab6e756
package
com.mall4j.cloud.auth.dto
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
jakarta.validation.constraints.NotBlank
;
/**
* 刷新token
*
* @author FrozenWatermelon
* @date 2020/7/1
*/
public
class
RefreshTokenDTO
{
/**
* refreshToken
*/
@NotBlank
(
message
=
"refreshToken不能为空"
)
@Schema
(
description
=
"refreshToken"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
private
String
refreshToken
;
public
String
getRefreshToken
()
{
return
refreshToken
;
}
public
void
setRefreshToken
(
String
refreshToken
)
{
this
.
refreshToken
=
refreshToken
;
}
@Override
public
String
toString
()
{
return
"RefreshTokenDTO{"
+
"refreshToken='"
+
refreshToken
+
'\''
+
'}'
;
}
}
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/dto/UpdatePasswordDTO.java
0 → 100644
View file @
3ab6e756
package
com.mall4j.cloud.auth.dto
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
jakarta.validation.constraints.NotBlank
;
import
jakarta.validation.constraints.NotNull
;
/**
* 更新密码
*
* @author FrozenWatermelon
* @date 2020/09/21
*/
public
class
UpdatePasswordDTO
{
@NotBlank
(
message
=
"oldPassword NotBlank"
)
@Schema
(
description
=
"旧密码"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
private
String
oldPassword
;
@NotNull
(
message
=
"newPassword NotNull"
)
@Schema
(
description
=
"新密码"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
private
String
newPassword
;
public
String
getOldPassword
()
{
return
oldPassword
;
}
public
void
setOldPassword
(
String
oldPassword
)
{
this
.
oldPassword
=
oldPassword
;
}
public
String
getNewPassword
()
{
return
newPassword
;
}
public
void
setNewPassword
(
String
newPassword
)
{
this
.
newPassword
=
newPassword
;
}
@Override
public
String
toString
()
{
return
"UpdatePasswordDTO{"
+
"oldPassword='"
+
oldPassword
+
'\''
+
", newPassword='"
+
newPassword
+
'\''
+
'}'
;
}
}
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/feign/AccountFeignController.java
0 → 100644
View file @
3ab6e756
package
com.mall4j.cloud.auth.feign
;
import
cn.hutool.core.util.StrUtil
;
import
com.mall4j.cloud.api.auth.bo.UserInfoInTokenBO
;
import
com.mall4j.cloud.api.auth.constant.SysTypeEnum
;
import
com.mall4j.cloud.api.auth.dto.AuthAccountDTO
;
import
com.mall4j.cloud.api.auth.feign.AccountFeignClient
;
import
com.mall4j.cloud.api.auth.vo.AuthAccountVO
;
import
com.mall4j.cloud.api.leaf.feign.SegmentFeignClient
;
import
com.mall4j.cloud.auth.manager.TokenStore
;
import
com.mall4j.cloud.auth.mapper.AuthAccountMapper
;
import
com.mall4j.cloud.auth.model.AuthAccount
;
import
com.mall4j.cloud.common.exception.Mall4cloudException
;
import
com.mall4j.cloud.common.response.ResponseEnum
;
import
com.mall4j.cloud.common.response.ServerResponseEntity
;
import
com.mall4j.cloud.common.security.AuthUserContext
;
import
com.mall4j.cloud.common.security.bo.AuthAccountInVerifyBO
;
import
com.mall4j.cloud.common.security.constant.InputUserNameEnum
;
import
com.mall4j.cloud.api.auth.vo.TokenInfoVO
;
import
com.mall4j.cloud.common.util.PrincipalUtil
;
import
com.mall4j.cloud.common.util.BeanUtil
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.security.crypto.password.PasswordEncoder
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.web.bind.annotation.RestController
;
import
java.util.Objects
;
/**
* @author FrozenWatermelon
* @date 2020/9/22
*/
@RestController
public
class
AccountFeignController
implements
AccountFeignClient
{
@Autowired
private
AuthAccountMapper
authAccountMapper
;
@Autowired
private
PasswordEncoder
passwordEncoder
;
@Autowired
private
TokenStore
tokenStore
;
@Autowired
private
SegmentFeignClient
segmentFeignClient
;
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
ServerResponseEntity
<
Long
>
save
(
AuthAccountDTO
authAccountDTO
)
{
ServerResponseEntity
<
Long
>
segmentIdResponse
=
segmentFeignClient
.
getSegmentId
(
"mall4cloud-auth-account"
);
if
(!
segmentIdResponse
.
isSuccess
())
{
throw
new
Mall4cloudException
(
ResponseEnum
.
EXCEPTION
);
}
ServerResponseEntity
<
AuthAccount
>
verify
=
verify
(
authAccountDTO
);
if
(!
verify
.
isSuccess
())
{
return
ServerResponseEntity
.
transform
(
verify
);
}
AuthAccount
data
=
verify
.
getData
();
data
.
setUid
(
segmentIdResponse
.
getData
());
authAccountMapper
.
save
(
data
);
return
ServerResponseEntity
.
success
(
data
.
getUid
());
}
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
ServerResponseEntity
<
Void
>
update
(
AuthAccountDTO
authAccountDTO
)
{
ServerResponseEntity
<
AuthAccount
>
verify
=
verify
(
authAccountDTO
);
if
(!
verify
.
isSuccess
())
{
return
ServerResponseEntity
.
transform
(
verify
);
}
authAccountMapper
.
updateAccountInfo
(
verify
.
getData
());
return
ServerResponseEntity
.
success
();
}
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
ServerResponseEntity
<
Void
>
updateAuthAccountStatus
(
AuthAccountDTO
authAccountDTO
)
{
if
(
Objects
.
isNull
(
authAccountDTO
.
getStatus
()))
{
throw
new
Mall4cloudException
(
ResponseEnum
.
EXCEPTION
);
}
AuthAccount
authAccount
=
BeanUtil
.
map
(
authAccountDTO
,
AuthAccount
.
class
);
authAccountMapper
.
updateAccountInfo
(
authAccount
);
return
ServerResponseEntity
.
success
();
}
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
ServerResponseEntity
<
Void
>
deleteByUserIdAndSysType
(
Long
userId
)
{
UserInfoInTokenBO
userInfoInTokenBO
=
AuthUserContext
.
get
();
authAccountMapper
.
deleteByUserIdAndSysType
(
userId
,
userInfoInTokenBO
.
getSysType
());
return
ServerResponseEntity
.
success
();
}
@Override
public
ServerResponseEntity
<
AuthAccountVO
>
getByUserIdAndSysType
(
Long
userId
,
Integer
sysType
)
{
UserInfoInTokenBO
userInfoInTokenBO
=
AuthUserContext
.
get
();
AuthAccount
authAccount
=
authAccountMapper
.
getByUserIdAndType
(
userId
,
userInfoInTokenBO
.
getSysType
());
return
ServerResponseEntity
.
success
(
BeanUtil
.
map
(
authAccount
,
AuthAccountVO
.
class
));
}
@Override
public
ServerResponseEntity
<
TokenInfoVO
>
storeTokenAndGetVo
(
UserInfoInTokenBO
userInfoInTokenBO
)
{
return
ServerResponseEntity
.
success
(
tokenStore
.
storeAndGetVo
(
userInfoInTokenBO
));
}
@Override
public
ServerResponseEntity
<
AuthAccountVO
>
getByUsernameAndSysType
(
String
username
,
SysTypeEnum
sysType
)
{
return
ServerResponseEntity
.
success
(
authAccountMapper
.
getByUsernameAndSysType
(
username
,
sysType
.
value
()));
}
private
ServerResponseEntity
<
AuthAccount
>
verify
(
AuthAccountDTO
authAccountDTO
)
{
// 用户名
if
(!
PrincipalUtil
.
isUserName
(
authAccountDTO
.
getUsername
()))
{
return
ServerResponseEntity
.
showFailMsg
(
"用户名格式不正确"
);
}
AuthAccountInVerifyBO
userNameBo
=
authAccountMapper
.
getAuthAccountInVerifyByInputUserName
(
InputUserNameEnum
.
USERNAME
.
value
(),
authAccountDTO
.
getUsername
(),
authAccountDTO
.
getSysType
());
if
(
userNameBo
!=
null
&&
!
Objects
.
equals
(
userNameBo
.
getUserId
(),
authAccountDTO
.
getUserId
()))
{
return
ServerResponseEntity
.
showFailMsg
(
"用户名已存在,请更换用户名再次尝试"
);
}
AuthAccount
authAccount
=
BeanUtil
.
map
(
authAccountDTO
,
AuthAccount
.
class
);
if
(
StrUtil
.
isNotBlank
(
authAccount
.
getPassword
()))
{
authAccount
.
setPassword
(
passwordEncoder
.
encode
(
authAccount
.
getPassword
()));
}
return
ServerResponseEntity
.
success
(
authAccount
);
}
@Override
@Transactional
(
rollbackFor
=
Exception
.
class
)
public
ServerResponseEntity
<
Void
>
updateUserInfoByUserIdAndSysType
(
UserInfoInTokenBO
userInfoInTokenBO
,
Long
userId
,
Integer
sysType
)
{
AuthAccount
byUserIdAndType
=
authAccountMapper
.
getByUserIdAndType
(
userId
,
sysType
);
userInfoInTokenBO
.
setUid
(
byUserIdAndType
.
getUid
());
tokenStore
.
updateUserInfoByUidAndAppId
(
byUserIdAndType
.
getUid
(),
sysType
.
toString
(),
userInfoInTokenBO
);
AuthAccount
authAccount
=
BeanUtil
.
map
(
userInfoInTokenBO
,
AuthAccount
.
class
);
int
res
=
authAccountMapper
.
updateUserInfoByUserId
(
authAccount
,
userId
,
sysType
);
if
(
res
!=
1
)
{
throw
new
Mall4cloudException
(
"用户信息错误,更新失败"
);
}
return
ServerResponseEntity
.
success
();
}
@Override
public
ServerResponseEntity
<
AuthAccountVO
>
getMerchantInfoByTenantId
(
Long
tenantId
)
{
AuthAccountVO
authAccountVO
=
authAccountMapper
.
getMerchantInfoByTenantId
(
tenantId
);
return
ServerResponseEntity
.
success
(
authAccountVO
);
}
}
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/feign/TokenFeignController.java
0 → 100644
View file @
3ab6e756
package
com.mall4j.cloud.auth.feign
;
import
com.mall4j.cloud.api.auth.bo.UserInfoInTokenBO
;
import
com.mall4j.cloud.api.auth.feign.TokenFeignClient
;
import
com.mall4j.cloud.auth.manager.TokenStore
;
import
com.mall4j.cloud.common.response.ServerResponseEntity
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.RestController
;
/**
* @author FrozenWatermelon
* @date 2020/7/15
*/
@RestController
public
class
TokenFeignController
implements
TokenFeignClient
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
TokenFeignController
.
class
);
@Autowired
private
TokenStore
tokenStore
;
@Override
public
ServerResponseEntity
<
UserInfoInTokenBO
>
checkToken
(
String
accessToken
)
{
ServerResponseEntity
<
UserInfoInTokenBO
>
userInfoByAccessTokenResponse
=
tokenStore
.
getUserInfoByAccessToken
(
accessToken
,
true
);
if
(!
userInfoByAccessTokenResponse
.
isSuccess
())
{
return
ServerResponseEntity
.
transform
(
userInfoByAccessTokenResponse
);
}
return
ServerResponseEntity
.
success
(
userInfoByAccessTokenResponse
.
getData
());
}
}
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/manager/TokenStore.java
0 → 100644
View file @
3ab6e756
package
com.mall4j.cloud.auth.manager
;
import
cn.hutool.core.codec.Base64
;
import
cn.hutool.core.collection.CollUtil
;
import
cn.hutool.core.util.BooleanUtil
;
import
cn.hutool.core.util.IdUtil
;
import
cn.hutool.core.util.StrUtil
;
import
cn.hutool.crypto.symmetric.AES
;
import
com.mall4j.cloud.common.cache.constant.CacheNames
;
import
com.mall4j.cloud.common.exception.Mall4cloudException
;
import
com.mall4j.cloud.common.response.ResponseEnum
;
import
com.mall4j.cloud.common.security.bo.TokenInfoBO
;
import
com.mall4j.cloud.api.auth.bo.UserInfoInTokenBO
;
import
com.mall4j.cloud.api.auth.constant.SysTypeEnum
;
import
com.mall4j.cloud.common.response.ServerResponseEntity
;
import
com.mall4j.cloud.api.auth.vo.TokenInfoVO
;
import
com.mall4j.cloud.common.util.PrincipalUtil
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.cloud.context.config.annotation.RefreshScope
;
import
org.springframework.data.redis.core.RedisCallback
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.data.redis.core.StringRedisTemplate
;
import
org.springframework.data.redis.serializer.RedisSerializer
;
import
org.springframework.stereotype.Component
;
import
java.nio.charset.StandardCharsets
;
import
java.util.*
;
import
java.util.concurrent.TimeUnit
;
/**
* token管理 1. 登陆返回token 2. 刷新token 3. 清除用户过去token 4. 校验token
*
* @author FrozenWatermelon
* @date 2020/7/2
*/
@Component
@RefreshScope
public
class
TokenStore
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
TokenStore
.
class
);
private
final
RedisTemplate
<
Object
,
Object
>
redisTemplate
;
private
final
RedisSerializer
<
Object
>
redisSerializer
;
private
final
StringRedisTemplate
stringRedisTemplate
;
public
TokenStore
(
RedisTemplate
<
Object
,
Object
>
redisTemplate
,
RedisSerializer
<
Object
>
redisSerializer
,
StringRedisTemplate
stringRedisTemplate
)
{
this
.
redisTemplate
=
redisTemplate
;
this
.
redisSerializer
=
redisSerializer
;
this
.
stringRedisTemplate
=
stringRedisTemplate
;
}
/**
* 将用户的部分信息存储在token中,并返回token信息
* @param userInfoInToken 用户在token中的信息
* @return token信息
*/
public
TokenInfoBO
storeAccessToken
(
UserInfoInTokenBO
userInfoInToken
)
{
TokenInfoBO
tokenInfoBO
=
new
TokenInfoBO
();
String
accessToken
=
IdUtil
.
simpleUUID
();
String
refreshToken
=
IdUtil
.
simpleUUID
();
tokenInfoBO
.
setUserInfoInToken
(
userInfoInToken
);
tokenInfoBO
.
setExpiresIn
(
getExpiresIn
(
userInfoInToken
.
getSysType
()));
String
uidToAccessKeyStr
=
getUidToAccessKey
(
getApprovalKey
(
userInfoInToken
));
String
accessKeyStr
=
getAccessKey
(
accessToken
);
String
refreshToAccessKeyStr
=
getRefreshToAccessKey
(
refreshToken
);
// 一个用户会登陆很多次,每次登陆的token都会存在 uid_to_access里面
// 但是每次保存都会更新这个key的时间,而key里面的token有可能会过期,过期就要移除掉
List
<
String
>
existsAccessTokens
=
new
ArrayList
<>();
// 新的token数据
existsAccessTokens
.
add
(
accessToken
+
StrUtil
.
COLON
+
refreshToken
);
Long
size
=
redisTemplate
.
opsForSet
().
size
(
uidToAccessKeyStr
);
if
(
size
!=
null
&&
size
!=
0
)
{
List
<
String
>
tokenInfoBoList
=
stringRedisTemplate
.
opsForSet
().
pop
(
uidToAccessKeyStr
,
size
);
if
(
tokenInfoBoList
!=
null
)
{
for
(
String
accessTokenWithRefreshToken
:
tokenInfoBoList
)
{
String
[]
accessTokenWithRefreshTokenArr
=
accessTokenWithRefreshToken
.
split
(
StrUtil
.
COLON
);
String
accessTokenData
=
accessTokenWithRefreshTokenArr
[
0
];
if
(
BooleanUtil
.
isTrue
(
stringRedisTemplate
.
hasKey
(
getAccessKey
(
accessTokenData
))))
{
existsAccessTokens
.
add
(
accessTokenWithRefreshToken
);
}
}
}
}
redisTemplate
.
executePipelined
((
RedisCallback
<
Object
>)
connection
->
{
long
expiresIn
=
tokenInfoBO
.
getExpiresIn
();
byte
[]
uidKey
=
uidToAccessKeyStr
.
getBytes
(
StandardCharsets
.
UTF_8
);
byte
[]
refreshKey
=
refreshToAccessKeyStr
.
getBytes
(
StandardCharsets
.
UTF_8
);
byte
[]
accessKey
=
accessKeyStr
.
getBytes
(
StandardCharsets
.
UTF_8
);
for
(
String
existsAccessToken
:
existsAccessTokens
)
{
connection
.
sAdd
(
uidKey
,
existsAccessToken
.
getBytes
(
StandardCharsets
.
UTF_8
));
}
// 通过uid + sysType 保存access_token,当需要禁用用户的时候,可以根据uid + sysType 禁用用户
connection
.
expire
(
uidKey
,
expiresIn
);
// 通过refresh_token获取用户的access_token从而刷新token
connection
.
setEx
(
refreshKey
,
expiresIn
,
accessToken
.
getBytes
(
StandardCharsets
.
UTF_8
));
// 通过access_token保存用户的租户id,用户id,uid
connection
.
setEx
(
accessKey
,
expiresIn
,
Objects
.
requireNonNull
(
redisSerializer
.
serialize
(
userInfoInToken
)));
return
null
;
});
// 返回给前端是加密的token
tokenInfoBO
.
setAccessToken
(
encryptToken
(
accessToken
,
userInfoInToken
.
getSysType
()));
tokenInfoBO
.
setRefreshToken
(
encryptToken
(
refreshToken
,
userInfoInToken
.
getSysType
()));
return
tokenInfoBO
;
}
private
int
getExpiresIn
(
int
sysType
)
{
// 3600秒
int
expiresIn
=
3600
;
// 普通用户token过期时间 1小时
if
(
Objects
.
equals
(
sysType
,
SysTypeEnum
.
ORDINARY
.
value
()))
{
expiresIn
=
expiresIn
*
24
*
30
;
}
// 系统管理员的token过期时间 2小时
if
(
Objects
.
equals
(
sysType
,
SysTypeEnum
.
MULTISHOP
.
value
())
||
Objects
.
equals
(
sysType
,
SysTypeEnum
.
PLATFORM
.
value
()))
{
expiresIn
=
expiresIn
*
24
*
30
;
}
return
expiresIn
;
}
/**
* 根据accessToken 获取用户信息
* @param accessToken accessToken
* @param needDecrypt 是否需要解密
* @return 用户信息
*/
public
ServerResponseEntity
<
UserInfoInTokenBO
>
getUserInfoByAccessToken
(
String
accessToken
,
boolean
needDecrypt
)
{
if
(
StrUtil
.
isBlank
(
accessToken
))
{
return
ServerResponseEntity
.
showFailMsg
(
"accessToken is blank"
);
}
String
realAccessToken
;
if
(
needDecrypt
)
{
ServerResponseEntity
<
String
>
decryptTokenEntity
=
decryptToken
(
accessToken
);
if
(!
decryptTokenEntity
.
isSuccess
())
{
return
ServerResponseEntity
.
transform
(
decryptTokenEntity
);
}
realAccessToken
=
decryptTokenEntity
.
getData
();
}
else
{
realAccessToken
=
accessToken
;
}
UserInfoInTokenBO
userInfoInTokenBO
=
(
UserInfoInTokenBO
)
redisTemplate
.
opsForValue
()
.
get
(
getAccessKey
(
realAccessToken
));
if
(
userInfoInTokenBO
==
null
)
{
return
ServerResponseEntity
.
showFailMsg
(
"accessToken 已过期"
);
}
return
ServerResponseEntity
.
success
(
userInfoInTokenBO
);
}
/**
* 刷新token,并返回新的token
* @param refreshToken
* @return
*/
public
ServerResponseEntity
<
TokenInfoBO
>
refreshToken
(
String
refreshToken
)
{
if
(
StrUtil
.
isBlank
(
refreshToken
))
{
return
ServerResponseEntity
.
showFailMsg
(
"refreshToken is blank"
);
}
ServerResponseEntity
<
String
>
decryptTokenEntity
=
decryptToken
(
refreshToken
);
if
(!
decryptTokenEntity
.
isSuccess
())
{
return
ServerResponseEntity
.
transform
(
decryptTokenEntity
);
}
String
realRefreshToken
=
decryptTokenEntity
.
getData
();
String
accessToken
=
stringRedisTemplate
.
opsForValue
().
get
(
getRefreshToAccessKey
(
realRefreshToken
));
if
(
StrUtil
.
isBlank
(
accessToken
))
{
return
ServerResponseEntity
.
showFailMsg
(
"refreshToken 已过期"
);
}
ServerResponseEntity
<
UserInfoInTokenBO
>
userInfoByAccessTokenEntity
=
getUserInfoByAccessToken
(
accessToken
,
false
);
if
(!
userInfoByAccessTokenEntity
.
isSuccess
())
{
return
ServerResponseEntity
.
showFailMsg
(
"refreshToken 已过期"
);
}
UserInfoInTokenBO
userInfoInTokenBO
=
userInfoByAccessTokenEntity
.
getData
();
// 删除旧的refresh_token
stringRedisTemplate
.
delete
(
getRefreshToAccessKey
(
realRefreshToken
));
// 删除旧的access_token
stringRedisTemplate
.
delete
(
getAccessKey
(
accessToken
));
// 保存一份新的token
TokenInfoBO
tokenInfoBO
=
storeAccessToken
(
userInfoInTokenBO
);
return
ServerResponseEntity
.
success
(
tokenInfoBO
);
}
/**
* 删除全部的token
*/
public
void
deleteAllToken
(
String
appId
,
Long
uid
)
{
String
uidKey
=
getUidToAccessKey
(
getApprovalKey
(
appId
,
uid
));
Long
size
=
redisTemplate
.
opsForSet
().
size
(
uidKey
);
if
(
size
==
null
||
size
==
0
)
{
return
;
}
List
<
String
>
tokenInfoBoList
=
stringRedisTemplate
.
opsForSet
().
pop
(
uidKey
,
size
);
if
(
CollUtil
.
isEmpty
(
tokenInfoBoList
))
{
return
;
}
for
(
String
accessTokenWithRefreshToken
:
tokenInfoBoList
)
{
String
[]
accessTokenWithRefreshTokenArr
=
accessTokenWithRefreshToken
.
split
(
StrUtil
.
COLON
);
String
accessToken
=
accessTokenWithRefreshTokenArr
[
0
];
String
refreshToken
=
accessTokenWithRefreshTokenArr
[
1
];
redisTemplate
.
delete
(
getRefreshToAccessKey
(
refreshToken
));
redisTemplate
.
delete
(
getAccessKey
(
accessToken
));
}
redisTemplate
.
delete
(
uidKey
);
}
private
static
String
getApprovalKey
(
UserInfoInTokenBO
userInfoInToken
)
{
return
getApprovalKey
(
userInfoInToken
.
getSysType
().
toString
(),
userInfoInToken
.
getUid
());
}
private
static
String
getApprovalKey
(
String
appId
,
Long
uid
)
{
return
uid
==
null
?
appId
:
appId
+
StrUtil
.
COLON
+
uid
;
}
private
String
encryptToken
(
String
accessToken
,
Integer
sysType
)
{
return
Base64
.
encode
(
accessToken
+
System
.
currentTimeMillis
()
+
sysType
);
}
private
ServerResponseEntity
<
String
>
decryptToken
(
String
data
)
{
String
decryptStr
;
String
decryptToken
;
try
{
decryptStr
=
Base64
.
decodeStr
(
data
);
decryptToken
=
decryptStr
.
substring
(
0
,
32
);
// 创建token的时间,token使用时效性,防止攻击者通过一堆的尝试找到aes的密码,虽然aes是目前几乎最好的加密算法
long
createTokenTime
=
Long
.
parseLong
(
decryptStr
.
substring
(
32
,
45
));
// 系统类型
int
sysType
=
Integer
.
parseInt
(
decryptStr
.
substring
(
45
));
// token的过期时间
int
expiresIn
=
getExpiresIn
(
sysType
);
long
second
=
1000L
;
if
(
System
.
currentTimeMillis
()
-
createTokenTime
>
expiresIn
*
second
)
{
return
ServerResponseEntity
.
showFailMsg
(
"token 格式有误"
);
}
}
catch
(
Exception
e
)
{
logger
.
error
(
e
.
getMessage
());
return
ServerResponseEntity
.
showFailMsg
(
"token 格式有误"
);
}
// 防止解密后的token是脚本,从而对redis进行攻击,uuid只能是数字和小写字母
if
(!
PrincipalUtil
.
isSimpleChar
(
decryptToken
))
{
return
ServerResponseEntity
.
showFailMsg
(
"token 格式有误"
);
}
return
ServerResponseEntity
.
success
(
decryptToken
);
}
public
String
getAccessKey
(
String
accessToken
)
{
return
CacheNames
.
ACCESS
+
accessToken
;
}
public
String
getUidToAccessKey
(
String
approvalKey
)
{
return
CacheNames
.
UID_TO_ACCESS
+
approvalKey
;
}
public
String
getRefreshToAccessKey
(
String
refreshToken
)
{
return
CacheNames
.
REFRESH_TO_ACCESS
+
refreshToken
;
}
public
TokenInfoVO
storeAndGetVo
(
UserInfoInTokenBO
userInfoInToken
)
{
TokenInfoBO
tokenInfoBO
=
storeAccessToken
(
userInfoInToken
);
TokenInfoVO
tokenInfoVO
=
new
TokenInfoVO
();
tokenInfoVO
.
setAccessToken
(
tokenInfoBO
.
getAccessToken
());
tokenInfoVO
.
setRefreshToken
(
tokenInfoBO
.
getRefreshToken
());
tokenInfoVO
.
setExpiresIn
(
tokenInfoBO
.
getExpiresIn
());
return
tokenInfoVO
;
}
public
void
updateUserInfoByUidAndAppId
(
Long
uid
,
String
appId
,
UserInfoInTokenBO
userInfoInTokenBO
)
{
if
(
userInfoInTokenBO
==
null
)
{
return
;
}
String
uidKey
=
getUidToAccessKey
(
getApprovalKey
(
appId
,
uid
));
Set
<
String
>
tokenInfoBoList
=
stringRedisTemplate
.
opsForSet
().
members
(
uidKey
);
if
(
tokenInfoBoList
==
null
||
tokenInfoBoList
.
size
()
==
0
)
{
throw
new
Mall4cloudException
(
ResponseEnum
.
UNAUTHORIZED
);
}
for
(
String
accessTokenWithRefreshToken
:
tokenInfoBoList
)
{
String
[]
accessTokenWithRefreshTokenArr
=
accessTokenWithRefreshToken
.
split
(
StrUtil
.
COLON
);
String
accessKey
=
this
.
getAccessKey
(
accessTokenWithRefreshTokenArr
[
0
]);
UserInfoInTokenBO
oldUserInfoInTokenBO
=
(
UserInfoInTokenBO
)
redisTemplate
.
opsForValue
().
get
(
accessKey
);
if
(
oldUserInfoInTokenBO
==
null
)
{
continue
;
}
BeanUtils
.
copyProperties
(
userInfoInTokenBO
,
oldUserInfoInTokenBO
);
redisTemplate
.
opsForValue
().
set
(
accessKey
,
Objects
.
requireNonNull
(
userInfoInTokenBO
),
getExpiresIn
(
userInfoInTokenBO
.
getSysType
()),
TimeUnit
.
SECONDS
);
}
}
}
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/mapper/AuthAccountMapper.java
0 → 100644
View file @
3ab6e756
package
com.mall4j.cloud.auth.mapper
;
import
com.mall4j.cloud.api.auth.vo.AuthAccountVO
;
import
com.mall4j.cloud.auth.model.AuthAccount
;
import
com.mall4j.cloud.common.security.bo.AuthAccountInVerifyBO
;
import
org.apache.ibatis.annotations.Param
;
/**
* @author FrozenWatermelon
* @date 2020/7/2
*/
public
interface
AuthAccountMapper
{
/**
* 根据输入的用户名及用户名类型获取用户信息
*
* @param inputUserNameType 输入的用户名类型 1.username 2.mobile 3.email
* @param inputUserName 输入的用户名
* @param sysType 系统类型
* @return 用户在token中信息 + 数据库中的密码
*/
AuthAccountInVerifyBO
getAuthAccountInVerifyByInputUserName
(
@Param
(
"inputUserNameType"
)
Integer
inputUserNameType
,
@Param
(
"inputUserName"
)
String
inputUserName
,
@Param
(
"sysType"
)
Integer
sysType
);
/**
* 根据用户id 和系统类型获取平台唯一用户
*
* @param userId 用户id
* @param sysType 系统类型
* @return 平台唯一用户
*/
AuthAccount
getByUserIdAndType
(
@Param
(
"userId"
)
Long
userId
,
@Param
(
"sysType"
)
Integer
sysType
);
/**
* 根据getByUid获取平台唯一用户
*
* @param uid uid
* @return 平台唯一用户
*/
AuthAccount
getByUid
(
@Param
(
"uid"
)
Long
uid
);
/**
* 更新密码 根据用户id 和系统类型
*
* @param userId 用户id
* @param sysType 系统类型
* @param newPassWord 新密码
*/
void
updatePassword
(
@Param
(
"userId"
)
Long
userId
,
@Param
(
"sysType"
)
Integer
sysType
,
@Param
(
"newPassWord"
)
String
newPassWord
);
/**
* 保存
*
* @param authAccount
*/
void
save
(
@Param
(
"authAccount"
)
AuthAccount
authAccount
);
/**
* 更新
*
* @param authAccount authAccount
*/
void
updateAccountInfo
(
@Param
(
"authAccount"
)
AuthAccount
authAccount
);
/**
* 根据用户id和系统类型删除用户
*
* @param userId 用户id
* @param sysType 系统类型
*/
void
deleteByUserIdAndSysType
(
@Param
(
"userId"
)
Long
userId
,
@Param
(
"sysType"
)
Integer
sysType
);
/**
* 根据用户名和系统类型获取用户信息
* @param validAccount
* @param systemType
* @return uid
*/
AuthAccount
getAccountByInputUserName
(
@Param
(
"validAccount"
)
String
validAccount
,
@Param
(
"systemType"
)
Integer
systemType
);
/**
* 根据用户名和系统类型获取用户信息
* @param username
* @param sysType
* @return
*/
AuthAccountVO
getByUsernameAndSysType
(
@Param
(
"userName"
)
String
username
,
@Param
(
"sysType"
)
Integer
sysType
);
/**
* 根据用户id更新租户id
* @param authAccount
* @param userId
* @param sysType
* @return
*/
int
updateUserInfoByUserId
(
@Param
(
"authAccount"
)
AuthAccount
authAccount
,
@Param
(
"userId"
)
Long
userId
,
@Param
(
"sysType"
)
Integer
sysType
);
/**
* 根据租户id获取商家信息
* @param tenantId
* @return
*/
AuthAccountVO
getMerchantInfoByTenantId
(
@Param
(
"tenantId"
)
Long
tenantId
);
}
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/model/AuthAccount.java
0 → 100644
View file @
3ab6e756
package
com.mall4j.cloud.auth.model
;
import
com.mall4j.cloud.common.database.annotations.DistributedId
;
import
com.mall4j.cloud.common.model.BaseModel
;
/**
* 统一账户信息
*
* @author FrozenWatermelon
* @date 2020/07/02
*/
public
class
AuthAccount
extends
BaseModel
{
/**
* 全平台用户唯一id
*/
@DistributedId
(
"mall4cloud-auth-account"
)
private
Long
uid
;
/**
* 用户名
*/
private
String
username
;
/**
* 密码
*/
private
String
password
;
/**
* 创建ip
*/
private
String
createIp
;
/**
* 状态 1:启用 0:禁用 -1:删除
*/
private
Integer
status
;
/**
* 系统类型见SysTypeEnum 0.普通用户系统 1.商家端
*/
private
Integer
sysType
;
/**
* 用户id
*/
private
Long
userId
;
/**
* 所属租户
*/
private
Long
tenantId
;
/**
* 是否是管理员
*/
private
Integer
isAdmin
;
public
Long
getUid
()
{
return
uid
;
}
public
void
setUid
(
Long
uid
)
{
this
.
uid
=
uid
;
}
public
String
getUsername
()
{
return
username
;
}
public
void
setUsername
(
String
username
)
{
this
.
username
=
username
;
}
public
String
getPassword
()
{
return
password
;
}
public
void
setPassword
(
String
password
)
{
this
.
password
=
password
;
}
public
String
getCreateIp
()
{
return
createIp
;
}
public
void
setCreateIp
(
String
createIp
)
{
this
.
createIp
=
createIp
;
}
public
Integer
getStatus
()
{
return
status
;
}
public
void
setStatus
(
Integer
status
)
{
this
.
status
=
status
;
}
public
Integer
getSysType
()
{
return
sysType
;
}
public
void
setSysType
(
Integer
sysType
)
{
this
.
sysType
=
sysType
;
}
public
Long
getUserId
()
{
return
userId
;
}
public
void
setUserId
(
Long
userId
)
{
this
.
userId
=
userId
;
}
public
Long
getTenantId
()
{
return
tenantId
;
}
public
void
setTenantId
(
Long
tenantId
)
{
this
.
tenantId
=
tenantId
;
}
public
Integer
getIsAdmin
()
{
return
isAdmin
;
}
public
void
setIsAdmin
(
Integer
isAdmin
)
{
this
.
isAdmin
=
isAdmin
;
}
@Override
public
String
toString
()
{
return
"AuthAccount{"
+
"uid="
+
uid
+
", username='"
+
username
+
'\''
+
", password='"
+
password
+
'\''
+
", createIp='"
+
createIp
+
'\''
+
", status="
+
status
+
", sysType="
+
sysType
+
", userId="
+
userId
+
", tenantId="
+
tenantId
+
", isAdmin="
+
isAdmin
+
'}'
;
}
}
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/service/AuthAccountService.java
0 → 100644
View file @
3ab6e756
package
com.mall4j.cloud.auth.service
;
import
com.mall4j.cloud.api.auth.bo.UserInfoInTokenBO
;
import
com.mall4j.cloud.auth.model.AuthAccount
;
import
com.mall4j.cloud.common.response.ServerResponseEntity
;
/**
* 统一账户信息
*
* @author FrozenWatermelon
* @date 2020/7/2
*/
public
interface
AuthAccountService
{
/**
* 通过输入的用户名密码,校验并获取部分用户信息
* @param inputUserName 输入的用户名(用户名)
* @param password 密码
* @param sysType 系统类型 @see SysTypeEnum
* @return 用户在token中信息
*/
ServerResponseEntity
<
UserInfoInTokenBO
>
getUserInfoInTokenByInputUserNameAndPassword
(
String
inputUserName
,
String
password
,
Integer
sysType
);
/**
* 根据用户id 和系统类型获取平台唯一用户
* @param userId 用户id
* @param sysType 系统类型
* @return 平台唯一用户
*/
AuthAccount
getByUserIdAndType
(
Long
userId
,
Integer
sysType
);
/**
* 更新密码 根据用户id 和系统类型
* @param userId 用户id
* @param sysType 系统类型
* @param newPassWord 新密码
*/
void
updatePassword
(
Long
userId
,
Integer
sysType
,
String
newPassWord
);
/**
* 根据getByUid获取平台唯一用户
*
* @param uid uid
* @return 平台唯一用户
*/
AuthAccount
getByUid
(
Long
uid
);
/**
* 根据用户名获取用户信息
* @param username 用户名
* @param systemType 系统类型
* @return uid
*/
AuthAccount
getAccountByInputUserName
(
String
username
,
Integer
systemType
);
}
mall4cloud-auth/src/main/java/com/mall4j/cloud/auth/service/impl/AuthAccountServiceImpl.java
0 → 100644
View file @
3ab6e756
package
com.mall4j.cloud.auth.service.impl
;
import
cn.hutool.core.util.StrUtil
;
import
com.mall4j.cloud.auth.constant.AuthAccountStatusEnum
;
import
com.mall4j.cloud.auth.model.AuthAccount
;
import
com.mall4j.cloud.common.security.bo.AuthAccountInVerifyBO
;
import
com.mall4j.cloud.api.auth.bo.UserInfoInTokenBO
;
import
com.mall4j.cloud.common.security.constant.InputUserNameEnum
;
import
com.mall4j.cloud.auth.mapper.AuthAccountMapper
;
import
com.mall4j.cloud.auth.service.AuthAccountService
;
import
com.mall4j.cloud.common.response.ServerResponseEntity
;
import
com.mall4j.cloud.common.util.PrincipalUtil
;
import
jakarta.annotation.Resource
;
import
com.mall4j.cloud.common.util.BeanUtil
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.security.crypto.password.PasswordEncoder
;
import
org.springframework.stereotype.Service
;
import
java.util.Objects
;
/**
* @author FrozenWatermelon
* @date 2020/7/2
*/
@Service
public
class
AuthAccountServiceImpl
implements
AuthAccountService
{
@Resource
private
AuthAccountMapper
authAccountMapper
;
@Autowired
private
PasswordEncoder
passwordEncoder
;
public
static
final
String
USER_NOT_FOUND_SECRET
=
"USER_NOT_FOUND_SECRET"
;
private
static
String
userNotFoundEncodedPassword
;
@Override
public
ServerResponseEntity
<
UserInfoInTokenBO
>
getUserInfoInTokenByInputUserNameAndPassword
(
String
inputUserName
,
String
password
,
Integer
sysType
)
{
if
(
StrUtil
.
isBlank
(
inputUserName
))
{
return
ServerResponseEntity
.
showFailMsg
(
"用户名不能为空"
);
}
if
(
StrUtil
.
isBlank
(
password
))
{
return
ServerResponseEntity
.
showFailMsg
(
"密码不能为空"
);
}
InputUserNameEnum
inputUserNameEnum
=
null
;
// 用户名
if
(
PrincipalUtil
.
isUserName
(
inputUserName
))
{
inputUserNameEnum
=
InputUserNameEnum
.
USERNAME
;
}
if
(
inputUserNameEnum
==
null
)
{
return
ServerResponseEntity
.
showFailMsg
(
"请输入正确的用户名"
);
}
AuthAccountInVerifyBO
authAccountInVerifyBO
=
authAccountMapper
.
getAuthAccountInVerifyByInputUserName
(
inputUserNameEnum
.
value
(),
inputUserName
,
sysType
);
if
(
authAccountInVerifyBO
==
null
)
{
prepareTimingAttackProtection
();
// 再次进行运算,防止计时攻击
// 计时攻击(Timing
// attack),通过设备运算的用时来推断出所使用的运算操作,或者通过对比运算的时间推定数据位于哪个存储设备,或者利用通信的时间差进行数据窃取。
mitigateAgainstTimingAttack
(
password
);
return
ServerResponseEntity
.
showFailMsg
(
"用户名或密码不正确"
);
}
if
(
Objects
.
equals
(
authAccountInVerifyBO
.
getStatus
(),
AuthAccountStatusEnum
.
DISABLE
.
value
()))
{
return
ServerResponseEntity
.
showFailMsg
(
"用户已禁用,请联系客服"
);
}
if
(!
passwordEncoder
.
matches
(
password
,
authAccountInVerifyBO
.
getPassword
()))
{
return
ServerResponseEntity
.
showFailMsg
(
"用户名或密码不正确"
);
}
return
ServerResponseEntity
.
success
(
BeanUtil
.
map
(
authAccountInVerifyBO
,
UserInfoInTokenBO
.
class
));
}
@Override
public
AuthAccount
getByUserIdAndType
(
Long
userId
,
Integer
sysType
)
{
return
authAccountMapper
.
getByUserIdAndType
(
userId
,
sysType
);
}
@Override
public
void
updatePassword
(
Long
userId
,
Integer
sysType
,
String
newPassWord
)
{
authAccountMapper
.
updatePassword
(
userId
,
sysType
,
passwordEncoder
.
encode
(
newPassWord
));
}
@Override
public
AuthAccount
getByUid
(
Long
uid
)
{
return
authAccountMapper
.
getByUid
(
uid
);
}
@Override
public
AuthAccount
getAccountByInputUserName
(
String
mobile
,
Integer
systemType
)
{
return
authAccountMapper
.
getAccountByInputUserName
(
mobile
,
systemType
);
}
/**
* 防止计时攻击
*/
private
void
prepareTimingAttackProtection
()
{
if
(
userNotFoundEncodedPassword
==
null
)
{
userNotFoundEncodedPassword
=
this
.
passwordEncoder
.
encode
(
USER_NOT_FOUND_SECRET
);
}
}
/**
* 防止计时攻击
*/
private
void
mitigateAgainstTimingAttack
(
String
presentedPassword
)
{
if
(
presentedPassword
!=
null
)
{
this
.
passwordEncoder
.
matches
(
presentedPassword
,
userNotFoundEncodedPassword
);
}
}
}
mall4cloud-auth/src/main/resources/META-INF/services/com.anji.captcha.service.CaptchaCacheService
0 → 100644
View file @
3ab6e756
com.anji.captcha.service.impl.CaptchaCacheServiceMemImpl
com.mall4j.cloud.auth.adapter.CaptchaCacheServiceRedisImpl
mall4cloud-auth/src/main/resources/bootstrap.yml
0 → 100644
View file @
3ab6e756
server
:
port
:
9101
spring
:
application
:
name
:
@
artifactId@
cloud
:
nacos
:
discovery
:
server-addr
:
${NACOS_HOST:192.168.1.46}:${NACOS_PORT:8848}
username
:
nacos
password
:
nacos
config
:
server-addr
:
${spring.cloud.nacos.discovery.server-addr}
file-extension
:
yml
namespace
:
@
nacos.namespace@
shared-configs
:
-
application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
username
:
${spring.cloud.nacos.discovery.username}
password
:
${spring.cloud.nacos.discovery.password}
profiles
:
active
:
@
profiles.active@
mall4cloud-auth/src/main/resources/captcha/original/1.png
0 → 100644
View file @
3ab6e756
35.4 KB
mall4cloud-auth/src/main/resources/captcha/original/2.png
0 → 100644
View file @
3ab6e756
42.9 KB
mall4cloud-auth/src/main/resources/captcha/original/3.png
0 → 100644
View file @
3ab6e756
40.2 KB
Prev
1
…
5
6
7
8
9
10
11
12
13
…
34
Next
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