【问题标题】:Form based authentication in JSFJSF 中基于表单的身份验证
【发布时间】:2012-12-14 16:26:41
【问题描述】:

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

我也看过 Java Security,比如:

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

有没有一种方法可以在不定义应用程序服务器的情况下对用户进行身份验证?还是另一种简单的解决方案来验证和保护不同的页面?

【问题讨论】:

    标签: java security jsf authentication jaspic


    【解决方案1】:

    有没有一种方法可以在不定义应用程序服务器的情况下对用户进行身份验证?

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

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

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

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

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

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

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

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

    【讨论】:

    • 听起来有点奇怪。如果我在应用程序服务器中进行了身份验证,则它不再是可移植的。如果我使用另一个应用程序服务器,我必须迁移整个用户群或重新实现它。我会看看 JASPIC 可能对我有帮助,谢谢。
    • @MikePetersen 确实,但这是传统方法的想法。它以应用程序服务器为中心与以应用程序为中心。这个想法是您在单个应用服务器上运行多个应用程序,并且它们都使用相同的身份验证。因此它是在应用服务器上设置的。当然,如果您所做的只是运行具有自己身份验证的单个应用程序,那是没有意义的。所以,这取决于情况。一种方法并不比另一种更好,只是有不同的用例。
    • Xou 是对的,如果您有更多使用相同用户群的应用程序,这很有意义。我认为具有不同身份验证的不同应用程序在 Web 应用程序中更为常见。
    【解决方案2】:

    我通过简单地使用 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

    【讨论】:

    • 您为什么要通过自定义 cookie 重新发明 HttpSession
    猜你喜欢
    • 2014-12-13
    • 1970-01-01
    • 2012-06-06
    • 1970-01-01
    • 1970-01-01
    • 2012-07-12
    • 2016-11-13
    • 1970-01-01
    相关资源
    最近更新 更多