Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
B
basic-api-boot
概览
概览
详情
活动
周期分析
版本库
存储库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
Basic
basic-api-boot
Commits
16ea2d1b
提交
16ea2d1b
authored
10月 14, 2024
作者:
方治民
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: 添加图形验证码生成接口、登录校验扩展图形验证码配置等
上级
ce3cf67b
隐藏空白字符变更
内嵌
并排
正在显示
10 个修改的文件
包含
201 行增加
和
6 行删除
+201
-6
application-dev-postgresql.yml
app/src/main/resources/application-dev-postgresql.yml
+7
-0
build.gradle
build.gradle
+5
-5
build.gradle
modules/auth/build.gradle
+2
-0
AuthConfig.java
...auth/src/main/java/com/yiring/auth/config/AuthConfig.java
+28
-0
Captcha.java
modules/auth/src/main/java/com/yiring/auth/core/Captcha.java
+64
-0
CaptchaParam.java
...rc/main/java/com/yiring/auth/param/auth/CaptchaParam.java
+34
-0
CaptchaVo.java
...auth/src/main/java/com/yiring/auth/vo/auth/CaptchaVo.java
+34
-0
AuthController.java
...rc/main/java/com/yiring/auth/web/auth/AuthController.java
+25
-1
messages.properties
modules/auth/src/main/resources/i18n/messages.properties
+1
-0
messages_zh_CN.properties
...es/auth/src/main/resources/i18n/messages_zh_CN.properties
+1
-0
没有找到文件。
app/src/main/resources/application-dev-postgresql.yml
浏览文件 @
16ea2d1b
...
@@ -40,6 +40,13 @@ spring:
...
@@ -40,6 +40,13 @@ spring:
# ----------------------------------------------
# ----------------------------------------------
# ----------------------------------------------
# ----------------------------------------------
# Auth
auth
:
# 是否启用图形验证码进行校验
captcha
:
true
# ----------------------------------------------
# ----------------------------------------------
# Spring Doc
# Spring Doc
springdoc
:
springdoc
:
default-consumes-media-type
:
"
application/x-www-form-urlencoded"
default-consumes-media-type
:
"
application/x-www-form-urlencoded"
...
...
build.gradle
浏览文件 @
16ea2d1b
...
@@ -29,17 +29,17 @@ ext {
...
@@ -29,17 +29,17 @@ ext {
// SpringBootAdmin
// SpringBootAdmin
// https://central.sonatype.com/artifact/de.codecentric/spring-boot-admin-starter-server
// https://central.sonatype.com/artifact/de.codecentric/spring-boot-admin-starter-server
springBootAdminVersion
=
'3.3.
3
'
springBootAdminVersion
=
'3.3.
4
'
// Sentry
// Sentry
// https://central.sonatype.com/artifact/io.sentry/sentry-spring-boot-starter-jakarta
// https://central.sonatype.com/artifact/io.sentry/sentry-spring-boot-starter-jakarta
sentryVersion
=
'7.1
4
.0'
sentryVersion
=
'7.1
5
.0'
// Dependencies
// Dependencies
// https://central.sonatype.com/artifact/com.github.xiaoymin/knife4j-openapi3-jakarta-spring-boot-starter
// https://central.sonatype.com/artifact/com.github.xiaoymin/knife4j-openapi3-jakarta-spring-boot-starter
knife4jOpen3Version
=
'4.5.0'
knife4jOpen3Version
=
'4.5.0'
// https://central.sonatype.com/artifact/io.swagger.core.v3/swagger-annotations
// https://central.sonatype.com/artifact/io.swagger.core.v3/swagger-annotations
swaggerAnnotationsVersion
=
'2.2.2
3
'
swaggerAnnotationsVersion
=
'2.2.2
5
'
// https://central.sonatype.com/artifact/cn.dev33/sa-token-spring-boot3-starter
// https://central.sonatype.com/artifact/cn.dev33/sa-token-spring-boot3-starter
saTokenVersion
=
'1.39.0'
saTokenVersion
=
'1.39.0'
// https://central.sonatype.com/artifact/cn.hutool/hutool-core
// https://central.sonatype.com/artifact/cn.hutool/hutool-core
...
@@ -59,9 +59,9 @@ ext {
...
@@ -59,9 +59,9 @@ ext {
// https://mvnrepository.com/artifact/org.n52.jackson/jackson-datatype-jts
// https://mvnrepository.com/artifact/org.n52.jackson/jackson-datatype-jts
jacksonDatatypeJtsVersion
=
'1.2.10'
jacksonDatatypeJtsVersion
=
'1.2.10'
// https://central.sonatype.com/artifact/com.github.liaochong/myexcel
// https://central.sonatype.com/artifact/com.github.liaochong/myexcel
myexcelVersion
=
'4.5.
2
'
myexcelVersion
=
'4.5.
3
'
// https://central.sonatype.com/artifact/org.jetbrains/annotations
// https://central.sonatype.com/artifact/org.jetbrains/annotations
jetbrainsAnnotationsVersion
=
'2
4.1
.0'
jetbrainsAnnotationsVersion
=
'2
6.0
.0'
// https://central.sonatype.com/artifact/org.apache.pdfbox/pdfbox
// https://central.sonatype.com/artifact/org.apache.pdfbox/pdfbox
pdfboxVersion
=
'3.0.3'
pdfboxVersion
=
'3.0.3'
// https://central.sonatype.com/artifact/org.lionsoul/ip2region
// https://central.sonatype.com/artifact/org.lionsoul/ip2region
...
...
modules/auth/build.gradle
浏览文件 @
16ea2d1b
...
@@ -4,6 +4,7 @@ plugins {
...
@@ -4,6 +4,7 @@ plugins {
dependencies
{
dependencies
{
implementation
project
(
':modules:common:core'
)
implementation
project
(
':modules:common:core'
)
implementation
project
(
':modules:common:redis'
)
implementation
project
(
':modules:common:i18n'
)
implementation
project
(
':modules:common:i18n'
)
implementation
project
(
':modules:common:util'
)
implementation
project
(
':modules:common:util'
)
...
@@ -25,6 +26,7 @@ dependencies {
...
@@ -25,6 +26,7 @@ dependencies {
// hutool-core
// hutool-core
implementation
"cn.hutool:hutool-core:${hutoolVersion}"
implementation
"cn.hutool:hutool-core:${hutoolVersion}"
implementation
"cn.hutool:hutool-http:${hutoolVersion}"
implementation
"cn.hutool:hutool-http:${hutoolVersion}"
implementation
"cn.hutool:hutool-captcha:${hutoolVersion}"
// https://github.com/vladmihalcea/hypersistence-utils
// https://github.com/vladmihalcea/hypersistence-utils
// hypersistence-utils-hibernate-63
// hypersistence-utils-hibernate-63
...
...
modules/auth/src/main/java/com/yiring/auth/config/AuthConfig.java
0 → 100644
浏览文件 @
16ea2d1b
/* (C) 2024 YiRing, Inc. */
package
com
.
yiring
.
auth
.
config
;
import
java.io.Serial
;
import
java.io.Serializable
;
import
lombok.AccessLevel
;
import
lombok.Data
;
import
lombok.experimental.FieldDefaults
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
org.springframework.context.annotation.Configuration
;
/**
* @author Jim
*/
@Data
@FieldDefaults
(
level
=
AccessLevel
.
PRIVATE
)
@Configuration
(
"custom.auth.config"
)
@ConfigurationProperties
(
prefix
=
"auth"
)
public
class
AuthConfig
implements
Serializable
{
@Serial
private
static
final
long
serialVersionUID
=
2896697722679227230L
;
/**
* 是否启用验证码校验
*/
boolean
captcha
;
}
modules/auth/src/main/java/com/yiring/auth/core/Captcha.java
0 → 100644
浏览文件 @
16ea2d1b
/* (C) 2024 YiRing, Inc. */
package
com
.
yiring
.
auth
.
core
;
import
cn.hutool.captcha.CaptchaUtil
;
import
cn.hutool.captcha.LineCaptcha
;
import
cn.hutool.core.util.IdUtil
;
import
cn.hutool.core.util.StrUtil
;
import
com.yiring.auth.vo.auth.CaptchaVo
;
import
com.yiring.common.core.Redis
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.stereotype.Component
;
/**
* @author Jim
*/
@Slf4j
@Component
@RequiredArgsConstructor
public
class
Captcha
{
final
Redis
redis
;
static
final
String
CAPTCHA_KEY_PREFIX
=
"CAPTCHA:"
;
/**
* 生成验证码
*
* @return CaptchaVo 验证码信息
*/
public
CaptchaVo
create
()
{
LineCaptcha
lineCaptcha
=
CaptchaUtil
.
createLineCaptcha
(
200
,
80
);
String
key
=
IdUtil
.
fastSimpleUUID
();
CaptchaVo
vo
=
CaptchaVo
.
builder
()
.
key
(
key
)
.
data
(
"data:image/jpg;base64,"
+
lineCaptcha
.
getImageBase64
())
.
build
();
redis
.
set
(
CAPTCHA_KEY_PREFIX
+
key
,
lineCaptcha
.
getCode
(),
300
);
return
vo
;
}
/**
* 校验验证码
*
* @param key 验证码标识
* @param code 验证码识别结果
* @return true: 验证通过 false: 验证失败
*/
public
boolean
verify
(
String
key
,
String
code
)
{
if
(
StrUtil
.
isBlank
(
key
)
||
StrUtil
.
isBlank
(
code
))
{
return
false
;
}
String
cacheKey
=
CAPTCHA_KEY_PREFIX
+
key
;
String
value
=
redis
.
get
(
cacheKey
,
String
.
class
);
if
(
value
==
null
||
!
value
.
equals
(
code
))
{
return
false
;
}
redis
.
del
(
cacheKey
);
return
true
;
}
}
modules/auth/src/main/java/com/yiring/auth/param/auth/CaptchaParam.java
0 → 100644
浏览文件 @
16ea2d1b
/* (C) 2021 YiRing, Inc. */
package
com
.
yiring
.
auth
.
param
.
auth
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
java.io.Serial
;
import
java.io.Serializable
;
import
lombok.*
;
import
lombok.experimental.FieldDefaults
;
/**
* 验证码校验参数
*
* @author ifzm
* @version 0.1
* 2019/5/28 22:11
*/
@Schema
(
name
=
"CaptchaParam"
)
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@FieldDefaults
(
level
=
AccessLevel
.
PRIVATE
)
public
class
CaptchaParam
implements
Serializable
{
@Serial
private
static
final
long
serialVersionUID
=
2482112377591343046L
;
@Schema
(
description
=
"验证码校验标识"
,
example
=
"b6523c1198f64602aea006238a744de7"
)
String
captchaKey
;
@Schema
(
description
=
"验证码识别结果"
,
example
=
"vLUF4"
)
String
captchaCode
;
}
modules/auth/src/main/java/com/yiring/auth/vo/auth/CaptchaVo.java
0 → 100644
浏览文件 @
16ea2d1b
/* (C) 2021 YiRing, Inc. */
package
com
.
yiring
.
auth
.
vo
.
auth
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
java.io.Serial
;
import
java.io.Serializable
;
import
lombok.*
;
import
lombok.experimental.FieldDefaults
;
/**
* 验证码输出信息
*
* @author ifzm
* @version 0.1
* 2019/5/28 22:11
*/
@Schema
(
name
=
"CaptchaVo"
)
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@FieldDefaults
(
level
=
AccessLevel
.
PRIVATE
)
public
class
CaptchaVo
implements
Serializable
{
@Serial
private
static
final
long
serialVersionUID
=
5303746889633243114L
;
@Schema
(
description
=
"验证码唯一标识"
,
example
=
"b6523c1198f64602aea006238a744de7"
)
String
key
;
@Schema
(
description
=
"验证码图片 Base64"
,
example
=
"data:image/jpg;base64,iV=="
)
String
data
;
}
modules/auth/src/main/java/com/yiring/auth/web/auth/AuthController.java
浏览文件 @
16ea2d1b
...
@@ -7,14 +7,18 @@ import cn.dev33.satoken.stp.StpUtil;
...
@@ -7,14 +7,18 @@ import cn.dev33.satoken.stp.StpUtil;
import
cn.hutool.core.util.StrUtil
;
import
cn.hutool.core.util.StrUtil
;
import
cn.hutool.http.useragent.*
;
import
cn.hutool.http.useragent.*
;
import
com.github.xiaoymin.knife4j.annotations.ApiSupport
;
import
com.github.xiaoymin.knife4j.annotations.ApiSupport
;
import
com.yiring.auth.config.AuthConfig
;
import
com.yiring.auth.core.Captcha
;
import
com.yiring.auth.domain.log.LoginLog
;
import
com.yiring.auth.domain.log.LoginLog
;
import
com.yiring.auth.domain.log.LoginLogRepository
;
import
com.yiring.auth.domain.log.LoginLogRepository
;
import
com.yiring.auth.domain.user.User
;
import
com.yiring.auth.domain.user.User
;
import
com.yiring.auth.domain.user.UserRepository
;
import
com.yiring.auth.domain.user.UserRepository
;
import
com.yiring.auth.param.auth.CaptchaParam
;
import
com.yiring.auth.param.auth.LoginParam
;
import
com.yiring.auth.param.auth.LoginParam
;
import
com.yiring.auth.param.auth.RegisterParam
;
import
com.yiring.auth.param.auth.RegisterParam
;
import
com.yiring.auth.param.auth.SafeParam
;
import
com.yiring.auth.param.auth.SafeParam
;
import
com.yiring.auth.util.Auths
;
import
com.yiring.auth.util.Auths
;
import
com.yiring.auth.vo.auth.CaptchaVo
;
import
com.yiring.auth.vo.auth.LoginVo
;
import
com.yiring.auth.vo.auth.LoginVo
;
import
com.yiring.common.annotation.RateLimiter
;
import
com.yiring.common.annotation.RateLimiter
;
import
com.yiring.common.core.I18n
;
import
com.yiring.common.core.I18n
;
...
@@ -56,6 +60,8 @@ public class AuthController {
...
@@ -56,6 +60,8 @@ public class AuthController {
final
I18n
i18n
;
final
I18n
i18n
;
final
Auths
auths
;
final
Auths
auths
;
final
Captcha
captcha
;
final
AuthConfig
authConfig
;
final
UserRepository
userRepository
;
final
UserRepository
userRepository
;
final
LoginLogRepository
loginLogRepository
;
final
LoginLogRepository
loginLogRepository
;
...
@@ -100,7 +106,11 @@ public class AuthController {
...
@@ -100,7 +106,11 @@ public class AuthController {
@RateLimiter
(
count
=
3
)
@RateLimiter
(
count
=
3
)
@Operation
(
summary
=
"登录"
)
@Operation
(
summary
=
"登录"
)
@PostMapping
(
"login"
)
@PostMapping
(
"login"
)
public
Result
<
LoginVo
>
login
(
@ParameterObject
@Validated
LoginParam
param
,
HttpServletRequest
request
)
{
public
Result
<
LoginVo
>
login
(
@ParameterObject
@Validated
LoginParam
param
,
@ParameterObject
CaptchaParam
captchaParam
,
HttpServletRequest
request
)
{
// 获取登录 IP
// 获取登录 IP
// String ip = "222.244.92.58";
// String ip = "222.244.92.58";
String
ip
=
IpUtil
.
getClientIp
(
request
);
String
ip
=
IpUtil
.
getClientIp
(
request
);
...
@@ -138,6 +148,13 @@ public class AuthController {
...
@@ -138,6 +148,13 @@ public class AuthController {
}
}
try
{
try
{
// 校验图形验证码
if
(
authConfig
.
isCaptcha
()
||
StrUtil
.
isNotBlank
(
captchaParam
.
getCaptchaKey
()))
{
if
(!
captcha
.
verify
(
captchaParam
.
getCaptchaKey
(),
captchaParam
.
getCaptchaCode
()))
{
throw
BusinessException
.
i18n
(
"Code.100006"
);
}
}
// 查询用户信息是否匹配
// 查询用户信息是否匹配
User
user
=
userRepository
.
findByAccount
(
param
.
getAccount
());
User
user
=
userRepository
.
findByAccount
(
param
.
getAccount
());
if
(
user
==
null
)
{
if
(
user
==
null
)
{
...
@@ -220,4 +237,11 @@ public class AuthController {
...
@@ -220,4 +237,11 @@ public class AuthController {
return
Result
.
no
();
return
Result
.
no
();
}
}
@Operation
(
summary
=
"生成图形验证码"
)
@GetMapping
(
"captcha"
)
public
Result
<
CaptchaVo
>
captcha
()
{
CaptchaVo
vo
=
captcha
.
create
();
return
Result
.
ok
(
vo
);
}
}
}
modules/auth/src/main/resources/i18n/messages.properties
浏览文件 @
16ea2d1b
...
@@ -11,3 +11,4 @@ Code.100002=\u90AE\u7BB1\u5DF2\u5B58\u5728
...
@@ -11,3 +11,4 @@ Code.100002=\u90AE\u7BB1\u5DF2\u5B58\u5728
Code.100003
=
\u
8D26
\u
53F7
\u
5BC6
\u7801\u9519\u
8BEF
Code.100003
=
\u
8D26
\u
53F7
\u
5BC6
\u7801\u9519\u
8BEF
Code.100004
=
\u7528\u6237\u
88AB
\u7981\u7528
,
\u
8BF7
\u8054\u
7CFB
\u
7BA1
\u7406\u5458
Code.100004
=
\u7528\u6237\u
88AB
\u7981\u7528
,
\u
8BF7
\u8054\u
7CFB
\u
7BA1
\u7406\u5458
Code.100005
=
\u7528\u6237\u
88AB
\u7981\u
6B62
\u
767B
\u
5F55,
\u
8BF7
\u8054\u
7CFB
\u
7BA1
\u7406\u5458
Code.100005
=
\u7528\u6237\u
88AB
\u7981\u
6B62
\u
767B
\u
5F55,
\u
8BF7
\u8054\u
7CFB
\u
7BA1
\u7406\u5458
Code.100006
=
\u
9A8C
\u
8BC1
\u7801\u6821\u
9A8C
\u5931\u
8D25
modules/auth/src/main/resources/i18n/messages_zh_CN.properties
浏览文件 @
16ea2d1b
...
@@ -11,3 +11,4 @@ Code.100002=\u90AE\u7BB1\u5DF2\u5B58\u5728
...
@@ -11,3 +11,4 @@ Code.100002=\u90AE\u7BB1\u5DF2\u5B58\u5728
Code.100003
=
\u
8D26
\u
53F7
\u
5BC6
\u7801\u9519\u
8BEF
Code.100003
=
\u
8D26
\u
53F7
\u
5BC6
\u7801\u9519\u
8BEF
Code.100004
=
\u7528\u6237\u
88AB
\u7981\u7528
,
\u
8BF7
\u8054\u
7CFB
\u
7BA1
\u7406\u5458
Code.100004
=
\u7528\u6237\u
88AB
\u7981\u7528
,
\u
8BF7
\u8054\u
7CFB
\u
7BA1
\u7406\u5458
Code.100005
=
\u7528\u6237\u
88AB
\u7981\u
6B62
\u
767B
\u
5F55,
\u
8BF7
\u8054\u
7CFB
\u
7BA1
\u7406\u5458
Code.100005
=
\u7528\u6237\u
88AB
\u7981\u
6B62
\u
767B
\u
5F55,
\u
8BF7
\u8054\u
7CFB
\u
7BA1
\u7406\u5458
Code.100006
=
\u
9A8C
\u
8BC1
\u7801\u6821\u
9A8C
\u5931\u
8D25
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论