From a7f178da53bba947caec334df1bf880150e9fa5a Mon Sep 17 00:00:00 2001 From: click33 <2393584716@qq.com> Date: Wed, 2 Apr 2025 02:54:50 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20sa-token-quick-login=20=E6=8F=92?= =?UTF-8?q?=E4=BB=B6=E6=94=AF=E6=8C=81=20Http=20Basic=20=E6=96=B9=E5=BC=8F?= =?UTF-8?q?=E9=80=9A=E8=BF=87=E8=AE=A4=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../httpauth/basic/SaHttpBasicAccount.java | 109 ++++++++++++++++++ .../httpauth/basic/SaHttpBasicTemplate.java | 16 ++- .../httpauth/basic/SaHttpBasicUtil.java | 12 +- sa-token-doc/plugin/quick-login.md | 6 + .../dev33/satoken/quick/SaQuickRegister.java | 27 ++++- .../satoken/quick/config/SaQuickConfig.java | 28 ++++- .../quick/function/DoLoginHandleFunction.java | 34 ++++++ .../satoken/quick/web/SaQuickController.java | 19 +-- 8 files changed, 223 insertions(+), 28 deletions(-) create mode 100644 sa-token-core/src/main/java/cn/dev33/satoken/httpauth/basic/SaHttpBasicAccount.java create mode 100644 sa-token-plugin/sa-token-quick-login/src/main/java/cn/dev33/satoken/quick/function/DoLoginHandleFunction.java diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/httpauth/basic/SaHttpBasicAccount.java b/sa-token-core/src/main/java/cn/dev33/satoken/httpauth/basic/SaHttpBasicAccount.java new file mode 100644 index 00000000..f50196b6 --- /dev/null +++ b/sa-token-core/src/main/java/cn/dev33/satoken/httpauth/basic/SaHttpBasicAccount.java @@ -0,0 +1,109 @@ +/* + * Copyright 2020-2099 sa-token.cc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package cn.dev33.satoken.httpauth.basic; + +import cn.dev33.satoken.exception.SaTokenException; +import cn.dev33.satoken.util.SaFoxUtil; + +/** + * Sa-Token Http Basic 账号 + * + * @author click33 + * @since 1.41.0 + */ +public class SaHttpBasicAccount { + + /** + * 账号 + */ + private String username; + + /** + * 密码 + */ + private String password; + + /** + * 构造函数 + * @param username 账号 + * @param password 密码 + */ + public SaHttpBasicAccount(String username, String password) { + this.username = username; + this.password = password; + } + + /** + * 构造函数 + * @param usernameAndPassword 账号和密码,冒号隔开 + */ + public SaHttpBasicAccount(String usernameAndPassword) { + if(SaFoxUtil.isEmpty(usernameAndPassword)) { + throw new SaTokenException("UsernameAndPassword 不能为空"); + } + String[] arr = usernameAndPassword.split(":"); + if(arr.length != 2) { + throw new SaTokenException("UsernameAndPassword 格式错误,正确格式为:username:password"); + } + this.username = arr[0]; + this.password = arr[1]; + } + + /** + * 获取 账号 + * + * @return username 账号 + */ + public String getUsername() { + return this.username; + } + + /** + * 设置 账号 + * + * @param username 账号 + */ + public void setUsername(String username) { + this.username = username; + } + + /** + * 获取 密码 + * + * @return password 密码 + */ + public String getPassword() { + return this.password; + } + + /** + * 设置 密码 + * + * @param password 密码 + */ + public void setPassword(String password) { + this.password = password; + } + + @Override + public String toString() { + return "SaHttpBasicAccount{" + + "username='" + username + '\'' + + ", password='" + password + '\'' + + '}'; + } + +} diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/httpauth/basic/SaHttpBasicTemplate.java b/sa-token-core/src/main/java/cn/dev33/satoken/httpauth/basic/SaHttpBasicTemplate.java index 90f8553c..d89e7c82 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/httpauth/basic/SaHttpBasicTemplate.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/httpauth/basic/SaHttpBasicTemplate.java @@ -45,7 +45,7 @@ public class SaHttpBasicTemplate { } /** - * 获取浏览器提交的 Basic 参数 (裁剪掉前缀并解码) + * 获取浏览器提交的 Http Basic 参数 (裁剪掉前缀并解码) * @return 值 */ public String getAuthorizationValue() { @@ -61,7 +61,19 @@ public class SaHttpBasicTemplate { // 裁剪前缀并解码 return SaBase64Util.decode(authorization.substring(6)); } - + + /** + * 获取 Http Basic 账号密码对象 + * @return / + */ + public SaHttpBasicAccount getHttpBasicAccount() { + String authorizationValue = getAuthorizationValue(); + if(authorizationValue == null) { + return null; + } + return new SaHttpBasicAccount(authorizationValue); + } + /** * 对当前会话进行 Basic 校验(使用全局配置的账号密码),校验不通过则抛出异常 */ diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/httpauth/basic/SaHttpBasicUtil.java b/sa-token-core/src/main/java/cn/dev33/satoken/httpauth/basic/SaHttpBasicUtil.java index f99fbed4..2dee3515 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/httpauth/basic/SaHttpBasicUtil.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/httpauth/basic/SaHttpBasicUtil.java @@ -32,13 +32,21 @@ public class SaHttpBasicUtil { public static SaHttpBasicTemplate saHttpBasicTemplate = new SaHttpBasicTemplate(); /** - * 获取浏览器提交的 Basic 参数 (裁剪掉前缀并解码) + * 获取浏览器提交的 Http Basic 参数 (裁剪掉前缀并解码) * @return 值 */ public static String getAuthorizationValue() { return saHttpBasicTemplate.getAuthorizationValue(); } - + + /** + * 获取 Http Basic 账号密码对象 + * @return / + */ + public static SaHttpBasicAccount getHttpBasicAccount() { + return saHttpBasicTemplate.getHttpBasicAccount(); + } + /** * 对当前会话进行 Basic 校验(使用全局配置的账号密码),校验不通过则抛出异常 */ diff --git a/sa-token-doc/plugin/quick-login.md b/sa-token-doc/plugin/quick-login.md index 94961c73..a035ee13 100644 --- a/sa-token-doc/plugin/quick-login.md +++ b/sa-token-doc/plugin/quick-login.md @@ -114,6 +114,12 @@ public class TestController {  +也可以通过 Http Basic 的方式直接进行认证 (一般需要在专门的 API 测试工具下才能正常测试,浏览器会自动忽略@之前的信息) + +``` url +http://sa:123456@localhost:8081/ +``` + ### 可配置信息 你可以在yml中添加如下配置 (所有配置都是可选的) diff --git a/sa-token-plugin/sa-token-quick-login/src/main/java/cn/dev33/satoken/quick/SaQuickRegister.java b/sa-token-plugin/sa-token-quick-login/src/main/java/cn/dev33/satoken/quick/SaQuickRegister.java index a9a9b647..c0f646c2 100644 --- a/sa-token-plugin/sa-token-quick-login/src/main/java/cn/dev33/satoken/quick/SaQuickRegister.java +++ b/sa-token-plugin/sa-token-quick-login/src/main/java/cn/dev33/satoken/quick/SaQuickRegister.java @@ -17,10 +17,13 @@ package cn.dev33.satoken.quick; import cn.dev33.satoken.context.SaHolder; import cn.dev33.satoken.filter.SaServletFilter; +import cn.dev33.satoken.httpauth.basic.SaHttpBasicAccount; +import cn.dev33.satoken.httpauth.basic.SaHttpBasicUtil; import cn.dev33.satoken.quick.config.SaQuickConfig; import cn.dev33.satoken.router.SaRouter; import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.util.SaFoxUtil; +import cn.dev33.satoken.util.SaResult; import cn.dev33.satoken.util.SaTokenConsts; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; @@ -75,11 +78,27 @@ public class SaQuickRegister { .match(SaFoxUtil.convertStringToList(SaQuickManager.getConfig().getInclude())) .notMatch(SaFoxUtil.convertStringToList(SaQuickManager.getConfig().getExclude())) .check(r -> { - // 未登录时直接转发到login.html页面 - if (SaQuickManager.getConfig().getAuth() && ! StpUtil.isLogin()) { - SaHolder.getRequest().forward("/saLogin"); - SaRouter.back(); + + // 如果已关闭认证要求,则直接通过 + if (!SaQuickManager.getConfig().getAuth()) { + return; } + + // 如果请求端提供了 Http Basic 认证信息,那么直接使用此认证信息进行登录判断 + SaHttpBasicAccount hba = SaHttpBasicUtil.getHttpBasicAccount(); + if(hba != null) { + SaResult res = SaQuickManager.getConfig().doLoginHandle.apply(hba.getUsername(), hba.getPassword()); + if(res.getCode() != SaResult.CODE_SUCCESS) { + SaRouter.back(res); + } + } else { + // 未登录时直接转发到 login.html 页面 + if (! StpUtil.isLogin()) { + SaHolder.getRequest().forward("/saLogin"); + SaRouter.back(); + } + } + }); }). diff --git a/sa-token-plugin/sa-token-quick-login/src/main/java/cn/dev33/satoken/quick/config/SaQuickConfig.java b/sa-token-plugin/sa-token-quick-login/src/main/java/cn/dev33/satoken/quick/config/SaQuickConfig.java index 496d89f0..c7ba6a00 100644 --- a/sa-token-plugin/sa-token-quick-login/src/main/java/cn/dev33/satoken/quick/config/SaQuickConfig.java +++ b/sa-token-plugin/sa-token-quick-login/src/main/java/cn/dev33/satoken/quick/config/SaQuickConfig.java @@ -15,6 +15,11 @@ */ package cn.dev33.satoken.quick.config; +import cn.dev33.satoken.quick.function.DoLoginHandleFunction; +import cn.dev33.satoken.stp.StpUtil; +import cn.dev33.satoken.util.SaFoxUtil; +import cn.dev33.satoken.util.SaResult; + /** * sa-quick 配置类 Model * @@ -110,8 +115,27 @@ public class SaQuickConfig { public void setExclude(String exclude) { this.exclude = exclude; } - - + + /** + * 登录处理函数 + */ + public DoLoginHandleFunction doLoginHandle = (name, pwd) -> { + + // 参数完整性校验 + if(SaFoxUtil.isEmpty(name) || SaFoxUtil.isEmpty(pwd)) { + return SaResult.get(500, "请输入账号和密码", null); + } + + // 密码校验:将前端提交的 name、pwd 与配置文件中的配置项进行比对 + if(name.equals(this.getName()) && pwd.equals(this.getPwd())) { + StpUtil.login(this.getName()); + return SaResult.data(StpUtil.getTokenInfo()); + } else { + return SaResult.error("账号或密码输入错误"); + } + }; + + @Override public String toString() { return "SaQuickConfig{" + diff --git a/sa-token-plugin/sa-token-quick-login/src/main/java/cn/dev33/satoken/quick/function/DoLoginHandleFunction.java b/sa-token-plugin/sa-token-quick-login/src/main/java/cn/dev33/satoken/quick/function/DoLoginHandleFunction.java new file mode 100644 index 00000000..13aeecee --- /dev/null +++ b/sa-token-plugin/sa-token-quick-login/src/main/java/cn/dev33/satoken/quick/function/DoLoginHandleFunction.java @@ -0,0 +1,34 @@ +/* + * Copyright 2020-2099 sa-token.cc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package cn.dev33.satoken.quick.function; + +import cn.dev33.satoken.util.SaResult; + +import java.util.function.BiFunction; + +/** + * 函数式接口:登录处理函数 + * + *
参数:账号、密码
+ *返回:登录结果
+ * + * @author click33 + * @since 1.41.0 + */ +@FunctionalInterface +public interface DoLoginHandleFunction extends BiFunction