在后台接口开发中会有一类接口是需要做登录校验的,类似于生成订单,查看自己的订单列表等接口,都需要先判断用户是否登录.虽然可以在接口中进行判断,但是会让代码冗余,所以决定用自定义拦截器+自定义注解来完成这个功能
自定义拦截器可以实现HandlerInterceptor接口或者继承HandlerInterceptorAdapter类,HandlerInterceptorAdapter适配器是对HandlerInterceptor接口做了默认实现, 这种适配器模式, 是为了方便开发者只去想要复写方法, 其他方法采取默认措施.
AuthorizationInterceptor:
@Component
public class AuthorizationInterceptor extends HandlerInterceptorAdapter {
/** 日志实例 */
private static final Logger logger = Logger.getLogger(AuthorizationInterceptor.class);
@Resource
private TokenManager tokenManager;
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 如果不是映射到方法直接通过
if (!(handler instanceof HandlerMethod)) {
logger.info("#################如果不是映射到方法直接通过#################");
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
// 无需验证直接返回
if (null == method.getAnnotation(Authorization.class)) {
logger.info("#################无需验证直接返回#################");
return true;
}
// 从header中得到token
String token = null==request.getHeader("token")?"":request.getHeader("token").trim();
logger.info("#################从header中得到token["+token+"]#################");
if ("null".equals(token) || StringUtils.isEmpty(token)) {
response.setStatus(HttpServletResponse.SC_OK);
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=utf-8");
response.getWriter().write(ENUM_RESTFUL_COMMON_CODE.NOT_AUTHORIZATION.toJsonString());
return false;
}
// 获取Token信息
TokenModel model = new TokenModel();
model.setCode("common.restful.token");
model.setToken(token);
model = tokenManager.getToken(model);
logger.info("#################从TokenModel中得到TokenModel["+model+"]#################");
if (model == null) {
response.setStatus(HttpServletResponse.SC_OK);
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=utf-8");
response.getWriter().write(ENUM_RESTFUL_COMMON_CODE.NOT_AUTHORIZATION.toJsonString());
return false;
}
Authorization authorization = method.getAnnotation(Authorization.class);
String authorize = null==authorization.authorize()?"":authorization.authorize().trim();
logger.info("#################获取注解自定义字段authorize的值为["+authorize+"]#################");
Object authorizeStrObj = model.getProperty(RESTFUL_COMMON_KEY.AUTHORIZATION_AUTHORIZE);
String authorizeStr = String.valueOf(null==authorizeStrObj?"":authorizeStrObj).trim();
logger.info("#################获取缓存中字段authorizeStr的值为["+authorizeStr+"]#################");
if(null==authorizeStr || "".equals(authorizeStr) || null==authorize || "".equals(authorize)){//没有指定权限 老的流程
// 用户认证失败返回验证失败401
Object userObj = model.getProperty(RESTFUL_COMMON_KEY.AUTHORIZATION_AUTHID);
logger.info("#################从TokenModel中得到userObj["+userObj+"]#################");
if (null == userObj) {
response.setStatus(HttpServletResponse.SC_OK);
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=utf-8");
response.getWriter().write(ENUM_RESTFUL_COMMON_CODE.NOT_AUTHORIZATION.toJsonString());
return false;
}
}else{
boolean isToken = TokenCheckUtil.checkAnnotationAuthorize(authorize, authorizeStr);
logger.info("#################验证是否存在这个权限为["+isToken+"]#################");
if(!isToken){
response.setStatus(HttpServletResponse.SC_OK);
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=utf-8");
response.getWriter().write(ENUM_RESTFUL_COMMON_CODE.NOT_AUTHORIZATION.toJsonString());
return false;
}else{
Object authorizeObj = model.getProperty(RESTFUL_COMMON_KEY.AUTHORIZATION_AUTHORIZEID);
logger.info("#################从TokenModel中得到authorizeObj["+authorizeObj+"]#################");
if (null == authorizeObj) {
response.setStatus(HttpServletResponse.SC_OK);
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=utf-8");
response.getWriter().write(ENUM_RESTFUL_COMMON_CODE.NOT_AUTHORIZATION.toJsonString());
return false;
}
}
}
request.setAttribute("tokenModel", model);
return true;
}
}
自定义注解:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Authorization {
/***
* 权限字符串 使用逗号隔开 如 nologin,bpmquery
* @return
*/
String authorize() default "";
}
在启动类中:
@Configuration
@ServletComponentScan
@ImportResource(locations = { "classpath:/applicationContext.xml" })
@SpringBootApplication
public class HrHrpRestfulNewApplication extends WebMvcConfigurationSupport {
@Autowired
private SpringContext springContext;
@Autowired
private AuthorizationInterceptor authorizationInterceptor;
public static void main(String[] args) {
SpringApplication.run(HrHrpRestfulNewApplication.class, args);
}
@Override
protected void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authorizationInterceptor);
super.addInterceptors(registry);
}
}
最后可以将注解加到相应的接口上。