我不知道是什么目前的做法是有关的用户认证网应用程序使用的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_usernamej_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的形式和豆 usernamepassword 性能和一个 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用于这样做。

scroll top