简体   繁体   中英

Form based authentication in JSF

I would like to implement a simple authentication in an JSF/Primefaces application. I have tried lots of different things, eg Dialog - Login Demo makes a simple test on a dialog, but it does not login a user or?

I also have taken a look at Java Security, like:

<security-constraint>
    <web-resource-collection>
        <web-resource-name>Protected Area</web-resource-name>
        <url-pattern>/protected/*</url-pattern>
        <http-method>PUT</http-method>
        <http-method>DELETE</http-method>
        <http-method>GET</http-method>
        <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
        <role-name>REGISTERED_USER</role-name>
    </auth-constraint>
</security-constraint>

With this everything under /protected is protected, but as far as i understand i need to define a realm in the server for authentication. I do not want to specify this in the server but just have a simple lookup in the database for it.

Is there a way to authenticate a user without defining something in the application server? Or anonther simple solution to authenticate and protect different pages?

Is there a way to authenticate a user without defining something in the application server?

This is a long and very thorny story. It often comes up as one the main points of criticism against Java EE.

The core of the story is that traditionally Java EE applications are supposed to be deployed with "unresolved dependencies". Those dependencies have to be satisfied at the application server, typically by someone who is not a developer, often by using some kind of GUI or console.

Security configuration is one of those unresolved dependencies.

If the security configuration is done at the application server, this is by definition always not portable, eg it has to be done in an application server specific way. It completely rules out using application domain models (eg a JPA entity User ) for this authentication.

Some servers (eg JBoss AS) allow configuring their proprietary security mechanisms from within the application, and additionally allow for 'custom login modules' (the term is different for pretty much every server) to be loaded from the application as well. With some small hacks, this will allow the usage of application domain models and the same data source that the application itself uses for authentication.

Finally, there's a relatively unknown portable way to do authentication from within an application. This is done via the JASPIC SPI, also known as JASPI or JSR 196 . Basically, this JASPIC seems to be what you are looking for.

Unfortunately, JASPIC is not perfect and even though it's a technology from Java EE 6 and we're almost at Java EE 7, at the moment support for JASPIC in various application servers is still sketchy. On top of that, even though JASPIC is standardized, application server vendors still somehow require proprietary configuration to actually make it work.

I wrote an article about JASPIC that explains the current problems in more detail: Implementing container authentication in Java EE with JASPIC

I have found a for me suitable and easy solution by simply using Web Filters. I have added a filter to web.xml like

<!-- Authentication Filter -->
<filter>
    <filter-name>AuthenticationFilter</filter-name>
    <filter-class>org.example.filters.AuthenticationFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>AuthenticationFilter</filter-name>
    <url-pattern>/protected/*</url-pattern>
</filter-mapping>

The filter looks something like this

@WebFilter(filterName="AuthenticationFilter")
public class AuthenticationFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        Cookie[] cookies = ((HttpServletRequest)request).getCookies();

        // Try to find a valid session cookie
        if (cookies != null) {
            String sessionId = null;
            for (Cookie cookie : cookies) {
                if ("sessionId".equals(cookie.getName())) {
                        sessionId = cookie.getValue();
                }
            }

            // Check if we have a valid session
            UserSession session = Backend.getInstance().getSessionGateway().getBySessionId(sessionId);

            if (session != null) {
                chain.doFilter(request, response);
                return;
            } else if (sessionId != null) {
                // Remove the cookie
                Cookie cookie = new Cookie("sessionId", null);
                cookie.setMaxAge(-1);
                ((HttpServletResponse)response).addCookie(cookie);
            }
        }


//      Problem due to relative path!!
//      ((HttpServletResponse)response).sendRedirect("../login.xhtml");
        RequestDispatcher rd = request.getRequestDispatcher("/login.xhtml");
        rd.forward(request, response);
    }
}

So i had just to implement a Bean that authenticates and sets the session cookie. I will add the user agent to have additional security but it basically works.

The only problem i have that i can not do a redirect, cause it is not using context path but just redirects to /index.xhtml instead of /my_app_context/index.xhtml

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM