基于用户角色渲染JSF组件

时间:2011-01-20 12:51:31

标签: jsf jsf-2

如何根据登录用户的角色呈现JSF组件?我知道外部上下文暴露了主体,但是我应该如何在JSF中正确地进行呈现?在JSP中,它将类似于

<% isUserInRole(Roles.ADMIN) { %>
<button>Edit!</button>
<% } %>

如何以最佳方式在JSF中编写此代码?我最好的猜测是渲染属性绑定到一个返回布尔值的支持bean的方法,但如果我必须只为管理员渲染一些导航项,那将引入一个无关的支持bean ...

Glassfish V3.1,JSF 2.x

3 个答案:

答案 0 :(得分:34)

如果您的web.xml被声明为Servlet 3.0(隐含地与JSP / EL 2.2相关)

<?xml version="1.0" encoding="UTF-8"?>
<web-app 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
    version="3.0">

那么你可以利用能够在EL中调用带有参数的方法,如ExternalContext#isUserInRole()

rendered="#{facesContext.externalContext.isUserInRole('ADMIN')}"

请注意,这需要一个支持Servlet 3.0的容器,但由于您使用的是Glassfish 3(支持Servlet 3.0),因此它应该没有任何问题。

另请注意,如果您使用的是Facelets而不是JSP,那么EL中的HttpServletRequest可用作#{request},可以使用以下较短的表达式:

rendered="#{request.isUserInRole('ADMIN')}"

答案 1 :(得分:5)

在回复@wasimbhalli时,有两个原因我发现表达式总是返回false:

  1. 角色名称区分大小写。 rendered="#{facesContext.externalContext.isUserInRole('ADMIN')}"可能会返回false,但请尝试 rendered="#{facesContext.externalContext.isUserInRole('admin')}",或呈现=“#{facesContext.externalContext.isUserInRole('Admin')}”。

  2. 您必须在web.xml(或作为注释)中定义角色,并将其映射到glassfish-web.xml

  3. 以下是如何在web.ml

    中指定角色
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns="http://java.sun.com/xml/ns/javaee"
             xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
      <security-role>
        <role-name>admin</role-name>
      </security-role>
    </web-app>
    

    以下是如何将身份验证组映射到glassfish-web.xml中的角色。

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
    <glassfish-web-app>
      <security-role-mapping>
        <role-name>admin</role-name> <!-- name defined in web.xml or annotations -->
        <group-name>admin</group-name><!-- name from authentication mechanism -->
      </security-role-mapping>
    </glassfish-web-app>
    

    在我的测试中,即使名称相同,也必须进行映射,就像我在示例代码中所示。同样在我的测试中,我尝试仅定义映射并仅在web.xml中定义角色,但两者都没有效果。我需要两个,因为在正确的情况下指定角色名称。

答案 2 :(得分:0)

将角色存储在会话属性中,并使用渲染属性进行比较。

e.g。 rendered="#{yoursessionbean.userRole == Roles.ADMIN}"