mirror of
https://gitee.com/dromara/sa-token.git
synced 2024-12-01 03:18:00 +08:00
新增 Http Basic 认证
This commit is contained in:
parent
3567e9f54b
commit
cc4cc89e27
@ -6,10 +6,12 @@ import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.annotation.SaCheckBasic;
|
||||
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.dev33.satoken.annotation.SaCheckRole;
|
||||
import cn.dev33.satoken.annotation.SaCheckSafe;
|
||||
import cn.dev33.satoken.basic.SaBasicUtil;
|
||||
import cn.dev33.satoken.session.SaSession;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
import cn.dev33.satoken.util.SaTokenConsts;
|
||||
@ -133,6 +135,12 @@ public class SaTokenActionDefaultImpl implements SaTokenAction {
|
||||
SaCheckSafe at = target.getAnnotation(SaCheckSafe.class);
|
||||
SaManager.getStpLogic(null).checkByAnnotation(at);
|
||||
}
|
||||
|
||||
// 校验 @SaCheckBasic 注解
|
||||
if(target.isAnnotationPresent(SaCheckBasic.class)) {
|
||||
SaCheckBasic at = target.getAnnotation(SaCheckBasic.class);
|
||||
SaBasicUtil.check(at.realm(), at.account());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,32 @@
|
||||
package cn.dev33.satoken.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import cn.dev33.satoken.basic.SaBasicTemplate;
|
||||
|
||||
/**
|
||||
* Http Basic 认证:只有通过 Basic 认证才能进入该方法
|
||||
* <p> 可标注在函数、类上(效果等同于标注在此类的所有方法上)
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||
public @interface SaCheckBasic {
|
||||
|
||||
/**
|
||||
* 领域
|
||||
* @return see note
|
||||
*/
|
||||
String realm() default SaBasicTemplate.DEFAULT_REALM;
|
||||
|
||||
/**
|
||||
* 需要校验的账号密码
|
||||
* @return see note
|
||||
*/
|
||||
String account() default "";
|
||||
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package cn.dev33.satoken.basic;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.context.SaHolder;
|
||||
import cn.dev33.satoken.exception.NotBasicAuthException;
|
||||
import cn.dev33.satoken.secure.SaBase64Util;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
|
||||
/**
|
||||
* Sa-Token Http Basic 认证模块
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SaBasicTemplate {
|
||||
|
||||
/**
|
||||
* 默认的 Realm 名称
|
||||
*/
|
||||
public static final String DEFAULT_REALM = "Sa-Token";
|
||||
|
||||
/**
|
||||
* 设置响应头,并抛出异常
|
||||
* @param realm 领域
|
||||
*/
|
||||
public void throwNotBasicAuthException(String realm) {
|
||||
SaHolder.getResponse().setStatus(401).setHeader("WWW-Authenticate", "Basic Realm=" + realm);
|
||||
throw new NotBasicAuthException();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取浏览器提交的 Basic 参数 (裁剪掉前缀并解码)
|
||||
* @return 值
|
||||
*/
|
||||
public String getAuthorizationValue() {
|
||||
|
||||
// 获取请求头 Authorization 参数
|
||||
String authorization = SaHolder.getRequest().getHeader("Authorization");
|
||||
|
||||
// 如果不是以 Basic 作为前缀,则视为无效
|
||||
if(authorization == null || authorization.startsWith("Basic ") == false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 裁剪前缀并解码
|
||||
return SaBase64Util.decode(authorization.substring(6));
|
||||
}
|
||||
|
||||
/**
|
||||
* 对当前会话进行 Basic 校验(使用全局配置的账号密码),校验不通过则抛出异常
|
||||
* @param basicAccount 账号(格式为 user:password)
|
||||
*/
|
||||
public void check() {
|
||||
check(DEFAULT_REALM, SaManager.getConfig().getBasic());
|
||||
}
|
||||
|
||||
/**
|
||||
* 对当前会话进行 Basic 校验(手动设置账号密码),校验不通过则抛出异常
|
||||
* @param account 账号(格式为 user:password)
|
||||
*/
|
||||
public void check(String account) {
|
||||
check(DEFAULT_REALM, account);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对当前会话进行 Basic 校验(手动设置 Realm & 账号密码),校验不通过则抛出异常
|
||||
* @param realm 领域
|
||||
* @param account 账号(格式为 user:password)
|
||||
*/
|
||||
public void check(String realm, String account) {
|
||||
if(SaFoxUtil.isEmpty(account)) {
|
||||
account = SaManager.getConfig().getBasic();
|
||||
}
|
||||
String authorization = getAuthorizationValue();
|
||||
if(SaFoxUtil.isEmpty(authorization) || authorization.equals(account) == false) {
|
||||
throwNotBasicAuthException(realm);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package cn.dev33.satoken.basic;
|
||||
|
||||
/**
|
||||
* Sa-Token Http Basic 认证 Util
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SaBasicUtil {
|
||||
|
||||
/**
|
||||
* 底层 SaBasicTemplate 对象
|
||||
*/
|
||||
public static SaBasicTemplate saBasicTemplate = new SaBasicTemplate();
|
||||
|
||||
/**
|
||||
* 获取浏览器提交的 Basic 参数 (裁剪掉前缀并解码)
|
||||
* @return 值
|
||||
*/
|
||||
public static String getAuthorizationValue() {
|
||||
return saBasicTemplate.getAuthorizationValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 对当前会话进行 Basic 校验(使用全局配置的账号密码),校验不通过则抛出异常
|
||||
* @param basicAccount 账号(格式为 user:password)
|
||||
*/
|
||||
public static void check() {
|
||||
saBasicTemplate.check();
|
||||
}
|
||||
|
||||
/**
|
||||
* 对当前会话进行 Basic 校验(手动设置账号密码),校验不通过则抛出异常
|
||||
* @param account 账号(格式为 user:password)
|
||||
*/
|
||||
public static void check(String account) {
|
||||
saBasicTemplate.check(account);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对当前会话进行 Basic 校验(手动设置 Realm & 账号密码),校验不通过则抛出异常
|
||||
* @param realm 领域
|
||||
* @param account 账号(格式为 user:password)
|
||||
*/
|
||||
public static void check(String realm, String account) {
|
||||
saBasicTemplate.check(realm, account);
|
||||
}
|
||||
|
||||
}
|
@ -74,6 +74,11 @@ public class SaTokenConfig implements Serializable {
|
||||
* Id-Token的有效期 (单位: 秒)
|
||||
*/
|
||||
private long idTokenTimeout = 60 * 60 * 24;
|
||||
|
||||
/**
|
||||
* Http Basic 认证的账号&密码
|
||||
*/
|
||||
private String basic = "";
|
||||
|
||||
|
||||
/**
|
||||
@ -373,6 +378,22 @@ public class SaTokenConfig implements Serializable {
|
||||
this.idTokenTimeout = idTokenTimeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Http Basic 认证的账号&密码
|
||||
*/
|
||||
public String getBasic() {
|
||||
return basic;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param basic Http Basic 认证的账号&密码
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaTokenConfig setBasic(String basic) {
|
||||
this.basic = basic;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SSO单点登录配置对象
|
||||
@ -388,6 +409,7 @@ public class SaTokenConfig implements Serializable {
|
||||
this.sso = sso;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SaTokenConfig [tokenName=" + tokenName + ", timeout=" + timeout + ", activityTimeout=" + activityTimeout
|
||||
@ -396,12 +418,9 @@ public class SaTokenConfig implements Serializable {
|
||||
+ ", dataRefreshPeriod=" + dataRefreshPeriod + ", tokenSessionCheckLogin=" + tokenSessionCheckLogin
|
||||
+ ", autoRenew=" + autoRenew + ", cookieDomain=" + cookieDomain + ", tokenPrefix=" + tokenPrefix
|
||||
+ ", isPrint=" + isPrint + ", isLog=" + isLog + ", jwtSecretKey=" + jwtSecretKey + ", idTokenTimeout="
|
||||
+ idTokenTimeout + ", sso=" + sso + "]";
|
||||
+ idTokenTimeout + ", basic=" + basic + ", sso=" + sso + "]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <h1> 本函数设计已过时,未来版本可能移除此函数,请及时更换为 setIsConcurrent() ,使用方式保持不变 </h1>
|
||||
* @param allowConcurrentLogin see note
|
||||
|
@ -28,6 +28,13 @@ public interface SaResponse {
|
||||
* @param timeout 过期时间 (秒)
|
||||
*/
|
||||
public void addCookie(String name, String value, String path, String domain, int timeout);
|
||||
|
||||
/**
|
||||
* 设置响应状态码
|
||||
* @param sc 响应状态码
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaResponse setStatus(int sc);
|
||||
|
||||
/**
|
||||
* 在响应头里写入一个值
|
||||
|
@ -0,0 +1,24 @@
|
||||
package cn.dev33.satoken.exception;
|
||||
|
||||
/**
|
||||
* 一个异常:代表会话未能通过 Http Basic 认证
|
||||
* @author kong
|
||||
*/
|
||||
public class NotBasicAuthException extends SaTokenException {
|
||||
|
||||
/**
|
||||
* 序列化版本号
|
||||
*/
|
||||
private static final long serialVersionUID = 6806129545290130144L;
|
||||
|
||||
/** 异常提示语 */
|
||||
public static final String BE_MESSAGE = "no basic auth";
|
||||
|
||||
/**
|
||||
* 一个异常:代表会话未通过 Http Basic 认证
|
||||
*/
|
||||
public NotBasicAuthException() {
|
||||
super(BE_MESSAGE);
|
||||
}
|
||||
|
||||
}
|
@ -34,7 +34,8 @@ public class SaCheckAspect {
|
||||
"@within(cn.dev33.satoken.annotation.SaCheckLogin) || @annotation(cn.dev33.satoken.annotation.SaCheckLogin) || "
|
||||
+ "@within(cn.dev33.satoken.annotation.SaCheckRole) || @annotation(cn.dev33.satoken.annotation.SaCheckRole) || "
|
||||
+ "@within(cn.dev33.satoken.annotation.SaCheckPermission) || @annotation(cn.dev33.satoken.annotation.SaCheckPermission) || "
|
||||
+ "@within(cn.dev33.satoken.annotation.SaCheckSafe) || @annotation(cn.dev33.satoken.annotation.SaCheckSafe)";
|
||||
+ "@within(cn.dev33.satoken.annotation.SaCheckSafe) || @annotation(cn.dev33.satoken.annotation.SaCheckSafe) || "
|
||||
+ "@within(cn.dev33.satoken.annotation.SaCheckBasic) || @annotation(cn.dev33.satoken.annotation.SaCheckBasic)";
|
||||
|
||||
/**
|
||||
* 声明AOP签名
|
||||
|
@ -27,23 +27,31 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
<version>2.0.0.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<!-- spring-web -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>5.0.4.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<!-- reactor-core -->
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-core</artifactId>
|
||||
<version>3.1.4.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<!-- OAuth2.0 (optional) -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-oauth2</artifactId>
|
||||
<version>${sa-token-version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- config -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
|
@ -74,6 +74,15 @@ public class SaResponseForReactor implements SaResponse {
|
||||
response.addCookie(builder.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置响应状态码
|
||||
*/
|
||||
@Override
|
||||
public SaResponse setStatus(int sc) {
|
||||
response.setStatusCode(HttpStatus.valueOf(sc));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在响应头里写入一个值
|
||||
*/
|
||||
|
@ -6,6 +6,8 @@ import org.springframework.util.PathMatcher;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.action.SaTokenAction;
|
||||
import cn.dev33.satoken.basic.SaBasicTemplate;
|
||||
import cn.dev33.satoken.basic.SaBasicUtil;
|
||||
import cn.dev33.satoken.config.SaTokenConfig;
|
||||
import cn.dev33.satoken.context.SaTokenContext;
|
||||
import cn.dev33.satoken.dao.SaTokenDao;
|
||||
@ -105,6 +107,16 @@ public class SaBeanInject {
|
||||
SaIdUtil.saIdTemplate = saIdTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注入 Sa-Token Http Basic 认证模块
|
||||
*
|
||||
* @param saBasicTemplate saBasicTemplate对象
|
||||
*/
|
||||
@Autowired(required = false)
|
||||
public void setSaSsoTemplate(SaBasicTemplate saBasicTemplate) {
|
||||
SaBasicUtil.saBasicTemplate = saBasicTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注入 Sa-Token-SSO 单点登录模块 Bean
|
||||
*
|
||||
|
@ -0,0 +1,40 @@
|
||||
package cn.dev33.satoken.reactor.spring.oauth2;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
|
||||
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
|
||||
import cn.dev33.satoken.oauth2.config.SaOAuth2Config;
|
||||
import cn.dev33.satoken.oauth2.logic.SaOAuth2Template;
|
||||
import cn.dev33.satoken.oauth2.logic.SaOAuth2Util;
|
||||
|
||||
/**
|
||||
* 注入 Sa-Token-OAuth2 所需要的Bean
|
||||
*
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
@ConditionalOnClass(SaOAuth2Manager.class)
|
||||
public class SaOAuth2BeanInject {
|
||||
|
||||
/**
|
||||
* 注入OAuth2配置Bean
|
||||
*
|
||||
* @param saOAuth2Config 配置对象
|
||||
*/
|
||||
@Autowired(required = false)
|
||||
public void setSaOAuth2Config(SaOAuth2Config saOAuth2Config) {
|
||||
SaOAuth2Manager.setConfig(saOAuth2Config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注入代码模板Bean
|
||||
*
|
||||
* @param saOAuth2Template 代码模板Bean
|
||||
*/
|
||||
@Autowired(required = false)
|
||||
public void setSaOAuth2Interface(SaOAuth2Template saOAuth2Template) {
|
||||
SaOAuth2Util.saOAuth2Template = saOAuth2Template;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package cn.dev33.satoken.reactor.spring.oauth2;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
|
||||
import cn.dev33.satoken.oauth2.config.SaOAuth2Config;
|
||||
|
||||
/**
|
||||
* 注册 Sa-Token-OAuth2 所需要的Bean
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
@ConditionalOnClass(SaOAuth2Manager.class)
|
||||
public class SaOAuth2BeanRegister {
|
||||
|
||||
/**
|
||||
* 获取OAuth2配置Bean
|
||||
* @return 配置对象
|
||||
*/
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = "sa-token.oauth2")
|
||||
public SaOAuth2Config getSaOAuth2Config() {
|
||||
return new SaOAuth2Config();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Sa-Token-OAuth2 模块自动化配置(只有引入了Sa-Token-OAuth2模块后,此包下的代码才会开始工作)
|
||||
*/
|
||||
package cn.dev33.satoken.reactor.spring.oauth2;
|
@ -1,4 +1,6 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
cn.dev33.satoken.reactor.spring.SaBeanRegister,\
|
||||
cn.dev33.satoken.reactor.spring.SaBeanInject,\
|
||||
cn.dev33.satoken.reactor.spring.SaHistoryVersionInject
|
||||
cn.dev33.satoken.reactor.spring.SaHistoryVersionInject,\
|
||||
cn.dev33.satoken.reactor.spring.oauth2.SaOAuth2BeanRegister,\
|
||||
cn.dev33.satoken.reactor.spring.oauth2.SaOAuth2BeanInject
|
@ -62,6 +62,15 @@ public class SaResponseForServlet implements SaResponse {
|
||||
response.addCookie(cookie);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置响应状态码
|
||||
*/
|
||||
@Override
|
||||
public SaResponse setStatus(int sc) {
|
||||
response.setStatus(sc);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在响应头里写入一个值
|
||||
*/
|
||||
@ -84,4 +93,5 @@ public class SaResponseForServlet implements SaResponse {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -11,6 +11,8 @@ import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.dev33.satoken.annotation.SaCheckRole;
|
||||
import cn.dev33.satoken.annotation.SaCheckSafe;
|
||||
import cn.dev33.satoken.basic.SaBasicTemplate;
|
||||
import cn.dev33.satoken.basic.SaBasicUtil;
|
||||
import cn.dev33.satoken.config.SaTokenConfig;
|
||||
import cn.dev33.satoken.dao.SaTokenDao;
|
||||
import cn.dev33.satoken.id.SaIdTemplate;
|
||||
@ -75,10 +77,16 @@ public class XPluginImp implements Plugin {
|
||||
SaIdUtil.saIdTemplate = bw.raw();
|
||||
});
|
||||
|
||||
// Sa-Token Http Basic 认证模块 Bean
|
||||
Aop.getAsyn(SaBasicTemplate.class, bw->{
|
||||
SaBasicUtil.saBasicTemplate = bw.raw();
|
||||
});
|
||||
|
||||
// Sa-Token-SSO 单点登录模块 Bean
|
||||
Aop.getAsyn(SaSsoTemplate.class, bw->{
|
||||
SaSsoUtil.saSsoTemplate = bw.raw();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -36,6 +36,12 @@ public class SaResponseForSolon implements SaResponse {
|
||||
ctx.cookieSet(name, value, domain, path, timeout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SaResponse setStatus(int sc) {
|
||||
ctx.statusSet(sc);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SaResponse setHeader(String name, String value) {
|
||||
ctx.headerSet(name, value);
|
||||
|
@ -6,6 +6,8 @@ import org.springframework.util.PathMatcher;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.action.SaTokenAction;
|
||||
import cn.dev33.satoken.basic.SaBasicTemplate;
|
||||
import cn.dev33.satoken.basic.SaBasicUtil;
|
||||
import cn.dev33.satoken.config.SaTokenConfig;
|
||||
import cn.dev33.satoken.context.SaTokenContext;
|
||||
import cn.dev33.satoken.dao.SaTokenDao;
|
||||
@ -105,6 +107,16 @@ public class SaBeanInject {
|
||||
SaIdUtil.saIdTemplate = saIdTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注入 Sa-Token Http Basic 认证模块
|
||||
*
|
||||
* @param saBasicTemplate saBasicTemplate对象
|
||||
*/
|
||||
@Autowired(required = false)
|
||||
public void setSaSsoTemplate(SaBasicTemplate saBasicTemplate) {
|
||||
SaBasicUtil.saBasicTemplate = saBasicTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注入 Sa-Token-SSO 单点登录模块 Bean
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user