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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 RequestUri
|
||||
*
|
||||
* @param request HttpServletRequest
|
||||
* @return {RequestUri}
|
||||
*/
|
||||
public static String getRequestURI(HttpServletRequest request) {
|
||||
if (request == null) {
|
||||
return StringPool.EMPTY;
|
||||
}
|
||||
return request.getRequestURI();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回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.console.UReportServlet;
|
||||
import com.bstek.ureport.provider.report.ReportProvider;
|
||||
import jakarta.servlet.Servlet;
|
||||
import org.springblade.core.report.props.ReportDatabaseProperties;
|
||||
import org.springblade.core.report.props.ReportProperties;
|
||||
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.core.annotation.Order;
|
||||
|
||||
import jakarta.servlet.Servlet;
|
||||
|
||||
/**
|
||||
* 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")
|
||||
public class ReportProperties {
|
||||
private Boolean enabled = true;
|
||||
private Boolean auth = true;
|
||||
private Boolean disableHttpSessionReportCache = false;
|
||||
private Boolean disableFileProvider = true;
|
||||
private String fileStoreDir = StringPool.EMPTY;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user