Java webapp的多个登录配置

Java webapp的多个登录配置,java,web-applications,login,Java,Web Applications,Login,我有一个Java web应用程序,它有一个用于用户交互的网站。为了对用户进行身份验证,我通过web.xml将应用程序配置为使用基于表单的身份验证。用户被转发到登录页面,目前一切正常 现在我们正在为这个web应用程序开发一个桌面客户端(C#),它通过RESTful web服务访问应用程序。我在与web站点相同的web应用程序中实现了这些服务,当然web服务的调用方也应该经过身份验证。但现在我面临的问题是,每当我调用web服务时,服务器都会返回登录页面的HTML作为响应 我认为能够为我的REST服务

我有一个Java web应用程序,它有一个用于用户交互的网站。为了对用户进行身份验证,我通过web.xml将应用程序配置为使用基于表单的身份验证。用户被转发到登录页面,目前一切正常

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

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

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


任何提示都非常感谢。

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


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

我也遇到了同样的问题,无法找到解决方案。 您可以定义多种身份验证方法: 但是:
不幸的是,FORM和BASIC不能同时存在于auth方法值列表中。

不幸的是,登录配置没有像筛选器和servlet那样映射,因此webapp只有一个全局配置。这意味着您需要2个webapps,或者如果在JBoss上,您可以使用WebAuthentication类通知容器您的应用程序的编程登录。但是,如果您使用的是嵌入式jetty或其他web服务器,则绝对无法使用web.xml支持BASIC和FORM off。您必须编写一个自定义身份验证服务

然而,您可以转换为ApacheShiro,它将以一种非常好的编写和简单的设计解决这些问题。这些步骤将允许REST客户端在没有会话cookie的情况下在每个页面上使用基本身份验证,或者登录/REST/login并接收会话。然后,浏览器客户端可以使用FORM auth

1) protect /login with "authc", set shiro.loginUrl to /login and host an HTML form at that location
2) protect /rest/login with "anon" and write a URL handler for POST with this code
    UsernamePasswordToken token = new UsernamePasswordToken(userName, password);
    token.setRememberMe(rememberMe);
    SecurityUtils.getSubject().login(token);
3) protect /rest/logout with "logout"
4) protect /rest/** with "noSessionCreation, authcBasic, rest"

我用tomcat阀门解决了这个问题。该阀检查是否存在授权标头,在这种情况下,标头被用作认证用户的凭据,否则,将使用正常的认证方法

以下是阀门的代码:

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安装的server.xml文件或WebApp的META-INF/context.xml文件中添加标记来使用阀门:

该项目位于github上:

Me与此相结合,以允许SSL客户端证书和表单以及基本的回退身份验证


向您致意

谢谢。我已经认为这是不可能的。所以我认为最好的选择是为Web服务实现自定义身份验证…7年后,这仍然是真的吗?看起来很酷。如果它仍然是2011年,我可以使用它:)但谢谢你的工作!我希望它能帮助别人。你现在知道玻璃鱼是否也有类似的情况吗?