Jersey框架:使用注解实现用户认证

业务场景描述

微服务框架势必要面临用户鉴权问题,如在搭建系统应用时必须要考虑什么资源可以公开,什么资源只有系统用户才可以访问?
本文针对Jersey框架,就REST资源的用户鉴权提供可行的解决思路,以简洁方便的注解形式实现。

Jersey的过滤器(Filter)

当你想要修改请求或响应参数,如HTTP请求响应头,可以使用过滤器来完成任务。例如,希望添加一个响应头X-Powered-By 到每个生成的响应中,可以使用ResponseFilter来完成添加。(例子来自官方文档)

@Provider
@PreMatching
public class PoweredByResponseFilter implements ContainerResponseFilter{
	public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
			throws IOException {
		responseContext.getHeaders().add("X-Powered-By", "Jersey :-)");
	}
}

ResponseFilter必须继承于ContainerResponseFilter,而且必注册为Provider,通过@Provider注解定义的Filter。 ResponseFilter 会被执行,即使资源方法没有执行。Filter()方法有两个参数,ContainerRequest以及ContainerResponse,分别用来读取请求参数以及写入响应参数。

命名绑定@NameBinding

被@NameBinding注解修饰的注解是元注解,可以注解其它注解,其他注解具体实现后才可以分配给一个资源方法。

定义元注解@UserAuth

使用Java标准的注解定义方式,定义一个运行时的、作用于方法和类上的注解。

@NameBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})

public @interface UserAuth {

}

实现用户权限认证注解

使用接口ContainerRequestFilter实现@UserAuth注解的具体功能。
关键代码
(1)指定过滤器优先级
@Priority(Priorities.AUTHENTICATION)
(2)在Jersey框架中注册资源@Provider
(3)绑定元注解@UserAuth

@Priority(Priorities.AUTHENTICATION)
@Provider
@UserAuth
public class UserAuthFilter implements ContainerRequestFilter {

    public void filter(ContainerRequestContext req) throws IOException {
        String user = req.getHeaderString("user");
        String token = req.getHeaderString("pass");
        if (StringUtils.isBlank(user) || StringUtils.isBlank(token)) {
            Response resp = Response.status(Response.Status.FORBIDDEN)
                    .type(MediaType.APPLICATION_JSON)
                    .entity(new SimpleMsg("no permission."))
                    .build();
            req.abortWith(resp);
        }
        //模拟简单的用户认证逻辑,实际应用中具体实现
        if (!"admin".equals(user) || !"admin".equals(token)) {
            Response resp = Response.status(Response.Status.FORBIDDEN)
                    .type(MediaType.APPLICATION_JSON)
                    .entity(new SimpleMsg("no permission."))
                    .build();
            req.abortWith(resp);
        }
    }
}

为资源开启用户认证注解

新建一个REST资源,在方法上使用@UserAuth注解。

@Path("/computer")
public class ComputerRes {
    @UserAuth
    @Path("")
    @GET
    public Response get() {
        return Response.ok("computers").build();
    }
}

测试

在浏览器中直接访问`http://localhost:8081/computer,返回403错误,提示无访问权限。
Jersey框架:使用注解实现用户认证_第1张图片

使用Postman工具提交带请求头user和pass的GET请求,返回正确结果。
Jersey框架:使用注解实现用户认证_第2张图片

案例Github地址:https://github.com/majxbear/jetty-rest

你可能感兴趣的:(Jersey,Jersey系列:实践全干货)