문제

JSF 2.0 (및 구성 요소가있는 경우)을 사용하여 웹 애플리케이션에 대한 사용자 인증에 대한 현재 접근 방식이 무엇인지 궁금합니다. 실재. Oracle Java EE 튜토리얼은 이것에 대해 약간 드문 일입니다 (서블릿 만 핸들링).

이것은 없이 스프링 보안 (ACEGI) 또는 이음새와 같은 완전히 다른 프레임 워크를 사용하지만 가능한 경우 새로운 Java EE 6 플랫폼 (웹 프로파일)과 함께 희망적으로 고수하려고합니다.

도움이 되었습니까?

해결책

웹을 검색하고 여러 가지 방법을 시도한 후 Java EE 6 인증에 대해 제안한 내용은 다음과 같습니다.

보안 영역 설정 :

제 경우에는 데이터베이스에 사용자가있었습니다. 그래서이 블로그 게시물을 따라 데이터베이스 테이블에서 사용자 이름과 MD5 하시트 암호를 기반으로 사용자를 인증 할 수있는 JDBC 영역을 만듭니다.

http://blog.gamatam.com/2009/11/jdbc-realm-setup-with-glassfish-v3.html

참고 : 게시물은 데이터베이스의 사용자 및 그룹 테이블에 대해 이야기합니다. 데이터베이스에 javax.persistence annotations를 통해 맵핑 된 사용자 유형 열거 속성이있는 사용자 클래스가있었습니다. 사용자 유형 열을 그룹 열로 사용하여 사용자 및 그룹에 대해 동일한 테이블로 영역을 구성했으며 잘 작동했습니다.

양식 인증 사용 :

위의 블로그 게시물을 따르기 위해 web.xml 및 sun-web.xml을 구성하지만 기본 인증을 사용하는 대신 양식을 사용합니다 (실제로 사용하는 것이 중요하지 않지만 양식을 사용했습니다). JSF가 아닌 표준 HTML을 사용하십시오.

그런 다음 데이터베이스에서 사용자 정보를 초기화하는 게으른 위의 Balusc의 팁을 사용하십시오. 그는 얼굴 맥락에서 교장을 얻는 관리하는 콩으로 그것을 제안했습니다. 대신 각 사용자에 대한 세션 정보를 저장하기 위해 상태가 많은 세션 Bean을 사용 했으므로 세션 컨텍스트를 주입했습니다.

 @Resource
 private SessionContext sessionContext;

교장과 함께 사용자 이름을 확인하고 EJB Entity Manager를 사용하여 데이터베이스에서 사용자 정보를 가져 와서 내 SessionInformation EJB.

로그 아웃:

또한 로그 아웃하는 가장 좋은 방법을 둘러 보았습니다. 내가 찾은 가장 좋은 것은 서블릿을 사용하는 것입니다.

 @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());
  }
 }

내 대답은 질문의 날짜를 고려할 때 정말 늦었지만, 이것이 내가 한 것처럼 Google에서 여기에있는 다른 사람들이 도움이되기를 바랍니다.

ciao,

Vítor Souza

다른 팁

나는 당신이 원한다고 생각합니다 양식 기반 인증 사용 배포 설명 자 그리고 j_security_check.

동일한 사전 정의 필드 이름 만 사용하여 JSF 에서이 작업을 수행 할 수 있습니다. j_username 그리고 j_password 튜토리얼에서 보여 주듯이.

예를 들어

<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 Getter가 있는지 확인하십시오 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}.

로그 아웃하려면 a HttpServletRequest#logout() (그리고 설정 User null!). 당신은 손잡이를 얻을 수 있습니다 HttpServletRequest JSF에서 ExternalContext#getRequest(). 또한 세션을 완전히 무효화 할 수 있습니다.

public String logout() {
    FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
    return "login?faces-redirect=true";
}

Remnant (배포 디스크립터 및 영역의 사용자, 역할 및 제약 조건을 정의 함)의 경우 Java EE 6 자습서와 ServletContainer 문서를 일반적인 방법으로 따르십시오.


업데이트: 새로운 서블릿 3.0을 사용할 수도 있습니다 HttpServletRequest#login() 사용하는 대신 프로그래밍 방식 로그인을 수행합니다 j_security_check 일부 ServletContainers의 디스패처에 의해 파견 할 수 없을 수 있습니다. 이 경우 완전한 JSF 양식과 콩을 사용할 수 있습니다. username 그리고 password 속성 및 a 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 웹 서버 (Apache Webserver)와 예를 들어 인증 문제를 전면 컨트롤러에 완전히 남겨두고 httpservletrequest.getRemoteUser ()를 대신 remote_user 환경 변수의 Java 표현 인 옵션이라고 언급해야합니다. 이를 통해 Shibboleth 인증과 같은 정교한 로그인 설계도 가능합니다. 웹 서버를 통해 서블릿 컨테이너에 대한 요청을 필터링하는 것은 생산 환경에 좋은 설계이며 종종 mod_jk는 그렇게하는 데 사용됩니다.

문제 httpservletrequest.login은 세션에서 인증 상태를 설정하지 않습니다 3.0.1에서 고정되었습니다. Glassfish를 최신 버전으로 업데이트하면 완료됩니다.

업데이트는 매우 간단합니다.

glassfishv3/bin/pkg set-authority -P dev.glassfish.org
glassfishv3/bin/pkg image-update
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top