mirror of
https://gitee.com/smallc/blade-tool.git
synced 2026-07-10 18:39:44 +08:00
🎉 ureport增加token认证功能
This commit is contained in:
parent
ad84479e92
commit
450cf2e2a2
|
|
@ -124,6 +124,19 @@ public class WebUtil extends org.springframework.web.util.WebUtils {
|
||||||
return (requestAttributes == null) ? null : ((ServletRequestAttributes) requestAttributes).getRequest();
|
return (requestAttributes == null) ? null : ((ServletRequestAttributes) requestAttributes).getRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 RequestUri
|
||||||
|
*
|
||||||
|
* @param request HttpServletRequest
|
||||||
|
* @return {RequestUri}
|
||||||
|
*/
|
||||||
|
public static String getRequestURI(HttpServletRequest request) {
|
||||||
|
if (request == null) {
|
||||||
|
return StringPool.EMPTY;
|
||||||
|
}
|
||||||
|
return request.getRequestURI();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回json
|
* 返回json
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.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.report.config;
|
||||||
|
|
||||||
|
import jakarta.servlet.Filter;
|
||||||
|
import org.springblade.core.report.filter.UReportAuthFilter;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UReport认证配置类
|
||||||
|
*
|
||||||
|
* @author BladeX
|
||||||
|
*/
|
||||||
|
@Order
|
||||||
|
@AutoConfiguration
|
||||||
|
@ConditionalOnProperty(value = "report.auth", havingValue = "true", matchIfMissing = true)
|
||||||
|
public class ReportAuthConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public FilterRegistrationBean<Filter> uReportAuthFilter() {
|
||||||
|
FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
|
||||||
|
registration.setFilter(new UReportAuthFilter());
|
||||||
|
registration.addUrlPatterns("/ureport/*");
|
||||||
|
registration.setName("uReportAuthFilter");
|
||||||
|
registration.setOrder(1);
|
||||||
|
return registration;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -18,6 +18,7 @@ package org.springblade.core.report.config;
|
||||||
import com.bstek.ureport.UReportPropertyPlaceholderConfigurer;
|
import com.bstek.ureport.UReportPropertyPlaceholderConfigurer;
|
||||||
import com.bstek.ureport.console.UReportServlet;
|
import com.bstek.ureport.console.UReportServlet;
|
||||||
import com.bstek.ureport.provider.report.ReportProvider;
|
import com.bstek.ureport.provider.report.ReportProvider;
|
||||||
|
import jakarta.servlet.Servlet;
|
||||||
import org.springblade.core.report.props.ReportDatabaseProperties;
|
import org.springblade.core.report.props.ReportDatabaseProperties;
|
||||||
import org.springblade.core.report.props.ReportProperties;
|
import org.springblade.core.report.props.ReportProperties;
|
||||||
import org.springblade.core.report.provider.DatabaseProvider;
|
import org.springblade.core.report.provider.DatabaseProvider;
|
||||||
|
|
@ -32,8 +33,6 @@ import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.ImportResource;
|
import org.springframework.context.annotation.ImportResource;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
|
|
||||||
import jakarta.servlet.Servlet;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UReport配置类
|
* UReport配置类
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,203 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.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.report.filter;
|
||||||
|
|
||||||
|
import jakarta.servlet.*;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import jakarta.servlet.http.HttpSession;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springblade.core.secure.utils.AuthUtil;
|
||||||
|
import org.springblade.core.tool.utils.WebUtil;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UReport 鉴权过滤器
|
||||||
|
*
|
||||||
|
* <p>处理 /ureport/* 路径的访问鉴权,放行前端资源文件</p>
|
||||||
|
*
|
||||||
|
* @author BladeX
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class UReportAuthFilter implements Filter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前端资源文件扩展名
|
||||||
|
*/
|
||||||
|
private static final List<String> STATIC_RESOURCE_EXTENSIONS = Arrays.asList(
|
||||||
|
".js", ".css", ".png", ".jpg", ".jpeg", ".gif", ".ico", ".svg",
|
||||||
|
".woff", ".woff2", ".ttf", ".eot", ".map", ".html", ".htm"
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源文件路径前缀
|
||||||
|
*/
|
||||||
|
private static final String RESOURCE_PATH_PREFIX = "/ureport/res/ureport-asserts";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Session 中存储认证状态的键名
|
||||||
|
*/
|
||||||
|
private static final String SESSION_AUTH_KEY = "UREPORT_AUTHENTICATED";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Session 中存储用户信息的键名
|
||||||
|
*/
|
||||||
|
private static final String SESSION_USER_KEY = "UREPORT_USER_INFO";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Session 中存储用户主键的键名
|
||||||
|
*/
|
||||||
|
private static final String SESSION_USER_ID = "UREPORT_USER_ID";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Session 超时时间,单位为秒
|
||||||
|
*/
|
||||||
|
private static final Integer INTERVAL_TIME = 120 * 60;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||||
|
throws IOException, ServletException {
|
||||||
|
|
||||||
|
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
||||||
|
HttpServletResponse httpResponse = (HttpServletResponse) response;
|
||||||
|
|
||||||
|
String requestURI = WebUtil.getRequestURI(httpRequest);
|
||||||
|
String requestIP = WebUtil.getIP(httpRequest);
|
||||||
|
|
||||||
|
// 检查是否为静态资源文件,如果是则直接放行
|
||||||
|
if (isStaticResource(requestURI)) {
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证用户是否已认证(优先检查 Session,再检查 Token)
|
||||||
|
if (!isAuthenticatedWithSession(httpRequest)) {
|
||||||
|
log.warn("未授权访问 UReport API: {}, IP: {}", requestURI, requestIP);
|
||||||
|
handleUnauthorized(httpResponse);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证通过放行请求
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否为静态资源文件
|
||||||
|
*/
|
||||||
|
private boolean isStaticResource(String requestURI) {
|
||||||
|
// 检查是否为资源文件路径
|
||||||
|
if (requestURI.startsWith(RESOURCE_PATH_PREFIX)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查文件扩展名
|
||||||
|
String lowerCaseURI = requestURI.toLowerCase();
|
||||||
|
return STATIC_RESOURCE_EXTENSIONS.stream()
|
||||||
|
.anyMatch(lowerCaseURI::endsWith);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证用户是否已认证(Session + Token 双重验证)
|
||||||
|
*/
|
||||||
|
private boolean isAuthenticatedWithSession(HttpServletRequest request) {
|
||||||
|
HttpSession session = request.getSession(false);
|
||||||
|
|
||||||
|
// 1. 优先检查 Session 认证状态
|
||||||
|
if (session != null && Boolean.TRUE.equals(session.getAttribute(SESSION_AUTH_KEY))) {
|
||||||
|
log.debug("Session 认证有效,用户: {}", session.getAttribute(SESSION_USER_KEY));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Session 无效,尝试 Token 认证
|
||||||
|
if (isTokenAuthenticated(request)) {
|
||||||
|
// Token 认证成功,建立 Session
|
||||||
|
establishSession(request);
|
||||||
|
log.info("Token 认证成功,已建立 Session 会话");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Token 认证验证
|
||||||
|
*/
|
||||||
|
private boolean isTokenAuthenticated(HttpServletRequest request) {
|
||||||
|
try {
|
||||||
|
Long userId = AuthUtil.getUserId(request);
|
||||||
|
return userId != null && userId > 0;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.debug("Token 认证失败: {}", e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 建立认证会话
|
||||||
|
*/
|
||||||
|
private void establishSession(HttpServletRequest request) {
|
||||||
|
HttpSession session = request.getSession(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
String userAccount = AuthUtil.getUserAccount(request);
|
||||||
|
Long userId = AuthUtil.getUserId(request);
|
||||||
|
|
||||||
|
// 设置认证标记
|
||||||
|
session.setAttribute(SESSION_AUTH_KEY, true);
|
||||||
|
session.setAttribute(SESSION_USER_KEY, userAccount);
|
||||||
|
session.setAttribute(SESSION_USER_ID, userId);
|
||||||
|
|
||||||
|
// 设置 Session 超时时间(60分钟)
|
||||||
|
session.setMaxInactiveInterval(INTERVAL_TIME);
|
||||||
|
|
||||||
|
log.debug("建立 UReport 认证会话: 用户 {}, SessionID: {}", userAccount, session.getId());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("建立认证会话失败: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从 Session 获取用户账号
|
||||||
|
*/
|
||||||
|
private String getUserFromSession(HttpServletRequest request) {
|
||||||
|
HttpSession session = request.getSession(false);
|
||||||
|
if (session != null) {
|
||||||
|
Object userAccount = session.getAttribute(SESSION_USER_KEY);
|
||||||
|
return userAccount != null ? userAccount.toString() : "未知用户";
|
||||||
|
}
|
||||||
|
return "未知用户";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理未授权访问
|
||||||
|
*/
|
||||||
|
private void handleUnauthorized(HttpServletResponse response) throws IOException {
|
||||||
|
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||||
|
response.setContentType("application/json;charset=UTF-8");
|
||||||
|
response.setCharacterEncoding("UTF-8");
|
||||||
|
|
||||||
|
try (PrintWriter writer = response.getWriter()) {
|
||||||
|
writer.write("访问 UReport 需要 BladeX 的 Token 认证");
|
||||||
|
writer.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -28,6 +28,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
@ConfigurationProperties(prefix = "report")
|
@ConfigurationProperties(prefix = "report")
|
||||||
public class ReportProperties {
|
public class ReportProperties {
|
||||||
private Boolean enabled = true;
|
private Boolean enabled = true;
|
||||||
|
private Boolean auth = true;
|
||||||
private Boolean disableHttpSessionReportCache = false;
|
private Boolean disableHttpSessionReportCache = false;
|
||||||
private Boolean disableFileProvider = true;
|
private Boolean disableFileProvider = true;
|
||||||
private String fileStoreDir = StringPool.EMPTY;
|
private String fileStoreDir = StringPool.EMPTY;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user