2009-09-24 24 views
35

Tôi muốn thấy một ứng dụng đăng nhập đơn giản, không đơn giản như this.Bảo mật cơ bản trong JSF

Điều tôi muốn đạt được là hiểu biết về cách JSF hoạt động, tôi đã phát triển rất nhiều ASP.NET nơi bạn có mã phía sau và nơi bạn có thể kiểm tra xem phiên đã được tạo khi Đăng nhập hay chưa.

Một giải pháp tương tự trong JSF sẽ tuyệt vời.

này về cơ bản là những gì tôi muốn đạt được:

  • trang Login
  • NẾU OK
    • Tạo phiên và trở về "thành công"
  • NẾU KHÔNG ĐẠT
    • trả lại "lỗi"

(Các "thành công" và thất bại được ánh xạ tới faces-config.xml)

Tại sự thành công-page Tôi muốn trở thành Một số mà người dùng đang đăng nhập, vì vậy một không nên điều hướng đến "success.jspx" nếu bạn chưa có phiên chính xác.

+1

Related: http://stackoverflow.com/questions/2206911/best-way-for-user-authentication-on-javaee-6-using-jsf-2-0/2207147#2207147 Hoặc nếu bạn đang mở cho các thư viện của bên thứ ba như Shiro, sau đó http://balusc.blogspot.com/2013/01/apache-shiro-is-it-ready-for-java-ee-6.html – BalusC

Trả lời

44

Không có chức năng xác thực vốn có trong JSF lõi ngoài việc có thể sử dụng những thứ như thành phần rendered thuộc tính hướng tới bảo mật dựa trên vai trò.

Theo mặc định, một ứng dụng JSF dựa trên cùng một cơ chế bảo mật do container quản lý như thành phần web có chứa nó (JEE5 tutorial). Khung bên thứ ba như Seam có thể cung cấp các lựa chọn thay thế.

Nếu bạn muốn thêm bảo mật ứng dụng của riêng mình, servlet filter là một trong những cơ chế đơn giản hơn.

lọc này bảo vệ các nguồn tài nguyên dưới restricted thư mục theo quy định tại web.xml:

<filter> 
    <filter-name>AuthenticationFilter</filter-name> 
    <filter-class>restricted.AuthenticationFilter</filter-class> 
    </filter> 
    <filter-mapping> 
    <filter-name>AuthenticationFilter</filter-name> 
    <url-pattern>/restricted/*</url-pattern> 
    </filter-mapping> 

Việc thực hiện lớp lọc:

public class AuthenticationFilter implements Filter { 
    private FilterConfig config; 

    public void doFilter(ServletRequest req, ServletResponse resp, 
     FilterChain chain) throws IOException, ServletException { 
    if (((HttpServletRequest) req).getSession().getAttribute(
     AuthenticationBean.AUTH_KEY) == null) { 
     ((HttpServletResponse) resp).sendRedirect("../restricted_login.faces"); 
    } else { 
     chain.doFilter(req, resp); 
    } 
    } 

    public void init(FilterConfig config) throws ServletException { 
    this.config = config; 
    } 

    public void destroy() { 
    config = null; 
    } 
} 

Một bean đăng nhập quy định tại faces-config.xml:

public class AuthenticationBean { 
    public static final String AUTH_KEY = "app.user.name"; 

    private String name; 
    public String getName() { return name; } 
    public void setName(String name) { this.name = name; } 

    public boolean isLoggedIn() { 
    return FacesContext.getCurrentInstance().getExternalContext() 
     .getSessionMap().get(AUTH_KEY) != null; 
    } 

    public String login() { 
    FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(
     AUTH_KEY, name); 
    return "secret"; 
    } 

    public String logout() { 
    FacesContext.getCurrentInstance().getExternalContext().getSessionMap() 
     .remove(AUTH_KEY); 
    return null; 
    } 
} 

Biểu mẫu đăng nhập JSF trong th e restricted_login.jsp page:

<f:view> 
    <p><a href="restricted/secret.faces">try to go to secret 
    page</a></p> 
    <h:form> 
    Username: 
    <h:panelGroup rendered="#{not authenticationBean.loggedIn}"> 
     <h:inputText value="#{authenticationBean.name}" /> 
     <h:commandButton value="login" 
      action="#{authenticationBean.login}" /> 
     </h:panelGroup> 
     <h:commandButton value="logout" 
     action="#{authenticationBean.logout}" 
     rendered="#{authenticationBean.loggedIn}" /> 
    </h:form> 
    </f:view> 

(URL redirect/cơ chế đã được lựa chọn cho ngắn gọn hơn bất kỳ loại thực hành tốt nhất; xem Servlet API để biết thêm các tùy chọn.)

+0

bạn có thể làm rõ cách thức này khác với quản lý container được bảo mật? & làm thế nào để thích cái này hơn cái kia sau khi cân nhắc những ưu điểm/disadvntages của mỗi cái? –

+0

@ Marcos - thực sự xứng đáng là câu hỏi của riêng mình, có thể tham chiếu đến câu hỏi này. – McDowell

+0

Thực ra tôi đã đăng một cái gì đó tương tự ở đây: http: //stackoverflow.com/questions/7872265/protected-urls-leaking-unprotected-components-of-the-webapge-to-unauthenticated/7875236#7875236 –

4

Nếu bạn sẵn sàng thử cách tiếp cận nâng cao hơn một chút thì tôi khuyên bạn nên xem xét bảo mật mùa xuân + JSF. Nó hoạt động như một say mê.

Bạn có thể viết ứng dụng của mình như thể nó không được bảo mật và sau đó chỉ cần định cấu hình các khu vực cần được bảo vệ bằng các khía cạnh.

mùa xuân an ninh: http://static.springsource.org/spring-security/site/

A Hướng dẫn: http://ocpsoft.com/java/acegi-spring-security-jsf-login-page/

3

Cách tốt nhất để làm điều đó sẽ được sử dụng chứa được quản lý an ninh.

Here is a tutorial về cách đạt được điều đó với glassfishjsf.

2

Nếu bạn sử dụng mẫu, tôi thấy bạn không thực sự cần bộ lọc.

index.jsp

<jsp:forward page="startup.faces"></jsp:forward> 

startup.xhtml (.faces), không actualy cố gắng hiển thị một màn hình, nó Calles các startupSubmit javascript() vào tải và đó nhấp vào nút. Điều này sẽ gửi luồng thẳng tới phương thức start() trong StartupBean.java.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0  Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
. 
. 
<script type="text/javascript"> 
function startupSubmit() { 
    **document.getElementById('startupForm:startupBtn').click();** 
} 
</script> 
<h:body onload="startupSubmit()"> 
<h:form id="startupForm"> 
<p:commandButton id="startupBtn" value="" action="#{startupBean.start}" ajax="false" /> 
</h:form> 
</h:body> 
</html> 

StartupBean.java (không phải là một phần của template.xhtml bên dưới). Phương thức start() trong StartupBean đặt một biến có tên là true (nó mặc định là false), sau đó nhảy tới first.xhtml. Bạn có thể sử dụng bất kỳ tiêu chí nào bạn muốn xác định nếu được ủy quyền được đặt thành true ... chẳng hạn như tiêu chí đăng nhập.

package gov.irs.eservices.managementBeans; 

import javax.faces.bean.ManagedBean; 
import javax.faces.bean.SessionScoped; 

@ManagedBean(name="startupBean") 
@SessionScoped 
public class StartupBean { 

private boolean authorized; 

public StartupBean() { 
} 

public String start() { 
    **setAuthorized(true);** 
    return "first"; 
} 

public boolean isAuthorized() { 
    return authorized; 
} 

public void setAuthorized(boolean authorized) { 
    this.authorized = authorized; 
} 
} 

template.xhtml. Trong template.xhtml, ngay bên trong biểu mẫu, bạn đặt một h: hoặc p: panelGrid và chỉ hiển thị nó nếu startupBean.authorized là đúng. Cách duy nhất mà người dùng có thể truy cập vào các trang có trong mẫu là nếu họ đến qua StartupBean.java trước.

<f:view> 
<div id="container"> 
<h:form id="templateForm"> 
**<p:panelGrid rendered="#{startupBean.authorized}">** 
    <div id="header"> 
     <ui:include src="header.xhtml" /> 
    </div> 

    <div id="wrapper"> 
     <div id="firstId"> 
      <ui:insert name="first"></ui:insert> 
     </div> 
. 
. <!-- MORE PAGES --> 
. 
. 
    </div> 

    <div id="footer"> 
     <ui:include src="footer.xhtml" /> 
    </div> 
</p:panelGrid> 
</h:form> 
</div>  
</f:view> 

Vì vậy, đó là giải pháp của tôi. Tôi đã thử nghiệm nó khá kỹ lưỡng và nó có vẻ hoạt động tốt.

+0

The '@ManagedBean Thuộc tính '* name * trong' StartupBean' là không cần thiết vì nó sẽ được đặt tên theo mặc định. – rbento

Các vấn đề liên quan