gpt4 book ai didi

java - 在 Apache CXF 拦截器中编写消息内容和响应代码

转载 作者:搜寻专家 更新时间:2023-11-01 02:25:22 26 4
gpt4 key购买 nike

我试图通过使其中一种方法需要 HTTP 基本身份验证来确保我的 Web 服务安全。为此,我实现了一个名为 LoginInterceptor 的自定义拦截器,它检查请求的 URL,如果它对应于一个名为 open 的方法,它会检查消息 header 用于用户名和密码。

如果头部没有认证字段,响应码设置为HTTP_UNAUTHORIZED,如果用户名或密码不正确,响应码设置为HTTP_FORBIDDEN。这是代码:

public LoginInterceptor() {
super(Phase.RECEIVE);
addAfter(RequestInterceptor.class.getName()); //another custom interceptor, for some simple redirections.
}

public void handleMessage(Message message) throws Fault {
String requestURI = message.get(Message.REQUEST_URI).toString();
String methodKeyword = requestURI.substring("localhost".length()+1).split("/")[0];

if(methodKeyword.equals("open")) {
AuthorizationPolicy policy = message.get(AuthorizationPolicy.class);
if(policy == null) {
sendErrorResponse(message, HttpURLConnection.HTTP_UNAUTHORIZED);
return;
}

//userPasswords is a hashmap of usernames and passwords.
String realPassword = userPasswords.get(policy.getUserName());
if (realPassword == null || !realPassword.equals(policy.getPassword())) {
sendErrorResponse(message, HttpURLConnection.HTTP_FORBIDDEN);
}
}
}

//This is where the response code is set, and this is where I'd like to write the response message.
private void sendErrorResponse(Message message, int responseCode) {
Message outMessage = getOutMessage(message);
outMessage.put(Message.RESPONSE_CODE, responseCode);

// Set the response headers
Map responseHeaders = (Map) message.get(Message.PROTOCOL_HEADERS);

if (responseHeaders != null) {
responseHeaders.put("Content-Type", Arrays.asList("text/html"));
responseHeaders.put("Content-Length", Arrays.asList(String.valueOf("0")));
}

message.getInterceptorChain().abort();

try {
getConduit(message).prepare(outMessage);
close(outMessage);
} catch (IOException e) {
e.printStackTrace();
}
}

private Message getOutMessage(Message inMessage) {
Exchange exchange = inMessage.getExchange();
Message outMessage = exchange.getOutMessage();

if (outMessage == null) {
Endpoint endpoint = exchange.get(Endpoint.class);
outMessage = endpoint.getBinding().createMessage();
exchange.setOutMessage(outMessage);
}

outMessage.putAll(inMessage);

return outMessage;

}

//Not actually sure what this does. Copied from a tutorial online. Any explanation is welcome
private Conduit getConduit(Message inMessage) throws IOException {
Exchange exchange = inMessage.getExchange();
Conduit conduit = exchange.getDestination().getBackChannel(inMessage);
exchange.setConduit(conduit);
return conduit;
}

private void close(Message outMessage) throws IOException {
OutputStream os = outMessage.getContent(OutputStream.class);
os.flush();
os.close();
}

这很好用,但是,我还想在响应中返回一条消息,例如“用户名或密码不正确”。我试过,从 sendErrorResponse 方法中,做:

outMessage.setContent(String.class, "不正确的用户名或密码")我将内容长度设置为 "incorrect username or password".length()。这不起作用,我猜是因为 Apache CXF 消息使用 InputStreamOutputStream

所以我尝试了:

OutputStream os = outMessage.getContent(OutputStream.class);
try {
os.write("incorrect username or password".getBytes() );
outMessage.setContent(OutputStream.class, os);
} catch (IOException e) {
e.printStackTrace();
}

这也行不通。使用调试器单步执行时,我注意到 osnull 使用 Postman 进行测试时,我得到:

Could not get any response This seems to be like an error connecting to http://localhost:9090/launcher/open. The response status was 0. Check out the W3C XMLHttpRequest Level 2 spec for more details about when this happens.

在 Chrome 中按 ctrl+shif+c(打开开发工具),然后检查网络选项卡,我看到:

"ERR_CONTENT_LENGTH_MISMATCH"

我试过使用 XMLStreamWriter,但这并没有什么好处。

问题:

  • 我可以返回正确的响应代码(401 Unauthorized 和 403 forbidden),但如何在响应正文中返回消息?

  • 我是否需要专门扩展特定的 OutInterceptor(例如 JASRXOutInterceptor)才能修改消息内容?

  • 我之前尝试过使用 JAASInterceptor,但没能成功。有人可以告诉我如何以这种方式实现它,如果那样更容易的话?

  • 我也可以像这样抛出一个错误:throw new Fault("incorrect username or password", Logger.getGlobal());,但是 HTTP 响应代码将是500. 我希望返回正确的 401 或 403 响应。

注意:

现在我仍在使用 HTTP 作为传输层。解决此问题后,我将更改为 HTTPS。

最佳答案

基本上,我想做的是用 401(未授权)或 403(禁止)而不是 500(服务器错误)的 HTTP 响应代码返回错误。事实证明,Apache CXF 提供了一种简单的方法,使用 Fault.setStatusCode(int) 方法,正如我从 Stack Overflow 上的这个问题中发现的那样:how to throw a 403 error in Apache CXF - Java

这就是我的 handleMessage 方法现在的样子:

public void handleMessage(Message message) throws Fault {
String requestURI = message.get(Message.REQUEST_URI).toString();
String methodKeyword = requestURI.substring("localhost".length()+1).split("/")[0];

if(methodKeyword.equals("open")) {
AuthorizationPolicy policy = message.get(AuthorizationPolicy.class);

if(policy == null) {
Fault fault = new Fault("incorrect username or password", Logger.getGlobal());
fault.setStatusCode(401);
throw fault;
}

String realPassword = userPasswords.get(policy.getUserName());
if (realPassword == null || !realPassword.equals(policy.getPassword())) {
Fault fault = new Fault("incorrect username or password", Logger.getGlobal());
fault.setStatusCode(403);
throw fault;
}
}
}

我删除了其他方法,它们是不必要的。

关于java - 在 Apache CXF 拦截器中编写消息内容和响应代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24992452/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com