Ant*_*s42 5 java jax-rs httprequest cdi
我有这样的网络服务:
@Path("/projects")
public class Projects {
[...]
@Inject
CurrentRequest current;
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("{id}")
public Response getProject(@PathParam("id") String id) {
if (current.isUserAuthenticated()) {
[...do something...]
} else {
[...produce an error...]
}
}
}
Run Code Online (Sandbox Code Playgroud)
还有一个带有auth checker方法的CDI bean,如下所示:
@RequestScoped
public class CurrentRequest {
public boolean isUserAuthenticated() {
[...do some header checking...]
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,我不能为我的生活从内部抓住HTTP标头CurrentRequest
.我试过注射HttpServletRequest
,但它没有初始化.我试过用@Context
同样的东西.显然FacesContext.getCurrentInstance()
不起作用,因为没有FacesContext.
我看到这个问题基本上是在问同样的问题,但是没有得到太多的关注.
我目前的方法是使用@Context HttpServletRequest request
内部Projects
并将其作为参数传递给current.isUserAuthenticated(request)
.但那感觉很糟糕.CDI bean不应该知道它自己的请求吗?
我错过了什么?
您不需要HttpServletRequest
在JAX-RS端点中从请求中获取HTTP标头.相反,你可以注入HttpHeaders
:
@Context
HttpHeaders httpHeaders;
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用HttpHeaders
API来获取标头值:
HttpHeaders#getHeaderString(String)
HttpHeaders#getRequestHeaders()
HttpHeaders#getHeaderString(String)
如果需要标准HTTP标头的值,请考虑使用API中提供HttpHeaders
的常量:
// Get the value of the Authorization header
String authorizationHeader = httpHeaders.getHeaderString(HttpHeaders.AUTHORIZATION);
Run Code Online (Sandbox Code Playgroud)
由于您正在执行身份验证和/或授权,因此我建议您使用过滤器,这样您就可以保持REST端点的精简并专注于业务逻辑.
要将过滤器绑定到REST端点,JAX-RS提供元注释@NameBinding
,可以使用如下:
@NameBinding
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Secured { }
Run Code Online (Sandbox Code Playgroud)
该@Secured
注释将被用来装饰一个过滤器类,它实现ContainerRequestFilter
,让您处理请求.
它ContainerRequestContext
可以帮助您从HTTP请求中提取信息(有关更多详细信息,请查看ContainerRequestContext
API):
@Secured
@Provider
@Priority(Priorities.AUTHENTICATION)
public class SecurityFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
// Use the ContainerRequestContext to extract information from the HTTP request
// Information such as the URI, headers and HTTP entity are available
}
}
Run Code Online (Sandbox Code Playgroud)
ContainerRequestFilter#filter()
如果用户未经过身份验证/授权,则该方法是中止请求的好地方.为此,您可以使用ContainerRequestContext#abortWith()
或抛出异常.
该@Provider
注释标记的扩展接口期间提供扫描阶段,应该是由JAX-RS运行时发现的实现.
要将过滤器绑定到端点方法或类,请使用@Secured
上面创建的注释对其进行 注释.对于注释的方法和/或类,将执行过滤器.
@Path("/")
public class MyEndpoint {
@GET
@Path("{id}")
@Produces("application/json")
public Response myUnsecuredMethod(@PathParam("id") Long id) {
// This method is not annotated with @Secured
// The security filter won't be executed before invoking this method
...
}
@DELETE
@Secured
@Path("{id}")
@Produces("application/json")
public Response mySecuredMethod(@PathParam("id") Long id) {
// This method is annotated with @Secured
// The security filter will be executed before invoking this method
...
}
}
Run Code Online (Sandbox Code Playgroud)
在上面的示例中,安全过滤器将仅执行,mySecuredMethod(Long)
因为它带有注释@Secured
.
您可以根据需要为REST端点提供尽可能多的过滤器.要确保过滤器的执行顺序,请使用@Priority
.
强烈建议使用Priorities
类中定义的值之一(将使用以下顺序):
如果您的过滤器未注释@Priority
,则将以USER
优先级执行过滤器.
你可能会发现这个答案很有用.
归档时间: |
|
查看次数: |
2438 次 |
最近记录: |