根据用户角色渲染 JSF 组件

Posted

技术标签:

【中文标题】根据用户角色渲染 JSF 组件【英文标题】:Render JSF component based on user role 【发布时间】:2011-06-12 10:49:05 【问题描述】:

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

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

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

Glassfish V3.1,JSF 2.x

【问题讨论】:

以后请加[jsf-2.0]标签表示:) 【参考方案1】:

如果您的 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')"
Conditionally displaying JSF components Conditional rendering of non-JSF components (plain vanilla html and template text) JSF: How control access and rights in JSF?

【讨论】:

确实是 Servlet 3.0,但不知何故,在考试的所有这些大惊小怪中,我忘记了他们向 JSF 添加了方法调用......非常感谢 :) 这不是专门的 JSF,重要的是 EL(那些 # 的东西)。如果您在例如 Servlet 2.5(这意味着 JSP/EL 2.1)上运行 JSF 2.0,它将无法工作。它是在 JSP/EL 2.2 中引入的。 我已经使用 JDBC Realm 为每个用户定义了角色。但是上面的表达式总是为任何用户返回“false”。我需要添加一些其他的东西来使它工作吗?【参考方案2】:

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

    角色名称区分大小写。 rendered="#facesContext.externalContext.isUserInRole('ADMIN')" 可能会返回 false,但请尝试 rendered="#facesContext.externalContext.isUserInRole('admin')",或者渲染了="#facesContext.externalContext.isUserInRole('Admin')"。

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

下面是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中的角色,但都没有奏效。我需要两者,因为在正确的情况下指定角色名称。

【讨论】:

【参考方案3】:

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

例如rendered="#yoursessionbean.userRole == Roles.ADMIN"

【讨论】:

这是我最初的想法之一,但用户可以根据他的组拥有无限数量的角色。只有当用户只有一个角色时才会真正起作用...... @TC1 - 同意,那么如果有任何其他解决方案出现,您将不得不进行方法调用或等待。

以上是关于根据用户角色渲染 JSF 组件的主要内容,如果未能解决你的问题,请参考以下文章

如何渲染组件取决于角色

使用spring security进行身份验证后如何根据角色进行重定向[重复]

在反应中根据用户角色显示组件

根据用户角色隐藏一些 React 组件子项

相同的 URL 路径,但根据用户角色加载不同的组件 - Angular

JSF(容器管理安全)组角色