mirror of
https://github.com/chillzhuang/blade-tool
synced 2024-12-12 12:19:27 +08:00
🎉 2.2.0.RELEASE
This commit is contained in:
parent
7d088af59f
commit
70a1574a8a
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springblade</groupId>
|
<groupId>org.springblade</groupId>
|
||||||
<artifactId>blade-tool</artifactId>
|
<artifactId>blade-tool</artifactId>
|
||||||
<version>2.1.1</version>
|
<version>2.2.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
@ -29,6 +29,12 @@ spring:
|
|||||||
add-mappings: false
|
add-mappings: false
|
||||||
datasource:
|
datasource:
|
||||||
driver-class-name: com.mysql.jdbc.Driver
|
driver-class-name: com.mysql.jdbc.Driver
|
||||||
|
hikari:
|
||||||
|
connection-test-query: SELECT 1 FROM DUAL
|
||||||
|
connection-timeout: 30000
|
||||||
|
maximum-pool-size: 5
|
||||||
|
max-lifetime: 1800000
|
||||||
|
minimum-idle: 1
|
||||||
devtools:
|
devtools:
|
||||||
restart:
|
restart:
|
||||||
log-condition-evaluation-delta: false
|
log-condition-evaluation-delta: false
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>blade-tool</artifactId>
|
<artifactId>blade-tool</artifactId>
|
||||||
<groupId>org.springblade</groupId>
|
<groupId>org.springblade</groupId>
|
||||||
<version>2.1.1</version>
|
<version>2.2.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>blade-tool</artifactId>
|
<artifactId>blade-tool</artifactId>
|
||||||
<groupId>org.springblade</groupId>
|
<groupId>org.springblade</groupId>
|
||||||
<version>2.1.1</version>
|
<version>2.2.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
@ -93,6 +93,7 @@ public class BladeApplication {
|
|||||||
props.setProperty("blade.is-local", String.valueOf(isLocalDev()));
|
props.setProperty("blade.is-local", String.valueOf(isLocalDev()));
|
||||||
props.setProperty("blade.dev-mode", profile.equals(AppConstant.PROD_CODE) ? "false" : "true");
|
props.setProperty("blade.dev-mode", profile.equals(AppConstant.PROD_CODE) ? "false" : "true");
|
||||||
props.setProperty("blade.service.version", AppConstant.APPLICATION_VERSION);
|
props.setProperty("blade.service.version", AppConstant.APPLICATION_VERSION);
|
||||||
|
props.setProperty("spring.main.allow-bean-definition-overriding", "true");
|
||||||
props.setProperty("spring.cloud.nacos.discovery.server-addr", NacosConstant.NACOS_ADDR);
|
props.setProperty("spring.cloud.nacos.discovery.server-addr", NacosConstant.NACOS_ADDR);
|
||||||
props.setProperty("spring.cloud.nacos.config.server-addr", NacosConstant.NACOS_ADDR);
|
props.setProperty("spring.cloud.nacos.config.server-addr", NacosConstant.NACOS_ADDR);
|
||||||
props.setProperty("spring.cloud.nacos.config.prefix", NacosConstant.NACOS_CONFIG_PREFIX);
|
props.setProperty("spring.cloud.nacos.config.prefix", NacosConstant.NACOS_CONFIG_PREFIX);
|
||||||
|
@ -1,3 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
|
||||||
|
* <p>
|
||||||
|
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.gnu.org/licenses/lgpl.html
|
||||||
|
* <p>
|
||||||
|
* 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 org.springblade.core.launch.constant;
|
package org.springblade.core.launch.constant;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
|
||||||
|
* <p>
|
||||||
|
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.gnu.org/licenses/lgpl.html
|
||||||
|
* <p>
|
||||||
|
* 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 org.springblade.core.launch.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Token配置常量.
|
||||||
|
*
|
||||||
|
* @author Chill
|
||||||
|
*/
|
||||||
|
public interface TokenConstant {
|
||||||
|
|
||||||
|
String SIGN_KEY = "BladeX";
|
||||||
|
String AVATAR = "avatar";
|
||||||
|
String HEADER = "blade-auth";
|
||||||
|
String BEARER = "bearer";
|
||||||
|
String ACCESS_TOKEN = "access_token";
|
||||||
|
String REFRESH_TOKEN = "refresh_token";
|
||||||
|
String TOKEN_TYPE = "token_type";
|
||||||
|
String EXPIRES_IN = "expires_in";
|
||||||
|
String ACCOUNT = "account";
|
||||||
|
String USER_ID = "user_id";
|
||||||
|
String ROLE_ID = "role_id";
|
||||||
|
String USER_NAME = "user_name";
|
||||||
|
String ROLE_NAME = "role_name";
|
||||||
|
String TENANT_CODE = "tenant_code";
|
||||||
|
String CLIENT_ID = "client_id";
|
||||||
|
String LICENSE = "license";
|
||||||
|
String LICENSE_NAME = "powered by bladex";
|
||||||
|
String DEFAULT_AVATAR = "https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png";
|
||||||
|
Integer AUTH_LENGTH = 7;
|
||||||
|
|
||||||
|
}
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>blade-tool</artifactId>
|
<artifactId>blade-tool</artifactId>
|
||||||
<groupId>org.springblade</groupId>
|
<groupId>org.springblade</groupId>
|
||||||
<version>2.1.1</version>
|
<version>2.2.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>blade-tool</artifactId>
|
<artifactId>blade-tool</artifactId>
|
||||||
<groupId>org.springblade</groupId>
|
<groupId>org.springblade</groupId>
|
||||||
<version>2.1.1</version>
|
<version>2.2.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>blade-tool</artifactId>
|
<artifactId>blade-tool</artifactId>
|
||||||
<groupId>org.springblade</groupId>
|
<groupId>org.springblade</groupId>
|
||||||
<version>2.1.1</version>
|
<version>2.2.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
@ -28,6 +28,17 @@
|
|||||||
<artifactId>blade-core-tool</artifactId>
|
<artifactId>blade-core-tool</artifactId>
|
||||||
<version>${blade.tool.version}</version>
|
<version>${blade.tool.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!--Jdbc-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>tomcat-jdbc</artifactId>
|
||||||
|
<groupId>org.apache.tomcat</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -42,5 +42,5 @@ public class AuthInfo {
|
|||||||
@ApiModelProperty(value = "过期时间")
|
@ApiModelProperty(value = "过期时间")
|
||||||
private long expiresIn;
|
private long expiresIn;
|
||||||
@ApiModelProperty(value = "许可证")
|
@ApiModelProperty(value = "许可证")
|
||||||
private String license = "made by blade";
|
private String license = "powered by blade";
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,11 @@ import java.io.Serializable;
|
|||||||
public class BladeUser implements Serializable {
|
public class BladeUser implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
/**
|
||||||
|
* 客户端id
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(hidden = true)
|
||||||
|
private String clientId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户id
|
* 用户id
|
||||||
|
@ -20,7 +20,9 @@ import java.lang.annotation.*;
|
|||||||
/**
|
/**
|
||||||
* 权限注解 用于检查权限 规定访问权限
|
* 权限注解 用于检查权限 规定访问权限
|
||||||
*
|
*
|
||||||
* @author Chill
|
* @example @PreAuth("#userVO.id<10")
|
||||||
|
* @example @PreAuth("hasRole(#test, #test1)")
|
||||||
|
* @example @PreAuth("hasPermission(#test) and @PreAuth.hasPermission(#test)")
|
||||||
*/
|
*/
|
||||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@ -24,7 +24,7 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* secure模块api放行默认配置
|
* secure注册默认配置
|
||||||
*
|
*
|
||||||
* @author Chill
|
* @author Chill
|
||||||
*/
|
*/
|
||||||
|
@ -18,32 +18,50 @@ package org.springblade.core.secure.config;
|
|||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import org.springblade.core.secure.aspect.AuthAspect;
|
import org.springblade.core.secure.aspect.AuthAspect;
|
||||||
|
import org.springblade.core.secure.interceptor.ClientInterceptor;
|
||||||
import org.springblade.core.secure.interceptor.SecureInterceptor;
|
import org.springblade.core.secure.interceptor.SecureInterceptor;
|
||||||
|
import org.springblade.core.secure.props.BladeClientProperties;
|
||||||
|
import org.springblade.core.secure.props.BladeSecureProperties;
|
||||||
|
import org.springblade.core.secure.provider.ClientDetailsServiceImpl;
|
||||||
|
import org.springblade.core.secure.provider.IClientDetailsService;
|
||||||
import org.springblade.core.secure.registry.SecureRegistry;
|
import org.springblade.core.secure.registry.SecureRegistry;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 配置类
|
* 安全配置类
|
||||||
*
|
*
|
||||||
* @author Chill
|
* @author Chill
|
||||||
*/
|
*/
|
||||||
@Order
|
@Order
|
||||||
@Configuration
|
@Configuration
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
|
@EnableConfigurationProperties({BladeSecureProperties.class, BladeClientProperties.class})
|
||||||
public class SecureConfiguration implements WebMvcConfigurer {
|
public class SecureConfiguration implements WebMvcConfigurer {
|
||||||
|
|
||||||
private final SecureRegistry secureRegistry;
|
private final SecureRegistry secureRegistry;
|
||||||
|
|
||||||
|
private final BladeSecureProperties secureProperties;
|
||||||
|
|
||||||
|
private final BladeClientProperties clientProperties;
|
||||||
|
|
||||||
|
private final JdbcTemplate jdbcTemplate;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInterceptors(InterceptorRegistry registry) {
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
|
clientProperties.getClient().forEach(cs -> registry.addInterceptor(new ClientInterceptor(cs.getClientId())).addPathPatterns(cs.getPathPatterns()));
|
||||||
|
|
||||||
if (secureRegistry.isEnable()) {
|
if (secureRegistry.isEnable()) {
|
||||||
registry.addInterceptor(new SecureInterceptor())
|
registry.addInterceptor(new SecureInterceptor())
|
||||||
.excludePathPatterns(secureRegistry.getExcludePatterns())
|
.excludePathPatterns(secureRegistry.getExcludePatterns())
|
||||||
.excludePathPatterns(secureRegistry.getDefaultExcludePatterns());
|
.excludePathPatterns(secureRegistry.getDefaultExcludePatterns())
|
||||||
|
.excludePathPatterns(secureProperties.getExcludePatterns());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,4 +70,10 @@ public class SecureConfiguration implements WebMvcConfigurer {
|
|||||||
return new AuthAspect();
|
return new AuthAspect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean(IClientDetailsService.class)
|
||||||
|
public IClientDetailsService clientDetailsService() {
|
||||||
|
return new ClientDetailsServiceImpl(jdbcTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,55 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
|
||||||
|
* <p>
|
||||||
|
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.gnu.org/licenses/lgpl.html
|
||||||
|
* <p>
|
||||||
|
* 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 org.springblade.core.secure.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权校验常量
|
||||||
|
*
|
||||||
|
* @author Chill
|
||||||
|
*/
|
||||||
|
public interface SecureConstant {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 认证请求头
|
||||||
|
*/
|
||||||
|
String BASIC_HEADER_KEY = "Authorization";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 认证请求头前缀
|
||||||
|
*/
|
||||||
|
String BASIC_HEADER_PREFIX = "Basic ";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* blade_client表字段
|
||||||
|
*/
|
||||||
|
String CLIENT_FIELDS = "client_id, client_secret, access_token_validity, refresh_token_validity";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* blade_client查询语句
|
||||||
|
*/
|
||||||
|
String BASE_STATEMENT = "select " + CLIENT_FIELDS + " from blade_client";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* blade_client查询排序
|
||||||
|
*/
|
||||||
|
String DEFAULT_FIND_STATEMENT = BASE_STATEMENT + " order by client_id";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询client_id
|
||||||
|
*/
|
||||||
|
String DEFAULT_SELECT_STATEMENT = BASE_STATEMENT + " where client_id = ?";
|
||||||
|
|
||||||
|
}
|
@ -32,7 +32,7 @@ public class SecureException extends RuntimeException {
|
|||||||
|
|
||||||
public SecureException(String message) {
|
public SecureException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
this.resultCode = ResultCode.INTERNAL_SERVER_ERROR;
|
this.resultCode = ResultCode.UN_AUTHORIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SecureException(IResultCode resultCode) {
|
public SecureException(IResultCode resultCode) {
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
|
||||||
|
* <p>
|
||||||
|
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.gnu.org/licenses/lgpl.html
|
||||||
|
* <p>
|
||||||
|
* 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 org.springblade.core.secure.interceptor;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springblade.core.secure.BladeUser;
|
||||||
|
import org.springblade.core.secure.utils.SecureUtil;
|
||||||
|
import org.springblade.core.tool.api.R;
|
||||||
|
import org.springblade.core.tool.api.ResultCode;
|
||||||
|
import org.springblade.core.tool.constant.BladeConstant;
|
||||||
|
import org.springblade.core.tool.jackson.JsonUtil;
|
||||||
|
import org.springblade.core.tool.utils.StringUtil;
|
||||||
|
import org.springblade.core.tool.utils.WebUtil;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端校验
|
||||||
|
*
|
||||||
|
* @author Chill
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class ClientInterceptor extends HandlerInterceptorAdapter {
|
||||||
|
|
||||||
|
private final String clientId;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
|
||||||
|
BladeUser user = SecureUtil.getUser();
|
||||||
|
if (user != null && StringUtil.equals(clientId, SecureUtil.getClientIdFromHeader()) && StringUtil.equals(clientId, user.getClientId())) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
log.warn("客户端认证失败,请求接口:{},请求IP:{},请求参数:{}", request.getRequestURI(), WebUtil.getIP(request), JsonUtil.toJson(request.getParameterMap()));
|
||||||
|
R result = R.fail(ResultCode.UN_AUTHORIZED);
|
||||||
|
response.setHeader(BladeConstant.CONTENT_TYPE_NAME, MediaType.APPLICATION_JSON_UTF8_VALUE);
|
||||||
|
response.setCharacterEncoding(BladeConstant.UTF_8);
|
||||||
|
response.setStatus(HttpServletResponse.SC_OK);
|
||||||
|
try {
|
||||||
|
response.getWriter().write(Objects.requireNonNull(JsonUtil.toJson(result)));
|
||||||
|
} catch (IOException ex) {
|
||||||
|
log.error(ex.getMessage());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -15,13 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
package org.springblade.core.secure.interceptor;
|
package org.springblade.core.secure.interceptor;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springblade.core.secure.utils.SecureUtil;
|
import org.springblade.core.secure.utils.SecureUtil;
|
||||||
import org.springblade.core.tool.api.R;
|
import org.springblade.core.tool.api.R;
|
||||||
import org.springblade.core.tool.api.ResultCode;
|
import org.springblade.core.tool.api.ResultCode;
|
||||||
import org.springblade.core.tool.constant.BladeConstant;
|
import org.springblade.core.tool.constant.BladeConstant;
|
||||||
import org.springblade.core.tool.jackson.JsonUtil;
|
import org.springblade.core.tool.jackson.JsonUtil;
|
||||||
import org.springblade.core.tool.utils.StringPool;
|
|
||||||
import org.springblade.core.tool.utils.WebUtil;
|
import org.springblade.core.tool.utils.WebUtil;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||||
@ -37,6 +37,7 @@ import java.util.Objects;
|
|||||||
* @author Chill
|
* @author Chill
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@AllArgsConstructor
|
||||||
public class SecureInterceptor extends HandlerInterceptorAdapter {
|
public class SecureInterceptor extends HandlerInterceptorAdapter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -46,7 +47,7 @@ public class SecureInterceptor extends HandlerInterceptorAdapter {
|
|||||||
} else {
|
} else {
|
||||||
log.warn("签名认证失败,请求接口:{},请求IP:{},请求参数:{}", request.getRequestURI(), WebUtil.getIP(request), JsonUtil.toJson(request.getParameterMap()));
|
log.warn("签名认证失败,请求接口:{},请求IP:{},请求参数:{}", request.getRequestURI(), WebUtil.getIP(request), JsonUtil.toJson(request.getParameterMap()));
|
||||||
R result = R.fail(ResultCode.UN_AUTHORIZED);
|
R result = R.fail(ResultCode.UN_AUTHORIZED);
|
||||||
response.setCharacterEncoding(StringPool.UTF_8);
|
response.setCharacterEncoding(BladeConstant.UTF_8);
|
||||||
response.setHeader(BladeConstant.CONTENT_TYPE_NAME, MediaType.APPLICATION_JSON_UTF8_VALUE);
|
response.setHeader(BladeConstant.CONTENT_TYPE_NAME, MediaType.APPLICATION_JSON_UTF8_VALUE);
|
||||||
response.setStatus(HttpServletResponse.SC_OK);
|
response.setStatus(HttpServletResponse.SC_OK);
|
||||||
try {
|
try {
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
|
||||||
|
* <p>
|
||||||
|
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.gnu.org/licenses/lgpl.html
|
||||||
|
* <p>
|
||||||
|
* 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 org.springblade.core.secure.props;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端校验配置
|
||||||
|
*
|
||||||
|
* @author Chill
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@ConfigurationProperties("blade.secure")
|
||||||
|
public class BladeClientProperties {
|
||||||
|
|
||||||
|
private final List<ClientSecure> client = new ArrayList<>();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
|
||||||
|
* <p>
|
||||||
|
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.gnu.org/licenses/lgpl.html
|
||||||
|
* <p>
|
||||||
|
* 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 org.springblade.core.secure.props;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* secure放行额外配置
|
||||||
|
*
|
||||||
|
* @author Chill
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@ConfigurationProperties("blade.secure.url")
|
||||||
|
public class BladeSecureProperties {
|
||||||
|
|
||||||
|
private final List<String> excludePatterns = new ArrayList<>();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
|
||||||
|
* <p>
|
||||||
|
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.gnu.org/licenses/lgpl.html
|
||||||
|
* <p>
|
||||||
|
* 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 org.springblade.core.secure.props;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端令牌认证信息
|
||||||
|
*
|
||||||
|
* @author Chill
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ClientSecure {
|
||||||
|
|
||||||
|
private String clientId;
|
||||||
|
|
||||||
|
private final List<String> pathPatterns = new ArrayList<>();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
|
||||||
|
* <p>
|
||||||
|
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.gnu.org/licenses/lgpl.html
|
||||||
|
* <p>
|
||||||
|
* 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 org.springblade.core.secure.provider;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端详情
|
||||||
|
*
|
||||||
|
* @author Chill
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ClientDetails implements IClientDetails {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端id
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "客户端id")
|
||||||
|
private String clientId;
|
||||||
|
/**
|
||||||
|
* 客户端密钥
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "客户端密钥")
|
||||||
|
private String clientSecret;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 令牌过期秒数
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "令牌过期秒数")
|
||||||
|
private Integer accessTokenValidity;
|
||||||
|
/**
|
||||||
|
* 刷新令牌过期秒数
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "刷新令牌过期秒数")
|
||||||
|
private Integer refreshTokenValidity;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
|
||||||
|
* <p>
|
||||||
|
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.gnu.org/licenses/lgpl.html
|
||||||
|
* <p>
|
||||||
|
* 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 org.springblade.core.secure.provider;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.springblade.core.secure.constant.SecureConstant;
|
||||||
|
import org.springframework.jdbc.core.BeanPropertyRowMapper;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取客户端详情
|
||||||
|
*
|
||||||
|
* @author Chill
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class ClientDetailsServiceImpl implements IClientDetailsService {
|
||||||
|
|
||||||
|
private final JdbcTemplate jdbcTemplate;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IClientDetails loadClientByClientId(String clientId) {
|
||||||
|
try {
|
||||||
|
return jdbcTemplate.queryForObject(SecureConstant.DEFAULT_SELECT_STATEMENT, new String[]{clientId}, new BeanPropertyRowMapper<>(ClientDetails.class));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
|
||||||
|
* <p>
|
||||||
|
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.gnu.org/licenses/lgpl.html
|
||||||
|
* <p>
|
||||||
|
* 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 org.springblade.core.secure.provider;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多终端详情接口
|
||||||
|
*
|
||||||
|
* @author Chill
|
||||||
|
*/
|
||||||
|
public interface IClientDetails extends Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端id.
|
||||||
|
*
|
||||||
|
* @return String.
|
||||||
|
*/
|
||||||
|
String getClientId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端密钥.
|
||||||
|
*
|
||||||
|
* @return String.
|
||||||
|
*/
|
||||||
|
String getClientSecret();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端token过期时间
|
||||||
|
*
|
||||||
|
* @return Integer
|
||||||
|
*/
|
||||||
|
Integer getAccessTokenValidity();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端刷新token过期时间
|
||||||
|
*
|
||||||
|
* @return Integer
|
||||||
|
*/
|
||||||
|
Integer getRefreshTokenValidity();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
|
||||||
|
* <p>
|
||||||
|
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.gnu.org/licenses/lgpl.html
|
||||||
|
* <p>
|
||||||
|
* 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 org.springblade.core.secure.provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多终端注册接口
|
||||||
|
*
|
||||||
|
* @author Chill
|
||||||
|
*/
|
||||||
|
public interface IClientDetailsService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据clientId获取Client详情
|
||||||
|
*
|
||||||
|
* @param clientId 客户端id
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
IClientDetails loadClientByClientId(String clientId);
|
||||||
|
|
||||||
|
}
|
@ -50,9 +50,6 @@ public class SecureRegistry {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置放行api
|
* 设置放行api
|
||||||
*
|
|
||||||
* @param patterns api配置
|
|
||||||
* @return SecureRegistry
|
|
||||||
*/
|
*/
|
||||||
public SecureRegistry excludePathPatterns(String... patterns) {
|
public SecureRegistry excludePathPatterns(String... patterns) {
|
||||||
return excludePathPatterns(Arrays.asList(patterns));
|
return excludePathPatterns(Arrays.asList(patterns));
|
||||||
@ -60,9 +57,6 @@ public class SecureRegistry {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置放行api
|
* 设置放行api
|
||||||
*
|
|
||||||
* @param patterns api配置
|
|
||||||
* @return SecureRegistry
|
|
||||||
*/
|
*/
|
||||||
public SecureRegistry excludePathPatterns(List<String> patterns) {
|
public SecureRegistry excludePathPatterns(List<String> patterns) {
|
||||||
this.excludePatterns.addAll(patterns);
|
this.excludePatterns.addAll(patterns);
|
||||||
|
@ -19,19 +19,19 @@ import io.jsonwebtoken.Claims;
|
|||||||
import io.jsonwebtoken.JwtBuilder;
|
import io.jsonwebtoken.JwtBuilder;
|
||||||
import io.jsonwebtoken.Jwts;
|
import io.jsonwebtoken.Jwts;
|
||||||
import io.jsonwebtoken.SignatureAlgorithm;
|
import io.jsonwebtoken.SignatureAlgorithm;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import org.springblade.core.launch.constant.TokenConstant;
|
||||||
import org.springblade.core.secure.BladeUser;
|
import org.springblade.core.secure.BladeUser;
|
||||||
import org.springblade.core.tool.utils.Charsets;
|
import org.springblade.core.secure.constant.SecureConstant;
|
||||||
import org.springblade.core.tool.utils.Func;
|
import org.springblade.core.secure.exception.SecureException;
|
||||||
import org.springblade.core.tool.utils.StringPool;
|
import org.springblade.core.secure.provider.IClientDetails;
|
||||||
import org.springblade.core.tool.utils.WebUtil;
|
import org.springblade.core.secure.provider.IClientDetailsService;
|
||||||
|
import org.springblade.core.tool.utils.*;
|
||||||
|
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.security.Key;
|
import java.security.Key;
|
||||||
import java.util.Base64;
|
import java.util.*;
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Secure工具类
|
* Secure工具类
|
||||||
@ -39,18 +39,25 @@ import java.util.Map;
|
|||||||
* @author Chill
|
* @author Chill
|
||||||
*/
|
*/
|
||||||
public class SecureUtil {
|
public class SecureUtil {
|
||||||
public static final String BLADE_USER_REQUEST_ATTR = "_BLADE_USER_REQUEST_ATTR_";
|
private static final String BLADE_USER_REQUEST_ATTR = "_BLADE_USER_REQUEST_ATTR_";
|
||||||
|
|
||||||
public final static String HEADER = "blade-auth";
|
private final static String HEADER = TokenConstant.HEADER;
|
||||||
public final static String BEARER = "bearer";
|
private final static String BEARER = TokenConstant.BEARER;
|
||||||
public final static String ACCOUNT = "account";
|
private final static String ACCOUNT = TokenConstant.ACCOUNT;
|
||||||
public final static String USER_ID = "userId";
|
private final static String USER_ID = TokenConstant.USER_ID;
|
||||||
public final static String ROLE_ID = "roleId";
|
private final static String ROLE_ID = TokenConstant.ROLE_ID;
|
||||||
public final static String USER_NAME = "userName";
|
private final static String USER_NAME = TokenConstant.USER_NAME;
|
||||||
public final static String ROLE_NAME = "roleName";
|
private final static String ROLE_NAME = TokenConstant.ROLE_NAME;
|
||||||
public final static String TENANT_CODE = "tenantCode";
|
private final static String TENANT_CODE = TokenConstant.TENANT_CODE;
|
||||||
public final static Integer AUTH_LENGTH = 7;
|
private final static String CLIENT_ID = TokenConstant.CLIENT_ID;
|
||||||
public static String BASE64_SECURITY = Base64.getEncoder().encodeToString("BladeX".getBytes(Charsets.UTF_8));
|
private final static Integer AUTH_LENGTH = TokenConstant.AUTH_LENGTH;
|
||||||
|
private static String BASE64_SECURITY = Base64.getEncoder().encodeToString(TokenConstant.SIGN_KEY.getBytes(Charsets.UTF_8));
|
||||||
|
|
||||||
|
private static IClientDetailsService clientDetailsService;
|
||||||
|
|
||||||
|
static {
|
||||||
|
clientDetailsService = SpringUtil.getBean(IClientDetailsService.class);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取用户信息
|
* 获取用户信息
|
||||||
@ -59,8 +66,11 @@ public class SecureUtil {
|
|||||||
*/
|
*/
|
||||||
public static BladeUser getUser() {
|
public static BladeUser getUser() {
|
||||||
HttpServletRequest request = WebUtil.getRequest();
|
HttpServletRequest request = WebUtil.getRequest();
|
||||||
|
if (request == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
// 优先从 request 中获取
|
// 优先从 request 中获取
|
||||||
BladeUser bladeUser = (BladeUser) request.getAttribute(BLADE_USER_REQUEST_ATTR);
|
Object bladeUser = request.getAttribute(BLADE_USER_REQUEST_ATTR);
|
||||||
if (bladeUser == null) {
|
if (bladeUser == null) {
|
||||||
bladeUser = getUser(request);
|
bladeUser = getUser(request);
|
||||||
if (bladeUser != null) {
|
if (bladeUser != null) {
|
||||||
@ -68,7 +78,7 @@ public class SecureUtil {
|
|||||||
request.setAttribute(BLADE_USER_REQUEST_ATTR, bladeUser);
|
request.setAttribute(BLADE_USER_REQUEST_ATTR, bladeUser);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return bladeUser;
|
return (BladeUser) bladeUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,6 +92,7 @@ public class SecureUtil {
|
|||||||
if (claims == null) {
|
if (claims == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
String clientId = Func.toStr(claims.get(SecureUtil.CLIENT_ID));
|
||||||
Integer userId = Func.toInt(claims.get(SecureUtil.USER_ID));
|
Integer userId = Func.toInt(claims.get(SecureUtil.USER_ID));
|
||||||
String tenantCode = Func.toStr(claims.get(SecureUtil.TENANT_CODE));
|
String tenantCode = Func.toStr(claims.get(SecureUtil.TENANT_CODE));
|
||||||
String roleId = Func.toStr(claims.get(SecureUtil.ROLE_ID));
|
String roleId = Func.toStr(claims.get(SecureUtil.ROLE_ID));
|
||||||
@ -89,6 +100,7 @@ public class SecureUtil {
|
|||||||
String roleName = Func.toStr(claims.get(SecureUtil.ROLE_NAME));
|
String roleName = Func.toStr(claims.get(SecureUtil.ROLE_NAME));
|
||||||
String userName = Func.toStr(claims.get(SecureUtil.USER_NAME));
|
String userName = Func.toStr(claims.get(SecureUtil.USER_NAME));
|
||||||
BladeUser bladeUser = new BladeUser();
|
BladeUser bladeUser = new BladeUser();
|
||||||
|
bladeUser.setClientId(clientId);
|
||||||
bladeUser.setUserId(userId);
|
bladeUser.setUserId(userId);
|
||||||
bladeUser.setTenantCode(tenantCode);
|
bladeUser.setTenantCode(tenantCode);
|
||||||
bladeUser.setAccount(account);
|
bladeUser.setAccount(account);
|
||||||
@ -183,7 +195,6 @@ public class SecureUtil {
|
|||||||
return (null == user) ? StringPool.EMPTY : user.getRoleName();
|
return (null == user) ? StringPool.EMPTY : user.getRoleName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取租户编号
|
* 获取租户编号
|
||||||
*
|
*
|
||||||
@ -205,6 +216,27 @@ public class SecureUtil {
|
|||||||
return (null == user) ? StringPool.EMPTY : user.getTenantCode();
|
return (null == user) ? StringPool.EMPTY : user.getTenantCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取客户端id
|
||||||
|
*
|
||||||
|
* @return tenantCode
|
||||||
|
*/
|
||||||
|
public static String getClientId() {
|
||||||
|
BladeUser user = getUser();
|
||||||
|
return (null == user) ? StringPool.EMPTY : user.getClientId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取客户端id
|
||||||
|
*
|
||||||
|
* @param request request
|
||||||
|
* @return tenantCode
|
||||||
|
*/
|
||||||
|
public static String getClientId(HttpServletRequest request) {
|
||||||
|
BladeUser user = getUser(request);
|
||||||
|
return (null == user) ? StringPool.EMPTY : user.getClientId();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取Claims
|
* 获取Claims
|
||||||
*
|
*
|
||||||
@ -229,7 +261,7 @@ public class SecureUtil {
|
|||||||
* @return header
|
* @return header
|
||||||
*/
|
*/
|
||||||
public static String getHeader() {
|
public static String getHeader() {
|
||||||
return getHeader(WebUtil.getRequest());
|
return getHeader(Objects.requireNonNull(WebUtil.getRequest()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -250,17 +282,16 @@ public class SecureUtil {
|
|||||||
*/
|
*/
|
||||||
public static Claims parseJWT(String jsonWebToken) {
|
public static Claims parseJWT(String jsonWebToken) {
|
||||||
try {
|
try {
|
||||||
Claims claims = Jwts.parser()
|
return Jwts.parser()
|
||||||
.setSigningKey(Base64.getDecoder().decode(BASE64_SECURITY))
|
.setSigningKey(Base64.getDecoder().decode(BASE64_SECURITY))
|
||||||
.parseClaimsJws(jsonWebToken).getBody();
|
.parseClaimsJws(jsonWebToken).getBody();
|
||||||
return claims;
|
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建jwt
|
* 创建令牌
|
||||||
*
|
*
|
||||||
* @param user user
|
* @param user user
|
||||||
* @param audience audience
|
* @param audience audience
|
||||||
@ -269,6 +300,17 @@ public class SecureUtil {
|
|||||||
* @return jwt
|
* @return jwt
|
||||||
*/
|
*/
|
||||||
public static String createJWT(Map<String, String> user, String audience, String issuer, boolean isExpire) {
|
public static String createJWT(Map<String, String> user, String audience, String issuer, boolean isExpire) {
|
||||||
|
|
||||||
|
String[] tokens = extractAndDecodeHeader();
|
||||||
|
assert tokens.length == 2;
|
||||||
|
String clientId = tokens[0];
|
||||||
|
String clientSecret = tokens[1];
|
||||||
|
|
||||||
|
// 校验客户端信息
|
||||||
|
if (!validateClient(clientId, clientSecret)) {
|
||||||
|
throw new SecureException("客户端认证失败!");
|
||||||
|
}
|
||||||
|
|
||||||
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
|
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
|
||||||
|
|
||||||
long nowMillis = System.currentTimeMillis();
|
long nowMillis = System.currentTimeMillis();
|
||||||
@ -287,6 +329,9 @@ public class SecureUtil {
|
|||||||
//设置JWT参数
|
//设置JWT参数
|
||||||
user.forEach(builder::claim);
|
user.forEach(builder::claim);
|
||||||
|
|
||||||
|
//设置应用id
|
||||||
|
builder.claim(CLIENT_ID, clientId);
|
||||||
|
|
||||||
//添加Token过期时间
|
//添加Token过期时间
|
||||||
if (isExpire) {
|
if (isExpire) {
|
||||||
long expMillis = nowMillis + getExpire();
|
long expMillis = nowMillis + getExpire();
|
||||||
@ -313,4 +358,65 @@ public class SecureUtil {
|
|||||||
return cal.getTimeInMillis() - System.currentTimeMillis();
|
return cal.getTimeInMillis() - System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取过期时间的秒数(次日凌晨3点)
|
||||||
|
*
|
||||||
|
* @return expire
|
||||||
|
*/
|
||||||
|
public static int getExpireSeconds() {
|
||||||
|
return (int) (getExpire() / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端信息解码
|
||||||
|
*/
|
||||||
|
@SneakyThrows
|
||||||
|
public static String[] extractAndDecodeHeader() {
|
||||||
|
// 获取请求头客户端信息
|
||||||
|
String header = Objects.requireNonNull(WebUtil.getRequest()).getHeader(SecureConstant.BASIC_HEADER_KEY);
|
||||||
|
if (header == null || !header.startsWith(SecureConstant.BASIC_HEADER_PREFIX)) {
|
||||||
|
throw new SecureException("No client information in request header");
|
||||||
|
}
|
||||||
|
byte[] base64Token = header.substring(6).getBytes(Charsets.UTF_8_NAME);
|
||||||
|
|
||||||
|
byte[] decoded;
|
||||||
|
try {
|
||||||
|
decoded = Base64.getDecoder().decode(base64Token);
|
||||||
|
} catch (IllegalArgumentException var7) {
|
||||||
|
throw new RuntimeException("Failed to decode basic authentication token");
|
||||||
|
}
|
||||||
|
|
||||||
|
String token = new String(decoded, Charsets.UTF_8_NAME);
|
||||||
|
int index = token.indexOf(StringPool.COLON);
|
||||||
|
if (index == -1) {
|
||||||
|
throw new RuntimeException("Invalid basic authentication token");
|
||||||
|
} else {
|
||||||
|
return new String[]{token.substring(0, index), token.substring(index + 1)};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取请求头中的客户端id
|
||||||
|
*/
|
||||||
|
public static String getClientIdFromHeader() {
|
||||||
|
String[] tokens = extractAndDecodeHeader();
|
||||||
|
assert tokens.length == 2;
|
||||||
|
return tokens[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验Client
|
||||||
|
*
|
||||||
|
* @param clientId 客户端id
|
||||||
|
* @param clientSecret 客户端密钥
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
private static boolean validateClient(String clientId, String clientSecret) {
|
||||||
|
IClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
|
||||||
|
if (clientDetails != null) {
|
||||||
|
return StringUtil.equals(clientId, clientDetails.getClientId()) && StringUtil.equals(clientSecret, clientDetails.getClientSecret());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>blade-tool</artifactId>
|
<artifactId>blade-tool</artifactId>
|
||||||
<groupId>org.springblade</groupId>
|
<groupId>org.springblade</groupId>
|
||||||
<version>2.1.1</version>
|
<version>2.2.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springblade</groupId>
|
<groupId>org.springblade</groupId>
|
||||||
<artifactId>blade-tool</artifactId>
|
<artifactId>blade-tool</artifactId>
|
||||||
<version>2.1.1</version>
|
<version>2.2.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package org.springblade.core.tool.utils;
|
package org.springblade.core.tool.utils;
|
||||||
|
|
||||||
|
|
||||||
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.charset.UnsupportedCharsetException;
|
import java.nio.charset.UnsupportedCharsetException;
|
||||||
|
|
||||||
@ -29,15 +30,20 @@ public class Charsets {
|
|||||||
/**
|
/**
|
||||||
* 字符集ISO-8859-1
|
* 字符集ISO-8859-1
|
||||||
*/
|
*/
|
||||||
public static final java.nio.charset.Charset ISO_8859_1 = StandardCharsets.ISO_8859_1;
|
public static final Charset ISO_8859_1 = StandardCharsets.ISO_8859_1;
|
||||||
|
public static final String ISO_8859_1_NAME = ISO_8859_1.name();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 字符集GBK
|
* 字符集GBK
|
||||||
*/
|
*/
|
||||||
public static final java.nio.charset.Charset GBK = java.nio.charset.Charset.forName(StringPool.GBK);
|
public static final Charset GBK = Charset.forName(StringPool.GBK);
|
||||||
|
public static final String GBK_NAME = GBK.name();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 字符集utf-8
|
* 字符集utf-8
|
||||||
*/
|
*/
|
||||||
public static final java.nio.charset.Charset UTF_8 = StandardCharsets.UTF_8;
|
public static final Charset UTF_8 = StandardCharsets.UTF_8;
|
||||||
|
public static final String UTF_8_NAME = UTF_8.name();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 转换为Charset对象
|
* 转换为Charset对象
|
||||||
|
4
pom.xml
4
pom.xml
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
<groupId>org.springblade</groupId>
|
<groupId>org.springblade</groupId>
|
||||||
<artifactId>blade-tool</artifactId>
|
<artifactId>blade-tool</artifactId>
|
||||||
<version>2.1.1</version>
|
<version>2.2.0</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<name>blade-tool</name>
|
<name>blade-tool</name>
|
||||||
<description>
|
<description>
|
||||||
@ -36,7 +36,7 @@
|
|||||||
</scm>
|
</scm>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<blade.tool.version>2.1.1</blade.tool.version>
|
<blade.tool.version>2.2.0</blade.tool.version>
|
||||||
|
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
<maven.plugin.version>3.8.0</maven.plugin.version>
|
<maven.plugin.version>3.8.0</maven.plugin.version>
|
||||||
|
Loading…
Reference in New Issue
Block a user