在项目开发过程中,会有很多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");
}
}
以上就是实现方式,如果觉得还有用,就点个赞吧 ~