jersey实现动态绑定

业务场景

对外提供接口服务时,需要基于token进行拦截。需要拦截指定的请求,根据token判断用户信息有效性。此文不提供token实现方法。

传统实现

传统作法是直接使用一个拦截器,然后拦截所有的请求,通过配置白名单的方式,如果不是白名单的请求则验证token。

还有一种则是在配置拦截器时,指定需要拦截的请求,则不需要配置白名单,也可以实现。

基于jersey的Dynamic binding动态绑定拦截

动态绑定就是一个以动态的方式分配资源方法的筛选器和拦截器。

第一步:定义一个过滤器

/**
 * 用户登录过滤器
 * @author xiaojun
 * @version 2018/12/17
 */
public class AuthorizationFilter implements ContainerRequestFilter {

    private TokenService tokenService;

    public AuthorizationFilter() {
        super();
        this.tokenService = TokenService.INSTANCE;
    }

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {

        String tokenStr = requestContext.getHeaderString("token");
        //token为空时,抛出未授权异常
        if (StringUtils.isBlank(tokenStr)) {
            throw new ForbiddenException(); //直接抛出异常,此处的异常也可以自定义
        }
        //验证token
        Token token = tokenService.getToken(tokenStr); //这一块根据实际情况验证token
        if (token == null) {
            throw  new ForbiddenException(); //直接抛出异常,此处的异常也可以自定义
        }
    }
}

第二步:定义注解

该注解用于方法或类上,如果类或方法有注解的话,则会被上述拦截器拦截

import javax.ws.rs.NameBinding;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 定义注解,判断是否登录,如果把这个注解增加到类或方法上面,说明该类或方法需要登录才可以调用
 * @author xiaojun
 * @version 2018/12/17
 */
@NameBinding
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface AuthAnnotation {
}

第三步:配置动态绑定

import javax.ws.rs.container.DynamicFeature;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.FeatureContext;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;

/**
 * 用户登录的一个动态绑定,只要方法上有注解,即会被拦截
 * @author xiaojun
 * @version 2018/12/17
 */
public class AuthorizationFilterFeature implements DynamicFeature {
    @Override
    public void configure(ResourceInfo resourceInfo, FeatureContext context) {

        List<Annotation> authzSpecs = new ArrayList<>();

        Annotation classAuthzSpec = resourceInfo.getResourceClass().getAnnotation(AuthAnnotation.class); //AuthAnnotation为上述定义的注解
        Annotation methodAuthzSpec = resourceInfo.getResourceMethod().getAnnotation(AuthAnnotation.class);
        if (classAuthzSpec != null) {
            authzSpecs.add(classAuthzSpec);
        }
        if (methodAuthzSpec != null) {
            authzSpecs.add(methodAuthzSpec);
        }

        if (!authzSpecs.isEmpty()) {
            context.register(AuthorizationFilter.class);
        }
    }
}

第四步:AuthorizationFilterFeature的注册

直接注册到ResourceConfig即可,类似如下代码:

final ResourceConfig rc = new ResourceConfig();
rc.register(AuthorizationFilterFeature.class);

第五步:简单使用

/**
 * 用户管理Api
 * @author: xiaojun
 * @version: 2018/12/11
 */
@Path("user")
@AuthAnnotation
public class UserApi {

    private Logger logger = Logger.getLogger(UserApi.class);
}

   转载规则


《jersey实现动态绑定》 孤独如梦 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
linux下如何解决jvm执行取得的时间和系统时间不一致的问题 linux下如何解决jvm执行取得的时间和系统时间不一致的问题
在查看日志的发现,打印出来的日志时间与当前linux的时间不一致,用new Date()打印出来的时间了发现是EST时间,而Linux机器的时间是CST时间(中国标准时间),所以是JVM与linux的时间不一致导致的。 解决方法有三种:
2019-06-06
下一篇 
jersey中@RolesAllowed的使用 jersey中@RolesAllowed的使用
在jersey中使用@RolesAllowed来控制指定的角色才可以访问,一般用于方法上面。 假定只有admin的用户才可以访问。 下面是使用步骤: 第一步:定义一个类MySecurityContext实现SecurityContextim
2019-06-06
  目录