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");
    }


}

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

相关推荐
逝水如流年轻往返染尘3 小时前
JAVA中的抽象类
java·开发语言
hx862274 小时前
Java MySQL 连接
java·mysql·adb
lpfasd1234 小时前
Kubernetes (K8s) 底层早已不再直接使用 Docker 引擎了
java·docker·kubernetes
aq55356004 小时前
SpringBoot有几种获取Request对象的方法
java·spring boot·后端
steel80884 小时前
Spring Boot 整合 log4j2 日志配置教程
spring boot·单元测试·log4j
lierenvip5 小时前
Spring Boot中Tomcat配置
spring boot·tomcat·firefox
Detachym5 小时前
InsightFlow 服务配置优化与部署实践
java·spring boot·tomcat·maven·状态模式·jar
rainchestnut5 小时前
Spring AI 初步集成(1)-初始化
spring boot
y = xⁿ5 小时前
【LeetCodehot100】T23:合并k个升序链表
java·数据结构·链表
流水武qin5 小时前
SpringAI多模态的基本使用
java·spring boot·spring·ai