Basic Security in JSF

前端 未结 4 702
你的背包
你的背包 2020-12-02 05:42

I would like to see a simple Login Application, not as simple as this though.

What I would like to achieve is an understanding on how JSF works, I\'ve developed a lo

相关标签:
4条回答
  • 2020-12-02 06:28

    There is no inherent authentication functionality in core JSF beyond being able to use things like component rendered attributes geared towards role-based security.

    By default, a JSF application relies on the same container-managed security mechanisms as the web component that contains it (JEE5 tutorial). 3rd party frameworks like Seam can provide alternatives.

    If you want to add your own application security, a servlet filter is one of the simpler mechanisms.

    This filter protects resources under the restricted directory as defined in 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>
    

    The filter class implementation:

    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;
      }
    }
    

    A login bean defined in 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;
      }
    }
    

    The JSF login form in the 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>
    

    (The redirect URL/mechanism was chosen for brevity rather than any sort of best practice; see the Servlet API for more options.)

    0 讨论(0)
  • 2020-12-02 06:34

    If you're willing to try a bit more advanced approach then I suggest looking into spring-security+JSF. It works like a charm.

    You can write your application as if it wasn't under security and then just configure which areas that should be protected using aspects.

    Spring security: http://static.springsource.org/spring-security/site/

    A Tutorial: http://ocpsoft.com/java/acegi-spring-security-jsf-login-page/

    0 讨论(0)
  • 2020-12-02 06:38

    The best way to do it would be to use container managed security.

    Here is a tutorial on how to achieve that with glassfish and jsf.

    0 讨论(0)
  • 2020-12-02 06:40

    If you use templates, I've found you don't really need a filter.

    index.jsp

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

    startup.xhtml (.faces), doesn't actualy try to show a screen, it calles the javascript startupSubmit() on load and that clicks the button. This sends the flow straight to the method start() in 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 (is not part of the template.xhtml below). The start() method in StartupBean sets a variable called authorized to true (it defaults to false), then jumps to first.xhtml. You can use any criteria you desire to determine if authorized is set to true... such as login criteria.

    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. In template.xhtml, just inside the form, you place a h: or p: panelGrid and only render it if startupBean.authorized is true. The only way a user can get to the pages contained in the template is if they come through StartupBean.java first.

    <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>
    

    So, that's my solution. I've tested it pretty thoroughly and it seems to work fine.

    0 讨论(0)
提交回复
热议问题