执行中的用户身份验证Java EE/JSF使用j_security_check来
-
18-09-2019 - |
题
我不知道是什么目前的做法是有关的用户认证网应用程序使用的JSF2.0(如果任何部件的确存在)和Java EE6个核心机制(登录/检查的权限/注销)与用户信息存在访问用户实体。Oracle Java EE教程是一个有点疏在本(仅处理servlet).
这个是 没有 使用一个整体的其他框架,就像春安全(acegi),或者缝,但试图坚守希望与新的Java EE6个平台(网profile),如果可能的。
解决方案
在网上搜索并尝试许多不同的方式后,这里是我建议的Java EE 6认证:
设置的安全域:
在我的情况,我在数据库中的用户。所以我跟着这个博客帖子创建JDBC领域,可以验证基于用户名和MD5哈希密码在我的数据库表的用户:
HTTP://blog.gamatam。 COM / 2009/11 / JDBC的境界-设置与 - 与GlassFish v3.html
注意:有关在数据库中的用户和组表中的交会谈。我有一个User类通过javax.persistence注释数据库映射一个UserType枚举属性。我配置有用于用户和组相同的表的境界,使用用户类型列作为组列和它工作得很好。
使用形式的验证:
不过按照上面的博客文章,配置,但而不是使用基本身份验证,使用形式(实际上,它不会不管你使用哪一个,但我最终使用FORM web.xml和sun-web.xml中)。使用标准的HTML,而不是JSF。
然后使用BalusC的顶端的上方上懒惰初始化从数据库中的用户信息。他建议做一个托管bean正从faces上下文的主体。我使用的,相反,有状态会话bean到为每个用户存储的会话信息,所以注入的会话上下文:
@Resource
private SessionContext sessionContext;
通过校长,我可以检查用户名,并使用EJB实体管理器,请从我SessionInformation
EJB的数据库和存储用户的信息。
注销:
我也环顾四周,注销的最佳途径。我发现,使用一个Servlet最好之一:
@WebServlet(name = "LogoutServlet", urlPatterns = {"/logout"})
public class LogoutServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession(false);
// Destroys the session for this user.
if (session != null)
session.invalidate();
// Redirects back to the initial page.
response.sendRedirect(request.getContextPath());
}
}
虽然我的答案是真的晚了考虑问题的日期,我希望这有助于从谷歌在这里结束了其他人,就像我一样。
侨,
维克托•Souza的
其他提示
我想你想 形式基于身份验证 使用 部署描述 和 j_security_check
.
你也可以做到这一点,在JSF通过仅仅使用相同的predefinied领域的名字 j_username
和 j_password
这表现在该教程。
E.g。
<form action="j_security_check" method="post">
<h:outputLabel for="j_username" value="Username" />
<h:inputText id="j_username" />
<br />
<h:outputLabel for="j_password" value="Password" />
<h:inputSecret id="j_password" />
<br />
<h:commandButton value="Login" />
</form>
你可以做懒装在 User
吸气,以检查是否 User
已登录在如果没有,然后检查 Principal
存在的请求,如果这样,那么得到的 User
关联 j_username
.
package com.stackoverflow.q2206911;
import java.io.IOException;
import java.security.Principal;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
@ManagedBean
@SessionScoped
public class Auth {
private User user; // The JPA entity.
@EJB
private UserService userService;
public User getUser() {
if (user == null) {
Principal principal = FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();
if (principal != null) {
user = userService.find(principal.getName()); // Find User by j_username.
}
}
return user;
}
}
的 User
显然可以在JSF通过EL #{auth.user}
.
注销做 HttpServletRequest#logout()
(并设置 User
为null!).你可以得到一个手柄 HttpServletRequest
在JSF的 ExternalContext#getRequest()
.你也只是无效的会议。
public String logout() {
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
return "login?faces-redirect=true";
}
对于剩余的(限定用户、角色和制约因素在部署描述和领域),只要按照Java EE6教程和servletcontainer文件通常的方式。
更新:你也可以使用的新Servlet3.0 HttpServletRequest#login()
要做到一个方案登录,而不是使用 j_security_check
这可能不是每个-se是可通过一个调度程序在一些servletcontainers.在这种情况下可以使用fullworthy JSF的形式和豆 username
和 password
性能和一个 login
方法看起来是这样的:
<h:form>
<h:outputLabel for="username" value="Username" />
<h:inputText id="username" value="#{auth.username}" required="true" />
<h:message for="username" />
<br />
<h:outputLabel for="password" value="Password" />
<h:inputSecret id="password" value="#{auth.password}" required="true" />
<h:message for="password" />
<br />
<h:commandButton value="Login" action="#{auth.login}" />
<h:messages globalOnly="true" />
</h:form>
和这个图范围内的管理豆还记得最初请求的网页:
@ManagedBean
@ViewScoped
public class Auth {
private String username;
private String password;
private String originalURL;
@PostConstruct
public void init() {
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
originalURL = (String) externalContext.getRequestMap().get(RequestDispatcher.FORWARD_REQUEST_URI);
if (originalURL == null) {
originalURL = externalContext.getRequestContextPath() + "/home.xhtml";
} else {
String originalQuery = (String) externalContext.getRequestMap().get(RequestDispatcher.FORWARD_QUERY_STRING);
if (originalQuery != null) {
originalURL += "?" + originalQuery;
}
}
}
@EJB
private UserService userService;
public void login() throws IOException {
FacesContext context = FacesContext.getCurrentInstance();
ExternalContext externalContext = context.getExternalContext();
HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
try {
request.login(username, password);
User user = userService.find(username, password);
externalContext.getSessionMap().put("user", user);
externalContext.redirect(originalURL);
} catch (ServletException e) {
// Handle unknown username/password in request.login().
context.addMessage(null, new FacesMessage("Unknown login"));
}
}
public void logout() throws IOException {
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
externalContext.invalidateSession();
externalContext.redirect(externalContext.getRequestContextPath() + "/login.xhtml");
}
// Getters/setters for username and password.
}
这种方式 User
可在JSF通过EL #{user}
.
应当提到的是一个选项,以完全离开认证的问题到前端控制器,例如Apache网络服务器和评估HttpServletRequest.getRemoteUser()代替,这对于REMOTE_USER环境变量的Java表示。这也使得复杂的日志中的设计,如Shibboleth的认证。过滤请求通过Web服务器Servlet容器是用于生产环境良好的设计,经常MOD_JK用于这样做。
在问题 HttpServletRequest.login不设置认证状态已被固定在3.0.1。 GlassFish的更新到最新版本,你就大功告成了。
更新是非常直接的:
glassfishv3/bin/pkg set-authority -P dev.glassfish.org
glassfishv3/bin/pkg image-update