Java webapp 的多个 login-config

2022-09-02 10:31:55

我有一个Java Web应用程序,它有一个用于用户交互的网站。为了对用户进行身份验证,我通过 Web.xml配置应用程序以使用基于 FORM 的身份验证。用户被转发到登录页面,到目前为止一切都很好。

现在我们正在为此Web应用程序开发一个桌面客户端(在C#中),该应用程序通过RESTful Web服务访问该应用程序。我在与网站相同的 Web 应用程序中实现了这些服务,当然 Web 服务的调用方也应该进行身份验证。但现在我面临的问题是,每当我调用Web服务时,服务器都会返回登录页面的HTML作为响应。

我认为能够为我的REST服务servlet使用另一个登录配置会很酷(当时可能会使用BASIC身份验证)。

谷歌没有提出太多,但我不敢相信我是第一个遇到这种情况的人。所以我想听听你的想法和解决方案。

任何提示都是值得赞赏的。


答案 1

唯一的解决方案是为具有不同登录机制的两个客户端提供两个应用。应用程序代码应分开,并将其移动到这些应用程序将请求转发到的公共应用程序。

否则,请使用自定义身份验证。


答案 2

我已经用雄猫阀门解决了这个问题。Valve 检查是否存在授权标头,在这种情况下,标头将用作凭据对用户进行身份验证,否则将发生正常的身份验证方法。

以下是阀门的代码:

package org.tastefuljava.tomcat;

import java.io.IOException;
import java.security.Principal;
import javax.servlet.ServletException;
import org.apache.catalina.Realm;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;

public class AutoBasicValve extends ValveBase {
    private static final String BASIC_PREFIX = "basic ";

    private String encoding = "UTF-8";

    public String getEncoding() {
        return encoding;
    }

    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }

    @Override
    public void invoke(Request request, Response response)
            throws IOException, ServletException {
        Principal principal = request.getUserPrincipal();
        Realm realm = getContainer().getRealm();
        if (principal != null) {
            if (containerLog.isDebugEnabled()) {
                containerLog.debug(
                        "Already authenticated as: " + principal.getName());
            }
        } else if (realm == null) {
            if (containerLog.isDebugEnabled()) {
                containerLog.debug("No realm configured");
            }
        } else {
            String auth = request.getHeader("authorization");
            if (auth != null) {
                if (auth.toLowerCase().startsWith(BASIC_PREFIX)) {
                    auth = auth.substring(BASIC_PREFIX.length());
                    byte[] bytes = Base64.decode(auth);
                    auth = new String(bytes, encoding);
                    int ix = auth.indexOf(':');
                    if (ix >= 0) {
                        String username = auth.substring(0, ix);
                        String password = auth.substring(ix+1);
                        principal = realm.authenticate(username, password);
                        if (principal == null) {
                            containerLog.warn(
                                    "Could not authenticate " + username);
                        } else {
                            containerLog.info(
                                    "Authenticated as " + principal.getName());
                            request.setAuthType("BASIC");
                            request.setUserPrincipal(principal);
                        }
                    }
                }
            }
        }
        getNext().invoke(request, response);
    }
}

您可以通过在 tomcat 安装的服务器.xml文件或 WebApp 的 META-INF/context.xml 文件中添加<Valve> 标记来使用该阀:

该项目在github上:https://github.com/robbyn/mydsrealm


推荐