4

我想在 JSF/Primefaces 应用程序中实现一个简单的身份验证。我尝试了很多不同的东西,例如Dialog - Login Demo对对话框进行了简单的测试,但它没有登录用户还是?

我还查看了 Java 安全性,例如:

<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>

有了这个 /protected 下的所有内容都受到保护,但据我了解,我需要在服务器中定义一个领域以进行身份​​验证。我不想在服务器中指定它,而只是在数据库中进行简单的查找。

有没有一种方法来验证用户而不在应用程序服务器中定义一些东西?或者另一个简单的解决方案来验证和保护不同的页面?

4

2 回答 2

7

有没有一种方法来验证用户而不在应用程序服务器中定义一些东西?

这是一个漫长而充满荆棘故事。它经常成为对 Java EE 的主要批评之一。

故事的核心是传统的 Java EE 应用程序应该使用“未解决的依赖项”进行部署。这些依赖项必须在应用程序服务器上得到满足,通常由非开发人员来满足,通常使用某种 GUI 或控制台。

安全配置是那些未解决的依赖项之一。

如果安全配置是在应用服务器上完成的,根据定义,这总是不可移植的,例如,它必须以应用服务器特定的方式完成。它完全排除了使用应用程序域模型(例如 JPA 实体User)进行此身份验证。

一些服务器(例如 JBoss AS)允许从应用程序中配置其专有的安全机制,并且还允许从应用程序加载“自定义登录模块”(几乎每个服务器的术语都不同)。通过一些小技巧,这将允许使用应用程序域模型和应用程序本身用于身份验证的相同数据源。

最后,还有一种相对未知的可移植方式从应用程序中进行身份验证。这是通过JASPIC SPI(也称为JASPIJSR 196 )完成的。基本上,这个 JASPIC 似乎就是你要找的。

不幸的是,JASPIC 并不完美,尽管它是 Java EE 6 中的一项技术,而且我们几乎处于 Java EE 7 阶段,但目前在各种应用程序服务器中对 JASPIC 的支持仍然很粗略。最重要的是,即使 JASPIC 是标准化的,应用服务器供应商仍然以某种方式需要专有配置才能使其真正工作。

我写了一篇关于 JASPIC 的文章,更详细地解释了当前的问题:Implementing container authentication in Java EE with JASPIC

于 2012-12-29T22:01:52.130 回答
0

通过简单地使用 Web 过滤器,我找到了适合我的简单解决方案。我已经向 web.xml 添加了一个过滤器,例如

<!-- 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>

过滤器看起来像这样

@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);
    }
}

所以我只需要实现一个 Bean 来验证和设置会话 cookie。我将添加用户代理以获得额外的安全性,但它基本上可以工作。

我唯一的问题是我无法进行重定向,因为它没有使用上下文路径,而只是重定向到 /index.xhtml 而不是 /my_app_context/index.xhtml

于 2012-12-31T15:09:41.917 回答