Commit 4c313f61 authored by 李超鹏's avatar 李超鹏

限流调整,包结构调整

parent be52c207
Pipeline #7371 canceled with stages
...@@ -72,7 +72,7 @@ ...@@ -72,7 +72,7 @@
<dependency> <dependency>
<groupId>io.quarkiverse.bucket4j</groupId> <groupId>io.quarkiverse.bucket4j</groupId>
<artifactId>quarkus-bucket4j</artifactId> <artifactId>quarkus-bucket4j</artifactId>
<version>1.0.1</version> <version>2.0.0</version>
</dependency> </dependency>
<!-- 短信供应商sdk --> <!-- 短信供应商sdk -->
......
...@@ -57,10 +57,15 @@ public class TokenFilter { ...@@ -57,10 +57,15 @@ public class TokenFilter {
if (!isIgnore(context.getUriInfo().getPath()) && StringUtil.isNullOrEmpty(token)) { if (!isIgnore(context.getUriInfo().getPath()) && StringUtil.isNullOrEmpty(token)) {
return RestResponse.status(Response.Status.FORBIDDEN, objectMapper.writeValueAsString(R.fail("您需要登录后才能进行此操作"))); return RestResponse.status(Response.Status.FORBIDDEN, objectMapper.writeValueAsString(R.fail("您需要登录后才能进行此操作")));
} }
AuthInfo parse = TokenUtil.parse(jwtParser, token); try {
QuestionerHolder.putQuestioner(parse); AuthInfo parse = TokenUtil.parse(jwtParser, token);
QuestionerHolder.putChannel(channel); QuestionerHolder.putQuestioner(parse);
return null; QuestionerHolder.putChannel(channel);
return null;
} catch (Exception e) {
Log.warnf("解析token失败,%s", e.getMessage());
return RestResponse.status(Response.Status.FORBIDDEN, objectMapper.writeValueAsString(R.fail("您需要登录后才能进行此操作")));
}
} }
@ServerResponseFilter(priority = 2000) @ServerResponseFilter(priority = 2000)
......
package cc.shenjiying.ai.config.ratelimit;
import cc.shenjiying.ai.dto.QuestionerLoginDTO;
import io.quarkiverse.bucket4j.runtime.resolver.IdentityResolver;
import jakarta.enterprise.context.RequestScoped;
@RequestScoped
public class LoginResolver implements IdentityResolver {
public String getIdentityKey(Object[] params) {
if (params != null && params.length > 0) {
if (params[0] instanceof QuestionerLoginDTO param) {
return param.getAccount();
}
}
return "";
}
@Override
public String getIdentityKey() {
return "";
}
}
package cc.shenjiying.ai.config.ratelimit;
import io.quarkiverse.bucket4j.runtime.resolver.IdentityResolver;
import io.vertx.ext.web.RoutingContext;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import java.util.List;
import java.util.Objects;
@RequestScoped
public class MobileResolver implements IdentityResolver {
@Inject
RoutingContext context;
@Override
public String getIdentityKey() {
List<String> mobile = context.queryParam("mobile");
return Objects.isNull(mobile) || mobile.isEmpty() ? "" : mobile.get(0);
}
}
package cc.shenjiying.ai.service; package cc.shenjiying.ai.manager;
import cc.shenjiying.ai.client.KnowLedgeChat; import cc.shenjiying.ai.client.KnowLedgeChat;
import cc.shenjiying.ai.config.QuestionerHolder; import cc.shenjiying.ai.config.QuestionerHolder;
......
...@@ -2,12 +2,14 @@ package cc.shenjiying.ai.manager; ...@@ -2,12 +2,14 @@ package cc.shenjiying.ai.manager;
import cc.shenjiying.ai.common.dto.AuthInfo; import cc.shenjiying.ai.common.dto.AuthInfo;
import cc.shenjiying.ai.common.dto.R; import cc.shenjiying.ai.common.dto.R;
import cc.shenjiying.ai.config.ratelimit.MobileResolver;
import cc.shenjiying.ai.repository.entity.Questioner; import cc.shenjiying.ai.repository.entity.Questioner;
import cc.shenjiying.ai.repository.entity.QuestionerWhiteList; import cc.shenjiying.ai.repository.entity.QuestionerWhiteList;
import cc.shenjiying.ai.repository.mapper.QuestionerMapper; import cc.shenjiying.ai.repository.mapper.QuestionerMapper;
import cc.shenjiying.ai.repository.mapper.QuestionerWhiteListMapper; import cc.shenjiying.ai.repository.mapper.QuestionerWhiteListMapper;
import cc.shenjiying.ai.util.TokenUtil; import cc.shenjiying.ai.util.TokenUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.quarkiverse.bucket4j.runtime.RateLimited;
import io.quarkus.runtime.util.StringUtil; import io.quarkus.runtime.util.StringUtil;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject; import jakarta.inject.Inject;
...@@ -25,9 +27,6 @@ public class QuestionerService { ...@@ -25,9 +27,6 @@ public class QuestionerService {
@Inject @Inject
SmsCodeService smsCodeService; SmsCodeService smsCodeService;
@Inject
QuestionerWhiteListMapper questionerWhiteListMapper;
public Questioner getQuestioner(Long userId) { public Questioner getQuestioner(Long userId) {
return questionerMapper.selectById(userId); return questionerMapper.selectById(userId);
} }
...@@ -45,19 +44,16 @@ public class QuestionerService { ...@@ -45,19 +44,16 @@ public class QuestionerService {
return questionerMapper.insert(questioner); return questionerMapper.insert(questioner);
} }
@RateLimited(bucket = "moblie_code", identityResolver = MobileResolver.class)
public R<Boolean> getLoginCode(@RestQuery String mobile) { public R<Boolean> getLoginCode(@RestQuery String mobile) {
if (StringUtil.isNullOrEmpty(mobile)) { if (StringUtil.isNullOrEmpty(mobile)) {
return R.validFail(); return R.validFail();
} }
Long count = questionerWhiteListMapper.selectCount(new LambdaQueryWrapper<QuestionerWhiteList>().eq(QuestionerWhiteList::getAccount, mobile)); smsCodeService.send(mobile);
if (count > 0) { return R.success(Boolean.TRUE);
smsCodeService.send(mobile);
return R.success(Boolean.TRUE);
}
return R.fail("尊敬的用户,感谢您对我们的产品感兴趣。但请注意,目前该产品仍处于内测阶段,仅对特定用户开放");
} }
public R<String> getLoginToken(String mobile, String code) { public R<AuthInfo> getLoginToken(String mobile, String code) {
if (StringUtil.isNullOrEmpty(mobile) || StringUtil.isNullOrEmpty(code)) { if (StringUtil.isNullOrEmpty(mobile) || StringUtil.isNullOrEmpty(code)) {
return R.validFail(); return R.validFail();
} }
...@@ -67,9 +63,10 @@ public class QuestionerService { ...@@ -67,9 +63,10 @@ public class QuestionerService {
if (Objects.isNull(questioner)) { if (Objects.isNull(questioner)) {
return R.fail("用户名或密码错误,请重新输入"); return R.fail("用户名或密码错误,请重新输入");
} }
String token = TokenUtil.create(new AuthInfo().setId(questioner.getId()).setAccount(questioner.getAccount()) AuthInfo authInfo = new AuthInfo().setId(questioner.getId()).setAccount(questioner.getAccount())
.setMobile(questioner.getMobile()).setChannel(questioner.getChannel()).setChannelUserId(questioner.getChannelUserId())); .setMobile(questioner.getMobile()).setChannel(questioner.getChannel()).setChannelUserId(questioner.getChannelUserId());
return R.success(token); String token = TokenUtil.create(authInfo);
return R.success(authInfo.setToken(token));
} }
return R.fail("验证码错误或已过期,请重新获取验证码后再试"); return R.fail("验证码错误或已过期,请重新获取验证码后再试");
} }
......
package cc.shenjiying.ai.manager; package cc.shenjiying.ai.manager;
import cc.shenjiying.ai.config.ratelimit.MobileResolver;
import cc.shenjiying.ai.repository.entity.SmsSendLog; import cc.shenjiying.ai.repository.entity.SmsSendLog;
import cc.shenjiying.ai.repository.mapper.SmsSendLogMapper; import cc.shenjiying.ai.repository.mapper.SmsSendLogMapper;
import cc.shenjiying.ai.util.RandomUtil; import cc.shenjiying.ai.util.RandomUtil;
...@@ -9,6 +10,7 @@ import cc.shenjiying.sms.AliSmsSender; ...@@ -9,6 +10,7 @@ import cc.shenjiying.sms.AliSmsSender;
import cc.shenjiying.sms.TencentSmsSender; import cc.shenjiying.sms.TencentSmsSender;
import cc.shenjiying.sms.dto.SmsSendResult; import cc.shenjiying.sms.dto.SmsSendResult;
import cc.shenjiying.sms.param.SmsSendParam; import cc.shenjiying.sms.param.SmsSendParam;
import io.quarkiverse.bucket4j.runtime.RateLimited;
import io.quarkus.runtime.util.StringUtil; import io.quarkus.runtime.util.StringUtil;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject; import jakarta.inject.Inject;
...@@ -32,7 +34,6 @@ public class SmsCodeService { ...@@ -32,7 +34,6 @@ public class SmsCodeService {
@Inject @Inject
SmsSendLogMapper logMapper; SmsSendLogMapper logMapper;
public void send(String mobile) { public void send(String mobile) {
String code = RandomUtil.generateNumber(4); String code = RandomUtil.generateNumber(4);
redisCache.setValue(new MobileCodeKey().key(mobile), code, 5 * 60); redisCache.setValue(new MobileCodeKey().key(mobile), code, 5 * 60);
......
...@@ -3,7 +3,7 @@ package cc.shenjiying.ai.resource; ...@@ -3,7 +3,7 @@ package cc.shenjiying.ai.resource;
import cc.shenjiying.ai.config.QuestionerHolder; import cc.shenjiying.ai.config.QuestionerHolder;
import cc.shenjiying.ai.dto.ChatAIResponse; import cc.shenjiying.ai.dto.ChatAIResponse;
import cc.shenjiying.ai.dto.FeedbackSaveDTO; import cc.shenjiying.ai.dto.FeedbackSaveDTO;
import cc.shenjiying.ai.service.KnowledgeService; import cc.shenjiying.ai.manager.KnowledgeService;
import io.quarkiverse.bucket4j.runtime.RateLimited; import io.quarkiverse.bucket4j.runtime.RateLimited;
import io.smallrye.mutiny.Multi; import io.smallrye.mutiny.Multi;
import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.Uni;
...@@ -37,7 +37,6 @@ public class KnowLedgeResource { ...@@ -37,7 +37,6 @@ public class KnowLedgeResource {
return knowledgeService.chatStream(text); return knowledgeService.chatStream(text);
} }
@PUT @PUT
@Path("/like/{questionId}") @Path("/like/{questionId}")
@Operation(summary = "点赞") @Operation(summary = "点赞")
......
package cc.shenjiying.ai.resource; package cc.shenjiying.ai.resource;
import cc.shenjiying.ai.common.dto.AuthInfo;
import cc.shenjiying.ai.common.dto.R; import cc.shenjiying.ai.common.dto.R;
import cc.shenjiying.ai.config.ratelimit.LoginResolver;
import cc.shenjiying.ai.config.ratelimit.MobileResolver;
import cc.shenjiying.ai.dto.QuestionerLoginDTO; import cc.shenjiying.ai.dto.QuestionerLoginDTO;
import cc.shenjiying.ai.manager.QuestionerService; import cc.shenjiying.ai.manager.QuestionerService;
import cc.shenjiying.ai.repository.entity.QuestionerWhiteList;
import cc.shenjiying.ai.repository.mapper.QuestionerWhiteListMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.quarkiverse.bucket4j.runtime.RateLimited;
import io.quarkiverse.bucket4j.runtime.resolver.IpResolver;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.ws.rs.*; import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.MediaType;
...@@ -13,28 +21,32 @@ import org.jboss.resteasy.reactive.RestQuery; ...@@ -13,28 +21,32 @@ import org.jboss.resteasy.reactive.RestQuery;
@Path("/questioner") @Path("/questioner")
@Tag(name = "用户") @Tag(name = "用户")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class QuestionerResource { public class QuestionerResource {
@Inject @Inject
QuestionerService questionerService; QuestionerService questionerService;
@Inject @Inject
JsonWebToken jwt; QuestionerWhiteListMapper questionerWhiteListMapper;
@GET @GET
@Path("/login/code") @Path("/login/code")
@Operation(summary = "发送验证码") @Operation(summary = "发送验证码")
public R<Boolean> getLoginCode(@RestQuery String mobile) { public R<Boolean> getLoginCode(@RestQuery String mobile) {
Long count = questionerWhiteListMapper.selectCount(new LambdaQueryWrapper<QuestionerWhiteList>().eq(QuestionerWhiteList::getAccount, mobile));
return questionerService.getLoginCode(mobile); if (count > 0) {
questionerService.getLoginCode(mobile);
return R.success(Boolean.TRUE);
}
return R.fail("尊敬的用户,感谢您对我们的产品感兴趣。但请注意,目前该产品仍处于内测阶段,仅对特定用户开放");
} }
@POST @POST
@Path("/login") @Path("/login")
@Operation(summary = "手机号登录") @Operation(summary = "手机号登录")
@Produces(MediaType.APPLICATION_JSON) @RateLimited(bucket = "login", identityResolver = LoginResolver.class)
@Consumes(MediaType.APPLICATION_JSON) public R<AuthInfo> login(QuestionerLoginDTO loginDTO) {
public R<String> login(QuestionerLoginDTO loginDTO) {
return questionerService.getLoginToken(loginDTO.getAccount(), loginDTO.getPassword()); return questionerService.getLoginToken(loginDTO.getAccount(), loginDTO.getPassword());
} }
......
package cc.shenjiying.ai.service;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.transaction.Transactional;
@ApplicationScoped
public class TestService {
@Transactional
public void service(){
}
}
...@@ -57,17 +57,22 @@ quarkus.redis.hosts=redis://192.168.1.24:6379/ ...@@ -57,17 +57,22 @@ quarkus.redis.hosts=redis://192.168.1.24:6379/
#quarkus.redis.replicas=share #quarkus.redis.replicas=share
#\u9650\u6D41 \u591A\u4E2A\u9650\u5236 #\u9650\u6D41 \u591A\u4E2A\u9650\u5236
#\u804A\u5929\u63A5\u53E3\u9650\u6D41
quarkus.rate-limiter.buckets.chat.limits[0].permitted-uses: 5 quarkus.rate-limiter.buckets.chat.limits[0].permitted-uses: 5
quarkus.rate-limiter.buckets.chat.limits[0].period: 1S quarkus.rate-limiter.buckets.chat.limits[0].period: 1S
quarkus.rate-limiter.buckets.chat.limits[1].permitted-uses: 700 quarkus.rate-limiter.buckets.chat.limits[1].permitted-uses: 700
quarkus.rate-limiter.buckets.chat.limits[1].period: 5M quarkus.rate-limiter.buckets.chat.limits[1].period: 5M
#\u53D1\u9001\u767B\u5F55\u9A8C\u8BC1\u7801
quarkus.rate-limiter.buckets.moblie_code.limits[0].permitted-uses: 1
quarkus.rate-limiter.buckets.moblie_code.limits[0].period: 1m
#\u767B\u5F55
quarkus.rate-limiter.buckets.login.limits[0].permitted-uses: 5
quarkus.rate-limiter.buckets.login.limits[0].period: 1S
#jwt #jwt
#\u53D1\u884C\u8005\u3001\u53D7\u4F17 #\u53D1\u884C\u8005\u3001\u53D7\u4F17
smallrye.jwt.new-token.issuer=ai.kaying.cc smallrye.jwt.new-token.issuer=ai.kaying.cc
#smallrye.jwt.new-token.audience=
smallrye.jwt.claims.sub=ai smallrye.jwt.claims.sub=ai
smallrye.jwt.require.named-principal=false
# \u8FC7\u671F\u65F6\u95F4 7\u5929 # \u8FC7\u671F\u65F6\u95F4 7\u5929
smallrye.jwt.new-token.lifespan=604800 smallrye.jwt.new-token.lifespan=604800
#\u7B7E\u540D\u7B97\u6CD5 #\u7B7E\u540D\u7B97\u6CD5
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment