SpringBoot如何优雅的处理免登录接口

在项目开发过程中,会有很多API接口不需要登录就能直接访问,比如公开数据查询之类的 ~

常规处理方法基本是 使用拦截器过滤器,拦截需要认证的请求路径。在拦截器中判断session或token信息,如果存在则放行,否则跳转到登录页。过滤器原理与拦截器类似,可以在过滤器中判断请求的session或token信息,麻烦的地方就是:每次开发新的免登录接口的时候,都需要去配置一下路径

今天介绍一个更优雅的方法:自定义注解的方式

基本思路是:自定义一个注解,在不需要校验登录的Controller方法或类上使用该注解。通过AOP或拦截器在方法执行前判断免登录状态

自定义注解这里命名为NoToken

java 复制代码
import java.lang.annotation.*;

/**
 * 不校验token注解
 */
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface NoToken {
    String name() default "";
}

这里采用拦截器搭配使用,拦截器代码如下

java 复制代码
@Slf4j
public class SessionInterceptor implements HandlerInterceptor {

    //在请求处理之前进行调用Controller方法调用之前
    @Override
    @Reference
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            NoToken classAnno = handlerMethod.getMethod().getDeclaringClass().getAnnotation(NoToken.class);
            //获取出Controller上的NoToken注解
            if (classAnno != null) {
                // 如果注解不为null, 说明不需要拦截, 直接放过
                return true;
            } else {
                Method method = handlerMethod.getMethod();
                handlerMethod.getMethodAnnotation(NoToken.class);
                //获取出方法上的NoToken注解
                NoToken access = method.getAnnotation(NoToken.class);
                if (access != null) {
                    // 如果注解不为null, 说明不需要拦截, 直接放过
                    return true;
                }
            }
        }

        RedisService redis = (RedisService) SpringContextUtils.getBean("redisService");
        String token = request.getHeader("token");


        boolean ok = false;
        log.info("开始检验token!");
        if (!StringUtils.isEmpty(token)) {
            if (redis.exists(token)) {
                redis.expire(token, ConstantsUtil.APP_TOKEN_EXPIRE);
                log.info("token有效!");
                ok = true;
            }
        }


        if (!ok) {
            Map<String, Object> result = new HashMap<>();
            result.put("returncode","-1");
            result.put("returnmsg", "登录已过期,请重新登录");
            writeJSON(response, result);
            return ok;
        }
        return ok;

    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) throws Exception {

    }
    public void writeJSON(HttpServletResponse response, Object o)
            throws IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        String JsonString = JSON.toJSONString(o);
        out.write(JsonString);
    }
}

大家看到在NoToken注解和拦截器上,做了两种处理 也就是类注解方法注解

如果注解放到方法上,该方法调用的时候就是免登录的。如果注解放到@Controller类上,那么该类下的所有请求接口,都是免登录的(是不是很方便 ~)

java 复制代码
/**
 * 类上加NoToken注解,该类下所有方法都免登录
 */
@NoToken
@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {


    /**
     * 方法上单独加注解,只对该方法免登录
     */
    @NoToken
    @RequestMapping("testMethod")
    public void testMethod() {
        System.out.println("1111111111111");
    }


}

以上就是实现方式,如果觉得还有用,就点个赞吧 ~

相关推荐
李慕婉学姐4 小时前
【开题答辩过程】以《基于JAVA的校园即时配送系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·开发语言·数据库
奋进的芋圆6 小时前
Java 延时任务实现方案详解(适用于 Spring Boot 3)
java·spring boot·redis·rabbitmq
sxlishaobin6 小时前
设计模式之桥接模式
java·设计模式·桥接模式
model20056 小时前
alibaba linux3 系统盘网站迁移数据盘
java·服务器·前端
荒诞硬汉6 小时前
JavaBean相关补充
java·开发语言
提笔忘字的帝国7 小时前
【教程】macOS 如何完全卸载 Java 开发环境
java·开发语言·macos
2501_941882487 小时前
从灰度发布到流量切分的互联网工程语法控制与多语言实现实践思路随笔分享
java·开发语言
華勳全栈7 小时前
两天开发完成智能体平台
java·spring·go
alonewolf_997 小时前
Spring MVC重点功能底层源码深度解析
java·spring·mvc
沛沛老爹7 小时前
Java泛型擦除:原理、实践与应对策略
java·开发语言·人工智能·企业开发·发展趋势·技术原理