RESTEasy with Undertow,访问 HttpServletRequest

Posted

技术标签:

【中文标题】RESTEasy with Undertow,访问 HttpServletRequest【英文标题】:RESTEasy with Undertow, accessing HttpServletRequest 【发布时间】:2016-03-19 12:52:43 【问题描述】:

我正在尝试将 RESTEasy 与 undertow 一起使用。首先我厌倦了UndertowJaxrsServersource,但发现它是直接使用PathHandler。所以我驱动了另一个继承自 PathHandler 的类,并更改了 UndertowJaxrsServer 以使用该类。

这是我从 PathHandler 驱动的新 Handler 中的 handleRequest 方法

@Override
public void handleRequest(HttpServerExchange exchange) throws Exception 
if (exchange.isInIoThread()) 
    exchange.dispatch(this);
    return;

boolean processed = exchange.getQueryParameters().get("INSPECTED") != null;
if (!processed) 
    exchange.addQueryParam(REQUEST_INSPECTED_PARAM, "T");
    String path = exchange.getRequestPath();
    if (!path.endsWith("/users/authenticate")) 
    String token = exchange.getRequestHeaders().getFirst("TOKEN");
    if (!AppUtil.isNullOrEmpty(token)) 
        try 
        User user = ServiceLocator.SECRUTIY_SERVICE.validateToken(token);
         exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY).getServletRequest()
         .setAttribute("USER",  user);

        super.handleRequest(exchange);
        return;
         catch (Exception e) 
        logger.warn("handleRequest(HttpServerExchange) - exception ignored", e);
        
    
    exchange.setResponseCode(HttpResponseCodes.SC_FORBIDDEN);
    exchange.endExchange();
    return;
    

super.handleRequest(exchange);

 

这是进行身份验证的资源

@Path("/users")
@Produces(MediaType.APPLICATION_JSON)
@Formatted
public class Users 
    @Context
    HttpServletRequest request;
    @Context
    HttpServletResponse response;

    @POST
    @Path("/authenticate")
    public String authenticate(@FormParam("username") String username, @FormParam("password") String password) 
    return "\"token\":\"" + ServiceLocator.SECRUTIY_SERVICE.authenticate(username, password) + "\"";
    

客户端应调用身份验证,然后获取用于下一次调用的令牌。

我的问题是

    我需要分析 Token 以获取登录用户,然后将其传递到 HttpRequest 中,以便资源可以轻松访问它。我正在通过此代码执行此操作

    exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY).getServletRequest() .setAttribute("USER", user);

但它会抛出 NPE,因为 exchange.getAttachement() 返回 null。

    我注意到 MyHandler 被调用了两次(在服务请求之前和之后)我只需要执行一次我的逻辑(分析令牌)。我在请求参数中设置了一个标志来这样做,但我不确定这是正确的方法。

【问题讨论】:

【参考方案1】:

嗯,这是一种解决方法,

public class MyTSA implements ThreadSetupAction 

private static final Logger logger = LoggerFactory.getLogger(MyTSA.class);

@Override
public Handle setup(HttpServerExchange exchange) 
if (exchange == null)
    return null;
    String token = exchange.getRequestHeaders().getFirst(TOKEN_HEADER_PARAM);
    if (!AppUtil.isNullOrEmpty(token)) 
    try 
        User user = ServiceLocator.SECRUTIY_SERVICE.validateToken(token);
        exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY).getServletRequest()
            .setAttribute("USER", user);

     catch (Exception e) 
        logger.warn("setup(HttpServerExchange) - exception ignored", e);
    

return null;

在此之前,在创建部署信息时,将此线程设置操作的新实例传递给部署信息。

DeploymentInfo di = ....

di.addThreadSetupAction(new MyTSA());

【讨论】:

以上是关于RESTEasy with Undertow,访问 HttpServletRequest的主要内容,如果未能解决你的问题,请参考以下文章

jakarta / javax 命名空间下的 Weld 和 Undertow

如何让 Wildfly 10 / Resteasy 向客户端指示序列化异常

Servlets/Undertow - 访问 HttpServletRequest 和 HttpServletResponse

Undertow 访问日志跳过时间 (%D)

在 UndertowJaxrsServer 中提供静态内容

随心所欲的失败