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错误,提示无访问权限。
使用Postman工具提交带请求头user和pass的GET请求,返回正确结果。
案例Github地址:https://github.com/majxbear/jetty-rest