Java EE 5 编程式身份验证
如何通过 JSF 操作(或在 servlet doGet
/doPost
方法中)对用户进行身份验证? 我的意思是:
Authenticator auth = ...;
if (!auth.authenticate("user","password"))
{
FacesContext.getInstance().addMessage("Incorrect username or password", null);
}
限制:
- 此方法必须与容器管理的安全性兼容。 (即“HttpServletRequest.getRemoteUser()”必须返回经过身份验证的用户)
- 此方法必须在任何地方都有效(即在每个应用程序服务器上)。
不使用 j_security_check
或其他 J2EE 身份验证类型(BASIC、DIGEST 等...)
有可能吗?
或者如何以这种方式创建验证码?
验证登录名和密码不为空?
当然,在单页上并且没有 JavaScript...
类似的问题...但没有回答这个问题:
JSF认证与授权
在 Java EE / JSF 中执行用户身份验证使用 j_security_check
编辑 1:
我的意思是 servet API 至少 2.3。 是的,我在 Servlet API 3.0 中读到过有关 login
的内容,但只有新版本的应用程序服务器才支持它。
我认为这里可以有一些解决方案来为每个应用程序服务器实现这种身份验证。 有时通过一些技巧,有时通过为此目的设计的特殊类。 像这样:
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;
}
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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
啊,这是
J2EE 1.3Java EE 5。太糟糕了,每当您想要继续使用容器管理的安全性时,您就运气不佳。您必须从幕后获取容器特定的实现。顺便说一句,“没有j_security_check
或 BASIC/DIGEST 的容器管理安全性”是自相矛盾的。我个人会忘记这一切并自行发展安全性或获取更可配置的第三方实现,例如 Spring 安全。Ah, it's
J2EE 1.3Java 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 withoutj_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.编程登录非常棘手,并且似乎因应用程序服务器而异。我相信使用 j_security_check 是最成功的,并且将允许您的应用程序跨各种应用程序服务器工作。
困难的部分是让应用程序服务器接受身份验证。在 Tomcat 上,我已经能够执行 myLoginModule.login() 并使登录模块成功,但用户未通过容器进行身份验证。 JBoss 有一些代码可以让程序化身份验证在 JBoss 和 Tomcat 之间工作(因为 Tomcat 位于 JBoss 中)。通过研究 Glassfish,我得到的印象是编程登录非常困难,应该留给专业人士。
Glassfish 文档 (http://docs.sun.com/app/docs/doc/820-4496/beacm?a=view) 说:
编辑
j_security_check 方法需要一些时间来适应,但是一旦您学会解决它,就会非常成功。基本上,您可以有一个欢迎页面,将用户重定向到您的应用程序;如果用户尚未登录,他们将被发送到您的登录页面。您的登录页面可以是您网站的主页。进入主页后,用户可以导航到站点的其他“不安全”页面。如果您愿意,您也可以在这些页面上包含登录表单。您不会被单一的登录页面所困扰。
编辑 2
我一直在使用 AJAX(通过 Richfaces)来检查用户的用户名/密码,并在需要时显示错误消息。如果凭据正确,则提交指向 j_security_check 的表单以进行实际身份验证。
编辑3
BalusC在第二个链接问题上建议的编程登录方法(http://stackoverflow.com/questions/2206911/best-way-for-user-authentication-on-javaee-6- using-jsf-2-0) 执行
request.login(...)
看起来很棒。我很快就会尝试一下;o) Glassfish 3 支持 Servlet 3,但还没有其他支持(将成为 Tomcat 7 的一部分,可能是 JBoss 6)。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:
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).