Java JSF中基于表单的身份验证
我想在JSF/Primefaces应用程序中实现一个简单的身份验证。我尝试过很多不同的事情,例如,在对话框上做一个简单的测试,但它不登录用户或 我还研究了Java安全性,如:Java JSF中基于表单的身份验证,java,security,jsf,authentication,jaspic,Java,Security,Jsf,Authentication,Jaspic,我想在JSF/Primefaces应用程序中实现一个简单的身份验证。我尝试过很多不同的事情,例如,在对话框上做一个简单的测试,但它不登录用户或 我还研究了Java安全性,如: <security-constraint> <web-resource-collection> <web-resource-name>Protected Area</web-resource-name> <url-pattern&
<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保护的内容都得到了保护,但据我所知,我需要在服务器中定义一个域来进行身份验证。我不想在服务器中指定它,只想在数据库中对它进行简单的查找
有没有一种方法可以在不在应用服务器中定义内容的情况下对用户进行身份验证?还是另一个简单的解决方案来验证和保护不同的页面
有没有一种方法可以在不在应用服务器中定义内容的情况下对用户进行身份验证
这是一个漫长而棘手的故事。它经常作为批评JavaEE的主要观点之一出现
故事的核心是,传统的JavaEE应用程序应该部署在“未解决的依赖项”中。这些依赖关系必须在应用服务器上得到满足,通常是由非开发人员通过使用某种GUI或控制台来满足
安全配置是这些未解析的依赖项之一
如果安全配置是在应用服务器上完成的,根据定义,这始终是不可移植的,例如,必须以特定于应用服务器的方式完成。它完全排除了使用应用程序域模型(例如JPA实体用户
)进行此身份验证
一些服务器(例如JBoss AS)允许从应用程序中配置其专有的安全机制,另外还允许从应用程序中加载“自定义登录模块”(几乎每台服务器的术语都不同)。通过一些小技巧,这将允许使用应用程序域模型和应用程序本身用于身份验证的相同数据源
最后,还有一种相对未知的从应用程序内部进行身份验证的可移植方法。这是通过JASPISPI完成的,也称为JASPI或JSR196。基本上,这个JASPIC似乎就是你想要的
不幸的是,JASPIC并不是完美的,尽管它是来自javaee6的一种技术,而我们几乎已经到了javaee7,但目前在各种应用服务器中对JASPIC的支持还很粗略。最重要的是,尽管JASPIC是标准化的,但应用服务器供应商仍然需要专有的配置才能使其真正工作
我写了一篇关于JASPIC的文章,更详细地解释了当前的问题:我通过简单地使用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>
所以我只需要实现一个Bean来验证和设置会话cookie。我将添加用户代理以增加安全性,但它基本上可以工作
我唯一的问题是无法重定向,因为它没有使用上下文路径,只是重定向到/index.xhtml而不是/my_app_context/index.xhtml,听起来有点奇怪。如果我在应用服务器中有身份验证,它就不再是可移植的了。如果我使用另一个应用服务器,我必须将整个用户库迁移到它上面或重新实现它。“我会看一看JASPIC,这可能对我有帮助,谢谢。”@Mikeptersen的确如此,但这是传统方法的想法。它以应用程序服务器为中心,而不是以应用程序为中心。其思想是在一台应用服务器上运行多个应用程序,它们都使用相同的身份验证。因此,它是在应用服务器上设置的。当然,如果你所做的只是运行一个具有自己身份验证的应用程序,那就没有意义了。所以,这要视情况而定。一种方法并不比另一种好,只是有不同的用例。如果你有更多的应用程序使用相同的用户群,Xou是正确的,这是有道理的。我认为对于web应用程序来说,具有不同身份验证的不同应用程序更为常见。为什么您要通过定制cookie来重新创建
HttpSession
?
@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);
}
}