문제

How I can authenticate a user from JSF action (or in servlet doGet/doPost methods)? I mean something like:

Authenticator auth = ...;
if (!auth.authenticate("user","password"))
{
    FacesContext.getInstance().addMessage("Incorrect username or password", null);
}

Restrictions:

  • This method must be compatible with container managed security. (i.e. `HttpServletRequest.getRemoteUser()` must return authenticated user)
  • This method must work everywhere (i.e. on each application server).

Not using j_security_check or another J2EE authentication type (BASIC, DIGEST, etc...)

It is possible?
Or how to create captcha in this way?
Validate that login and password is not empty?
On single page and without JavaScript, of course...

Similar questions... but without answer on this question:

JSF authentication and authorization
Performing user authentication in Java EE / JSF using j_security_check

Edit 1:
I mean serlvet API at least 2.3. Yes, I read about login in Servlet API 3.0, but it is supported only by new versions of application servers.

I think that here can be some solution that implements this authentication for each application server. Sometimes via some hacks, sometimes via special classes designed for this purpose. Like this:

private Class<?> tryClass(String name)
{
    try
    {
        return Class.forName(name);
    }
    catch (ClassNotFoundException e)
    {
        return null;
    }
}

public boolean authenticate(String username, String password) throws AuthenticationException
{
    try
    {

        ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
        Object request = context.getRequest();
        Object response = context.getResponse();

        Class<?> authClass = tryClass("com.sun.appserv.security.ProgrammaticLogin");
        if (authClass != null)
        {
            return (Boolean)authClass.getMethod("login").invoke(
                authClass.newInstance(), "user", "password", request, response);
        }

        authClass = tryClass("org.jboss.web.tomcat.security.login.WebAuthentication");
        if (authClass != null)
        {
            return (Boolean)authClass.getMethod("login").invoke(
                authClass.newInstance(), "user", "password");
        }

        // ... other hacks ...application servers 

    }
    catch (Exception e)
    {
        throw new AuthenticationException("an error occured during user authentication", e);
    }

    return false;
}
도움이 되었습니까?

해결책

Ah, it's J2EE 1.3 Java EE 5. Too bad, you're out of luck whenever you want to go ahead with container managed security. You have to grab containerspecific implementations from under the covers. By the way, "container managed security without j_security_check or BASIC/DIGEST" is self-contradicting. I would personally just forget about it all and homegrow security or grab a 3rd party implementation which is more configureable, like Spring Security.

다른 팁

Programmatic login is pretty darn tricky and seems to vary by application server. I believe that going with the j_security_check is the most successful, and will allow your application to work across various application servers.

The hard part is getting the application server to accept the authentication. On Tomcat, I've been able to do myLoginModule.login() and have the login module succeed, but the user wasn't authenticated with the container. JBoss has some code to get programmatic authentication to work between JBoss and Tomcat (since Tomcat lives within JBoss). Looking into this for Glassfish, I got the impression that programmatic login is very difficult and should be left to the pro's.

Glassfish documentation (http://docs.sun.com/app/docs/doc/820-4496/beacm?a=view) says:

Programmatic login is specific to the Enterprise Server and not portable to other application servers.

Edit

The j_security_check method takes a little getting used to, but once you learn to work around it, can be quite successful. Basically you can have a welcome page that redirects the user in to your application; if the user has not logged in yet, they'll get sent to your login page. Your login page can be your site's home page. Once on the home page, the user can navigate to other "unsecure" pages of your site. You can include login forms on those pages as well if you like. You're not stuck with a single login page.

Edit 2

I've been using AJAX (via Richfaces) to check the user's username/password and showing an error message if needed. If the credentials are correct, the form pointing to j_security_check is submitted to do the actual authentication.

Edit 3

The programmatic login method suggested by BalusC on the second linked question (http://stackoverflow.com/questions/2206911/best-way-for-user-authentication-on-javaee-6-using-jsf-2-0) doing request.login(...) looks great. I'll be trying it out soon ;o) Servlet 3 is supported by Glassfish 3 but not much else yet (will be part of Tomcat 7, probably JBoss 6).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top