进行鉴权有四大主流技术:原生开发Filter、Spring框架Interceptor、Shiro以及JWT
一、Filter
Java Filter 既可通过原生 Servlet API 开发,也可集成 Spring 框架实现。在代码审计中,需重点关注其实现逻辑的正确性、拦截路径的精确配置以及例外规则的合理排除。
原生 Filter 与 Spring Filter 在拦截路径定义上的主要差异,体现在配置载体,而拦截器本身编写无差异:前者依赖 web.xml 部署描述符,后者则通过注解或 Java 配置类实现。
在开发Filter时需要实现Filter接口,并重写doFilter
、init
以及destroy
方法,作用依次是请求过滤、初始化以及销毁;由于逻辑问题主要出现在doFilter
方法,因此doFilter
方法是审计的重中之重;以下为Filter示例:
public class AuthFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
// 1. 获取Token
String token = httpRequest.getHeader("Authorization");
// 2. 校验Token
if (token == null || !isValidToken(token)) {
// 3. 未认证处理
httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
httpResponse.getWriter().write("Unauthorized: Invalid token");
return;
}
// 4. 认证通过,继续请求
chain.doFilter(request, response);
}
private boolean isValidToken(String token) {
// 实际项目中调用认证服务
return token != null && token.startsWith("Bearer ");
}
@Override
public void init(FilterConfig filterConfig) {}
@Override
public void destroy() {}
}
1.1 使用XML编写拦截范围
通常纯原生开发会将拦截范围添加至web.xml
中,<filter>
标签注册拦截器,<filter-mapping>
标签配置拦截范围以及例外范围;以下为web.xml
范围示例:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 1. 注册AuthFilter -->
<filter>
<filter-name>AuthenticationFilter</filter-name>
<filter-class>com.example.AuthFilter</filter-class> <!-- 替换为您的完整类路径 -->
</filter>
<!-- 2. 配置AuthFilter的映射 -->
<filter-mapping>
<filter-name>AuthenticationFilter</filter-name>
<!-- 指定要保护的URL模式 -->
<url-pattern>/api/*</url-pattern>
<url-pattern>/admin/*</url-pattern>
<url-pattern>/secure/*</url-pattern>
</filter-mapping>
<!-- 3. 配置例外路径(如果不需要认证) -->
<filter-mapping>
<filter-name>AuthenticationFilter</filter-name>
<url-pattern>/public/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<!-- 禁用该路径的过滤器 -->
<dispatcher>NONE</dispatcher>
</filter-mapping>
</web-app>
1.2 结合Spring编写拦截范围
Spring 结合Filter的主流写法是单独写一个配置类,将已经编辑好的FIlter类添加至FilterRegistrationBean<T>
中;需要注意的是该方法只能添加拦截范围,若要添加例外范围需要在FIlter中编写逻辑;以下为Spring配置范围示例:
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<AuthFilter> authFilter() {
FilterRegistrationBean<AuthFilter> reg = new FilterRegistrationBean<>();
reg.setFilter(new AuthFilter());
reg.addUrlPatterns("/api/*"); // 保护API路径
reg.setOrder(1); // 执行顺序
return reg;
}
}
二、Interceptor
在功能定位上与 Filter 类似,核心职责均为请求拦截处理。作为 Spring MVC 体系的关键组件,它同样被广泛应用于 Spring Boot 应用中,实现对控制器方法的拦截控制。在 Spring MVC 中,拦截器的路径配置通常通过 XML 文件实现,而 Spring Boot 普遍采用 Java 配置类定义拦截范围。
在开发Interceptor需要实现HandlerInterceptor接口,并重写preHandle
、postHandle
以及afterCompletion
方法,作用依次是请求前拦截、请求后拦截以及请求完成后拦截;由于逻辑问题主要出现在preHandle
方法,因此preHandle
方法是审计的重中之重;以下为Interceptor示例:
public class LoggingInterceptor implements HandlerInterceptor {
// Controller 执行前调用
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
System.out.println("请求开始: " + request.getRequestURI());
long startTime = System.currentTimeMillis();
request.setAttribute("startTime", startTime);
return true; // 继续执行流程
}
// Controller 执行后,视图渲染前调用
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) {
System.out.println("Controller 执行完成");
}
// 请求完成后调用(视图渲染完成)
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) {
long startTime = (Long) request.getAttribute("startTime");
long duration = System.currentTimeMillis() - startTime;
System.out.println("请求完成: " + request.getRequestURI()
+ " 耗时: " + duration + "ms");
if (ex != null) {
System.err.println("请求异常: " + ex.getMessage());
}
}
}
2.1 Spring MVC
<mvc:interceptors>
<!-- 全局拦截器 -->
<bean class="com.example.LoggingInterceptor"/>
<!-- 路径匹配拦截器 -->
<mvc:interceptor>
<mvc:mapping path="/api/**"/>
<mvc:exclude-mapping path="/api/public/**"/>
<bean class="com.example.AuthInterceptor"/>
</mvc:interceptor>
<!-- 特定Controller拦截 -->
<mvc:interceptor>
<mvc:mapping path="/admin/**"/>
<ref bean="adminSecurityInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
2.2 Spring boot
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
// 注册拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 基础日志拦截器
registry.addInterceptor(new LoggingInterceptor())
.addPathPatterns("/**") // 所有路径
.excludePathPatterns("/static/**", "/public/**"); // 排除静态资源
}
@Bean
public AuthInterceptor authInterceptor() {
return new AuthInterceptor();
}
@Bean
public PerformanceInterceptor perfInterceptor() {
return new PerformanceInterceptor();
}
}
三、Shiro
Apache Shiro 作为轻量级 Java 安全框架,其核心能力包含精准的拦截范围控制;本文仅对路径拦截规则进行讨论。
Shiro拦截范围编写在配置文件中,排除例外的配置属性为shiro.anon_url
,编写实例:
tumo.shiro.anon_url=\
/login,/logout,/register,\
/,/about,/p/**,/links,/comment/**,/link/list,/article/list,\
/css/**,/js/**,/img/**
四、JWT
JWT 的四大核心安全问题包括:空加密算法使用、服务端签名缺失验证、默认密钥未更新及弱密钥漏洞。其中前两者属于代码逻辑缺陷,而默认密钥问题则源于部署时未修改配置文件中的初始值;主要审计项目中的默认秘钥值。
没有回复内容