springBoot项目中怎么实现接口拦截

系列文章目录


前言

在Spring Boot项目中实现接口拦截通常涉及到两个关键组件:拦截器(Interceptor)和过滤器(Filter)。Spring框架提供了这两种机制来进行HTTP请求的拦截,可以根据需要的粒度和场景来选择使用
重点
但是在项目中都是将其抽取出来作为一个单独的权限服务,和用户是绑定的关系,并非是直接在代码中进行硬编码做拦截接口,而是通过注解或者是通过配置文件,在访问接口前通过调用RPC接口的方式进行权限校验等等。


提示:以下是本篇文章正文内容,下面案例可供参考

一、使用Interceptors:

Spring MVC的拦截器可以让你在请求被处理之前后以及完成之后进行一些操作。要创建一个拦截器,你需要:

  1. 创建一个类实现 HandlerInterceptor 接口或者继承 HandlerInterceptorAdapter 类。
  2. 实现或重写 preHandle(), postHandle(), 和 afterCompletion() 方法。
  3. 注册这个拦截器。

代码

1.实现HandlerInterceptor接口:

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class MyCustomInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 在Controller处理之前调用
        // 返回true继续流程,返回false中止流程
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 在Controller处理之后调用,视图渲染之前
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 在整个请求结束之后调用,也就是在DispatcherServlet 渲染了视图执行
    }
}

2.配置类去注册这个拦截器:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Autowired
    private MyCustomInterceptor myCustomInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(myCustomInterceptor)
                .addPathPatterns("/**"); // 你可以添加特定路径的模式去匹配需要拦截的请求
    }
}

3.配置类去注册这个拦截器:

二.使用Filters

Spring Boot也支持标准的Servlet Filters。
这些filters在Spring MVC的DispatcherServlet 处理请求之前执行,这使得它们在处理请求时更加底层,也适用于非Spring管理的组件。

代码

1.实现Filter接口:

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

@Component
public class MyCustomFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        
        HttpServletRequest req = (HttpServletRequest) request;
        // 自定义一些操作
        chain.doFilter(request, response); // 继续执行链中的下一个过滤器
    }
}

Spring Boot会自动检测到实现了 Filter 接口的bean,并将它添加到filter链中。另外你也可以手动注册一个filter,通过一个 FilterRegistrationBean:

2、注入到容器

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean<MyCustomFilter> myFilter() {
        FilterRegistrationBean<MyCustomFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new MyCustomFilter());
        registrationBean.addUrlPatterns("/*");
        return registrationBean;
    }
}

总结: 选择Interceptor还是Filter

1、如果你想要利用Spring MVC的一些高级特性(如控制器映射、参数处理等),或者只是拦截由Spring处理的请求,使用Interceptor。
2、如果你需要更底层的控制,或者你需要拦截不论是不是Spring MVC处理的请求(比如直接请求静态资源文件),你可能会需要使用Filter。

补充:

拦截器(Interceptor)和过滤器(Filter)主要解决的问题是如何在不改变现有业务代码的情况下,统一处理HTTP请求和响应中的跨切面问题。他们在不同的层面上提供了处理请求的能力,这样开发人员可以以模块化的方式应用通用功能,而不必在每一个控制器或组件中重复相同的逻辑。

下面是拦截器和过滤器主要解决的几个问题:

拦截器(Interceptor):

**身份验证和授权:**确保用户在访问受保护资源之前已经正确地进行了身份验证,并且具备相应的权限。

日志记录:自动记录请求的详细信息,以便于调试、监控和审计。

异常处理:拦截由控制器抛出的异常,提供统一的异常处理逻辑。

性能监控:拦截请求,以监控处理时间,从而提供性能进度信息。

事务管理:在请求的生命周期中处理复杂的事务边界。

输入验证:拦截请求和对输入数据执行预处理,比如数据清洗、格式验证。

本地化:确定请求的本地化设置并相应地应用它们。

API协议处理:确保请求遵循特定的API协议,例如签名验证、版本控制。

过滤器(Filter):

HTTP请求修改:在Servlet层面上对进入的HTTP请求进行修改,比如增加、修改、删除请求头部信息。

HTTP响应修改:在返回给客户端之前对HTTP响应进行修改。

跨域资源共享(CORS):添加CORS(Cross-Origin Resource Sharing)头信息,允许或限制跨域请求。

安全性:实施如同拦截器的身份验证和授权控制,但在Servlet更早的阶段执行。

编码设置:确保请求和响应采用正确的字符编码。

资源管理:如在请求处理前后对资源进行分配和释放。

压缩:对响应体数据进行压缩以降低带宽消耗。

缓存控制:实现HTTP缓存逻辑,如ETags或者设置过期头部信息。

通过以上功能,拦截器和过滤器使得Spring Boot项目可以通过统一而高效的方式解决跨多个请求和响应的共性问题,并使得业务逻辑保持干净和聚焦于核心功能。

  • 27
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用Shiro实现接口授权的具体实现步骤如下: 1. 引入Shiro和Spring-boot-starter依赖: ```xml <dependencies> <!-- Shiro依赖 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.8.0</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.8.0</version> </dependency> <!-- Spring-boot-starter依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> ``` 2. 配置Shiro的Filter和Realm: ```java @Configuration public class ShiroConfig { @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) { ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean(); filterFactoryBean.setSecurityManager(securityManager); filterFactoryBean.setLoginUrl("/login"); // 设置未登录时跳转的URL filterFactoryBean.setUnauthorizedUrl("/unauthorized"); // 设置未授权时跳转的URL // 配置拦截规则 Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); filterChainDefinitionMap.put("/login", "anon"); // 登录接口放行 filterChainDefinitionMap.put("/logout", "logout"); // 注销接口放行 filterChainDefinitionMap.put("/**", "authc"); // 其他接口全部拦截,需要认证后访问 filterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return filterFactoryBean; } @Bean public DefaultWebSecurityManager securityManager(Realm realm) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(realm); return securityManager; } @Bean public Realm realm() { // 自定义Realm实现 return new MyRealm(); } } ``` 3. 自定义Realm实现授权逻辑: ```java public class MyRealm extends AuthorizingRealm { @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // 获取当前用户信息 String username = (String) principals.getPrimaryPrincipal(); // 查询用户角色和权限信息 Set<String> roles = new HashSet<>(); Set<String> permissions = new HashSet<>(); // TODO: 查询用户角色和权限信息 // roles.add("admin"); // permissions.add("user:list"); // 封装角色和权限信息 SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); authorizationInfo.setRoles(roles); authorizationInfo.setStringPermissions(permissions); return authorizationInfo; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { // 获取用户输入的用户名和密码 String username = (String) token.getPrincipal(); String password = new String((char[]) token.getCredentials()); // TODO: 验证用户名和密码是否正确 // if (!"admin".equals(username)) { // throw new UnknownAccountException("用户名不存在!"); // } // if (!"admin".equals(password)) { // throw new IncorrectCredentialsException("密码错误!"); // } // 封装用户认证信息 SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username, password, getName()); return authenticationInfo; } } ``` 4. 在Controller使用注解实现接口授权: ```java @RestController @RequestMapping("/user") public class UserController { @RequiresPermissions("user:list") @GetMapping("/list") public String list() { return "用户列表"; } @RequiresPermissions("user:add") @PostMapping("/add") public String add() { return "添加用户"; } } ``` 在Controller方法上使用@RequiresPermissions注解,指定需要的权限,如果当前用户没有该权限,则会抛出AuthorizationException异常,可以在异常处理器统一处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值