j_security_check를 사용하여 Java EE / JSF에서 사용자 인증 수행
JSF 2.0 (및 구성 요소가있는 경우)을 사용하는 웹 응용 프로그램의 사용자 인증과 JPA의 사용자 정보가있는 Java EE 6 핵심 메커니즘 (로그인 / 권한 확인 / 로그 아웃)에 대한 현재 접근 방식이 무엇인지 궁금합니다. 실재. Oracle Java EE 튜토리얼은 이것에 대해 조금 부족합니다 (서블릿 만 처리).
이것은 Spring-Security (acegi) 또는 Seam과 같은 다른 프레임 워크를 사용 하지 않지만 가능한 경우 새로운 Java EE 6 플랫폼 (웹 프로파일)을 고수하려고합니다.
웹을 검색하고 다양한 방법을 시도한 후 Java EE 6 인증에 대해 제안하는 내용은 다음과 같습니다.
보안 영역을 설정하십시오.
제 경우에는 데이터베이스에 사용자가있었습니다. 따라서이 블로그 게시물을 따라 데이터베이스 테이블의 사용자 이름 및 MD5 해시 암호를 기반으로 사용자를 인증 할 수있는 JDBC 영역을 만들었습니다.
http://blog.gamatam.com/2009/11/jdbc-realm-setup-with-glassfish-v3.html
참고 :이 게시물은 데이터베이스의 사용자 및 그룹 테이블에 대해 설명합니다. javax.persistence 주석을 통해 데이터베이스에 매핑 된 UserType enum 속성을 가진 User 클래스가 있습니다. userType 열을 그룹 열로 사용하여 사용자 및 그룹에 대해 동일한 테이블로 영역을 구성했으며 정상적으로 작동했습니다.
양식 인증 사용 :
여전히 위의 블로그 게시물을 따라 web.xml 및 sun-web.xml을 구성하지만 BASIC 인증을 사용하는 대신 FORM을 사용하십시오 (실제로 어떤 것을 사용하든 상관 없지만 FORM을 사용했습니다). 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에서 온 다른 사람들에게 도움이 되었기를 바랍니다.
챠오,
비 토르 수자
나는 당신이 원하는 가정 기반 인증을 구성 하여 배포 설명 과 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
(가) 있는지 확인하는 게터 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";
}
For the remnant (defining users, roles and constraints in deployment descriptor and realm), just follow the Java EE 6 tutorial and the servletcontainer documentation the usual way.
Update: you can also use the new Servlet 3.0 HttpServletRequest#login()
to do a programmatic login instead of using j_security_check
which may not per-se be reachable by a dispatcher in some servletcontainers. In this case you can use a fullworthy JSF form and a bean with username
and password
properties and a login
method which look like this:
<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>
And this view scoped managed bean which also remembers the initially requested page:
@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.
}
This way the User
is accessible in JSF EL by #{user}
.
It should be mentioned that it is an option to completely leave authentication issues to the front controller, e.g. an Apache Webserver and evaluate the HttpServletRequest.getRemoteUser() instead, which is the JAVA representation for the REMOTE_USER environment variable. This allows also sophisticated log in designs such as Shibboleth authentication. Filtering Requests to a servlet container through a web server is a good design for production environments, often mod_jk is used to do so.
The issue HttpServletRequest.login does not set authentication state in session has been fixed in 3.0.1. Update glassfish to the latest version and you're done.
Updating is quite straightforward:
glassfishv3/bin/pkg set-authority -P dev.glassfish.org
glassfishv3/bin/pkg image-update
'IT' 카테고리의 다른 글
통일이란 무엇입니까? (0) | 2020.06.07 |
---|---|
Perforce에서 작업 공간을 삭제하는 방법 (p4v 사용)? (0) | 2020.06.07 |
치명적인 오류 : 클래스에 구현되지 않은 초기화 프로그램 'init (coder :)'사용 (0) | 2020.06.07 |
Github : 업스트림 분기를 포크로 가져 오기 (0) | 2020.06.07 |
C #에 매개 변수 제약 조건이있는 일반 생성자가 있습니까? (0) | 2020.06.07 |