Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple login-config for Java webapp

I have a Java web application that has a website for user interactions. To authenticate users I configured the application via web.xml to use FORM-based authentication. Users are forwarded to a login page and everything is fine so far.

Now we are developing a desktop client (in C#) for this web application which accesses the application via RESTful web services. I implemented these services in the same web app as the web site and of course the caller of the web service should be authenticated too. But now I'm facing the problem, that whenever I call a web service the server is returning the login page's HTML as response.

I think it would be cool to be able to use another login-config for my REST service servlet (which would probably use BASIC authentication then).

Google didn't bring up much, but I can't believe I'm the first one being in such situation. So I would like to hear your thoughts and solutions.

Any hint is appreciated.

like image 744
hage Avatar asked May 27 '11 09:05

hage


2 Answers

The only solution is have two apps for two clients having different login mechanisms. The application code should be seperated and move it common app to which these apps with forward the requests.

Else, use your custom authentication.

like image 118
Ramesh PVK Avatar answered Nov 12 '22 16:11

Ramesh PVK


I've solved this problem with a tomcat valve. The valve checks for the presence of an Authorization header, in which case, the header is used as credentials to authenticate the user, otherwise, the normal authentication method takes place.

Here is the code of the 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);
    }
}

You can use the valve by adding a <Valve> tag either in the server.xml file in your tomcat installation, or in the META-INF/context.xml file of your WebApp:

The project is on github: https://github.com/robbyn/mydsrealm

like image 33
Maurice Perry Avatar answered Nov 12 '22 18:11

Maurice Perry