springboot拦截器鉴权

拦截器:作用类似于Servlet中的Filter,用于对处理器进行预处理和后处理。

public interface HandlerInterceptor {
	default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		return true;
	}
	default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			@Nullable ModelAndView modelAndView) throws Exception {
	}
	default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
			@Nullable Exception ex) throws Exception {
	}

}

其中 preHandle()实现处理器预处理,请求会先到这里,当这个方法返回值是true的时候表示处理器可以正常往下执行,返回false,则不会继续执行处理器的代码,一般用来身份验证和鉴权。
postHandle()是后处理回调方法,也就是控制器完成后执行。
afterCompletion()在视图渲染完毕时候调用,一般用来进行统一的异常处理,日志处理。

在springboot中可以通过实现HandlerInterceptor接口实现拦截器,这里主要介绍通过预处理做身份鉴权的方法。

  1. 定义注解
import java.lang.annotation.*;

/***
 * token校验拦截器
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface LoginRequired {

}
  1. 定义token校验方法
@Service
public class AccountAuthProxy {
	public boolean verifyToken(Long userId, String token){
		//定义校验规则
	}
}
  1. 定义拦截器
import com.xiaomi.gamecenter.misc.socialsquare.annotation.LoginRequired;
import com.xiaomi.gamecenter.misc.socialsquare.config.ConfigService;
import com.xiaomi.gamecenter.misc.socialsquare.constants.Err;
import com.xiaomi.gamecenter.misc.socialsquare.proxy.AccountAuthProxy;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class AccountInterceptor implements HandlerInterceptor {
    private static final Logger log = LoggerFactory.getLogger(AccountInterceptor.class);
    @Autowired
    AccountAuthProxy accountAuthProxy;

    public static final String USER_ID_NAME = "userId";
    public static final String TOKEN_NAME = "token";

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{
        Err err;
        try{
            if (handler instanceof HandlerMethod) {
                String token = parseTokenFromReq(request);
                long uid = parseUserIdFromReq(request);
                HandlerMethod method = (HandlerMethod) handler;
                LoginRequired option = method.getMethodAnnotation(LoginRequired.class);
                //如果未加注解则直接放行
                if (option == null) {
                    return true;
                }
                boolean pass = accountAuthProxy.verifyToken(uid, token);
                log.info("token verify result---userId={}, token={}, pass={}", uid, token, pass);
                if (!pass) {
                    log.info("token verify error---userId={}, token={}", uid, token);
                     throw new ServiceException(RetCode.LOGIN_EXPIRE);
                }
            }else {
                //处理预检请求
                response.setStatus(HttpServletResponse.SC_OK);
                return true;
            }
        }catch (Exception e){
            log.error("login interceptor error---", e);
        }
        return true;
    }
    /**
     * 从HTTP请求解析中得到用户ID,兼容了不同参数名
     */
    private long parseUserIdFromReq(HttpServletRequest request) {
        if (StringUtils.isNumeric(request.getParameter(USER_ID_NAME))) {
            return Long.parseLong(request.getParameter(USER_ID_NAME));
        } else {
            return 0L;
        }
    }

    /**
     * 从HTTP请求参数中解析得到token
     */
    private String parseTokenFromReq(HttpServletRequest request) {
        String token = null;
        if (StringUtils.isNotBlank(request.getParameter(TOKEN_NAME))) {
            token = request.getParameter(TOKEN_NAME);
        }
        return token;
    }

}
  1. 添加拦截器配置
import com.xiaomi.gamecenter.misc.socialsquare.interceptor.AccountInterceptor;
import org.springframework.context.annotation.Bean;
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 WebConfig implements WebMvcConfigurer {

    @Bean
    public AccountInterceptor accountInterceptor(){
        return new AccountInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 添加账号拦截器
        registry.addInterceptor(accountInterceptor())
                .addPathPatterns("/**");
    }

}
  1. token校验
    在需要校验token的接口上面添加注解 @LoginRequired ,则在请求接口的时候会走拦截器里面校验token的方法,接口捕获异常,返回前端登录错误的状态码。
    例如:
    /***
     * 获取该用户的帖子列表
     */
    @PostMapping("/user/list")
    @TokenCheck
    public BaseDataVo<UserContentVo> contentList(@RequestBody UserContentReq req){
        BaseDataVo<UserContentVo> responseVo = new BaseDataVo<>();
        try{
            responseVo = contentService.getUserContentList(req.getUserId(), req.getPage(), req.getPageSize());
            responseVo.setRetCode(RetCode.SUCCESS);
        }catch (ServiceException e){
            responseVo.setRetCode(e.getRetCode());
        }
        return responseVo;
    }
    ```
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Spring Boot中自定义拦截可以用来拦截请求并在请求前或请求后执行一些操作,比如记录日志、等。下面是一个简单的例子: 1. 创建一个拦截类,实现HandlerInterceptor接口,并实现其中的三个方法:preHandle、postHandle、afterCompletion。 ``` public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 在请求处理之前进行调用(Controller方法调用之前) return true; // 只有返回true才会继续向下执行,返回false取消当前请求 } @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. 创建一个配置类,注册拦截。 ``` @Configuration public class InterceptorConfig implements WebMvcConfigurer { @Autowired private MyInterceptor myInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { // 注册拦截 registry.addInterceptor(myInterceptor) .addPathPatterns("/api/**") // 拦截的路径 .excludePathPatterns("/api/login"); // 排除的路径 } } ``` 在上面的例子中,我们创建了一个MyInterceptor拦截类,并实现了其中的三个方法。然后,我们创建了一个InterceptorConfig配置类,并在其中注册了MyInterceptor拦截,并指定了拦截的路径和排除的路径。这样,所有以/api/开头的请求都会被MyInterceptor拦截拦截,除了/api/login路径的请求。 以上就是Spring Boot自定义拦截的简单示例。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值